コード例 #1
0
ファイル: insertconns.py プロジェクト: jameshanlon/tool_sire
 def create_single_conn(s, chan, scope, i_elem, elem):
     debug(self.debug, 'New connection for index {}'.format(elem.index))
     master = tab.lookup_is_master(chan, elem, scope)
     if master:
         location = ast.ExprSingle(
             ast.ElemNumber(
                 tab.lookup_slave_location(chan.name, elem.index,
                                           scope)))
     else:
         location = ast.ExprSingle(
             ast.ElemNumber(
                 tab.lookup_master_location(chan.name, elem.index,
                                            scope)))
     chanend = ast.ElemId(chan.chanend)
     chanend.symbol = Symbol(chan.chanend,
                             self.chanend_type(chan),
                             None,
                             scope=T_SCOPE_PROC)
     connid = tab.lookup_connid(chan.name, elem.index, scope)
     chanid = ast.ExprSingle(ast.ElemNumber(connid))
     cond = ast.ExprBinop(
         '=', i_elem,
         ast.ExprSingle(ast.ElemNumber(elem.indices_value)))
     conn = ast.StmtConnect(chanend, chanid, location,
                            self.connect_type(chan, master))
     return ast.StmtIf(cond, conn, s) if s != None else conn
コード例 #2
0
ファイル: insertconns.py プロジェクト: jameshanlon/tool_sire
        def create_range_conn(s, chan, i_elem, group):
            diff2 = group[0]
            elem0 = group[1][0][0]
            offset = target_loc(chan, elem0, scope)

            # Form the location expression
            if elem0.indices_value > 0:
                location = ast.ElemGroup(
                    ast.ExprBinop(
                        '-', i_elem,
                        ast.ExprSingle(ast.ElemNumber(elem0.indices_value))))
            else:
                location = i_elem
            location = ast.ExprBinop('*', ast.ElemNumber(diff2 + 1),
                                     ast.ExprSingle(location))
            location = ast.ExprBinop('+', ast.ElemGroup(location),
                                     ast.ExprSingle(ast.ElemNumber(offset)))

            chanend = ast.ElemId(chan.chanend)
            chanend.symbol = Symbol(chan.chanend,
                                    self.chanend_type(chan),
                                    None,
                                    scope=T_SCOPE_PROC)
            connid = tab.lookup_connid(chan.name, elem0.index, scope)
            chanid = ast.ExprSingle(ast.ElemNumber(connid))
            begin = elem0.indices_value
            end = group[1][-1][0].indices_value
            cond = ast.ExprBinop(
                '>=', i_elem, ast.ExprSingle(ast.ElemNumber(min(begin, end))))
            master = tab.lookup_is_master(chan, elem0, scope)
            conn = ast.StmtConnect(chanend, chanid, location,
                                   self.connect_type(chan, master))
            return ast.StmtIf(cond, conn, s) if s else conn
コード例 #3
0
ファイル: insertconns.py プロジェクト: jameshanlon/tool_sire
 def create_tree_conn(tab, scope, chan, phase, group_size,
                      base_indices_value, loc_base, loc_diff,
                      connid_min, connid_offset, connid_diff, i_elem):
     location = ast.ExprBinop(
         '-', i_elem,
         ast.ExprSingle(ast.ElemNumber(base_indices_value)))
     location = ast.ExprBinop(
         '/', ast.ElemGroup(location),
         ast.ExprSingle(ast.ElemNumber(group_size)))
     location = ast.ExprBinop('*', ast.ElemNumber(loc_diff),
                              ast.ExprSingle(ast.ElemGroup(location)))
     location = ast.ExprBinop('+', ast.ElemNumber(loc_base),
                              ast.ExprSingle(ast.ElemGroup(location)))
     chanend = ast.ElemId(chan.chanend)
     chanend.symbol = Symbol(chan.chanend,
                             self.chanend_type(chan),
                             None,
                             scope=T_SCOPE_PROC)
     elem0 = chan.elems[phase]
     #connid = ast.ExprBinop('+', i_elem,
     #    ast.ExprSingle(ast.ElemNumber(connid_offset)))
     connid = ast.ExprBinop('-', i_elem,
                            ast.ExprSingle(ast.ElemNumber(phase)))
     connid = ast.ExprBinop('rem', ast.ElemGroup(connid),
                            ast.ExprSingle(ast.ElemNumber(group_size)))
     connid = ast.ExprBinop('*', ast.ElemGroup(connid),
                            ast.ExprSingle(ast.ElemNumber(connid_diff)))
     connid = ast.ExprBinop('+', ast.ElemGroup(connid),
                            ast.ExprSingle(ast.ElemNumber(connid_min)))
     master = tab.lookup_is_master(chan, elem0, scope)
     return ast.StmtConnect(chanend, connid, location,
                            self.connect_type(chan, master))
コード例 #4
0
ファイル: formlocation.py プロジェクト: jameshanlon/tool_sire
def form_location(sym, base, offset, compression):
    """
  Given the base id (ElemId), offset (Expr) and compression ratio (integer),
  produce an expression for a location::

    location = (base + (off/comp)) rem NUM_CORES
  """
    assert isinstance(base, ast.Elem) or isinstance(base, ast.Expr)
    assert isinstance(offset, ast.Expr)

    if isinstance(base, ast.Expr):
        base = ast.ElemGroup(base)

    # Offset
    loc = offset

    # Apply compression
    #if compression > 1:
    #  loc = ast.ExprBinop('/', ast.ElemGroup(loc),
    #      ast.ExprSingle(ast.ElemNumber(compression)))

    #elem_numcores = ast.ElemId(SYS_NUM_CORES_CONST)
    #elem_numcores.symbol = sym.lookup(SYS_NUM_CORES_CONST)

    # Apply 'rem NUM_CORES' to base + (off/comp)
    loc = ast.ExprSingle(
        ast.ElemGroup(
            ast.ExprBinop('+', base, ast.ExprSingle(ast.ElemGroup(loc)))))
    #ast.ExprBinop('rem', ast.ExprSingle(elem_numcores))

    v = EvalExpr().expr(loc)
    loc = loc if v == None else ast.ExprSingle(ast.ElemNumber(v))

    return loc
コード例 #5
0
    def subscript_channel(self, indices, tab, stmt, name, expr, chanend,
                          chan_set):
        """
    Expand the use of a channel subscript over a set of iterators and determine
    for each the value of its index and location, and then add this to the
    channel table and corresponding expansion.
    """
        #print(Printer().expr(stmt.location))
        chan_elems = []

        # Iterate over cartesian product of iterator ranges
        ranges = [
            range(x.base_value, x.base_value + x.count_value) for x in indices
        ]
        for x in product(*ranges):

            # Deep copy expressions so we can modify them
            index_expr = copy.deepcopy(expr)
            location_expr = copy.deepcopy(stmt.location)

            # Substitute index variables for values
            index_values = []
            for (y, z) in zip(indices, x):
                index_expr.accept(
                    SubElem(ast.ElemId(y.name), ast.ElemNumber(z)))
                location_expr.accept(
                    SubElem(ast.ElemId(y.name),
                            ast.ElemNumber(z - y.base_value)))
                index_values.append(z)

            # Evaluate the expressions
            index_value = EvalExpr().expr(index_expr)
            location_value = EvalExpr().expr(location_expr)

            # Add to the table
            tab.insert(name, index_value, location_value, chanend, chan_set)

            # Add the expanded channel use to a list
            chan_elems.append(
                ChanElem(index_value, location_value, indices, index_values))

            debug(
                self.debug,
                '  {}[{}] at {} (chanend {})'.format(name, index_value,
                                                     location_value, chanend))

        return chan_elems
コード例 #6
0
    def single_channel(self, indices, tab, stmt, name, chanend, chan_set):
        """
    Process a single (non-subscripted) channel use by evaluating its location
    and then adding it to the channel table and returning it as an element.
    Single channels may appear only in replicators in the client process of a
    server, hence we evaluate their location over the incident indices.
    """
        #print(Printer().expr(stmt.location))
        if indices:
            elem = ChanElem(None, None, None, None)

            # Iterate over cartesian product of iterator ranges
            ranges = [
                range(x.base_value, x.base_value + x.count_value)
                for x in indices
            ]
            for x in product(*ranges):

                # Deep copy expressions so we can modify them
                location_expr = copy.deepcopy(stmt.location)

                # Substitute index variables for values
                index_values = []
                for (y, z) in zip(indices, x):
                    location_expr.accept(
                        SubElem(ast.ElemId(y.name),
                                ast.ElemNumber(z - y.base_value)))

                # Evaluate the expressions
                location_value = EvalExpr().expr(location_expr)

                # Add to the table
                tab.insert(name, None, location_value, chanend, chan_set)

                # Add the location to the channel element
                elem.add_location(location_value)

                debug(
                    self.debug,
                    '  {} at {} (chanend {})'.format(name, location_value,
                                                     chanend))

            elem.location = elem.locations[0]
            return [elem]

        else:
            location_value = EvalExpr().expr(stmt.location)
            tab.insert(name, None, location_value, chanend, chan_set)
            debug(
                self.debug,
                ' {} at {} (chanend {})'.format(name, location_value, chanend))
            return [ChanElem(None, location_value, None, None)]
コード例 #7
0
ファイル: insertconns.py プロジェクト: jameshanlon/tool_sire
 def gen_single_conn(self, tab, scope, chan):
     """
 Generate a connection for a single channel declaration. 'chan' is a
 ChanElemSet with one element.
 """
     elem = chan.elems[0]
     chanend = ast.ElemId(chan.chanend)
     chanend.symbol = Symbol(chan.chanend,
                             self.chanend_type(chan),
                             None,
                             scope=T_SCOPE_PROC)
     connid = tab.lookup_connid(chan.name, elem.index, scope)
     chanid = ast.ExprSingle(ast.ElemNumber(connid))
     # Server-end connections don't need targets
     if chan.symbol.scope == T_SCOPE_SERVER:
         return ast.StmtConnect(chanend, chanid,
                                ast.ExprSingle(ast.ElemNumber(0)),
                                self.connect_type(chan, False))
     # All other connections do
     else:
         master = tab.lookup_is_master(chan, elem, scope)
         if master:
             location = ast.ExprSingle(
                 ast.ElemNumber(
                     tab.lookup_slave_location(chan.name, elem.index,
                                               scope)))
         else:
             location = ast.ExprSingle(
                 ast.ElemNumber(
                     tab.lookup_master_location(chan.name, elem.index,
                                                scope)))
         chanend = ast.ElemId(chan.chanend)
         chanend.symbol = Symbol(chan.chanend,
                                 self.chanend_type(chan),
                                 None,
                                 scope=T_SCOPE_PROC)
         return ast.StmtConnect(chanend, chanid, location,
                                self.connect_type(chan, master))
コード例 #8
0
def indices_expr(indices):
    """
  Given a set of indices, return an expression computing their combined value.
  """
    dims = [x.count_value for x in indices]
    r = None
    for (i, x) in enumerate(indices):
        c = reduce(lambda x, y: x * y, dims[i + 1:], 1)
        c_expr = ast.ExprSingle(ast.ElemNumber(c))
        eid = ast.ElemId(x.name)
        eid.symbol = Symbol(x.name, T_VAL_SINGLE, None, scope=T_SCOPE_PROC)
        e = ast.ExprBinop('*', eid, c_expr) if c > 1 else ast.ExprSingle(eid)
        r = e if r == None else ast.ExprBinop('+', ast.ElemGroup(r), e)
    return r
コード例 #9
0
 def stmt_server(self, node, parent, d):
     """
 For server statements the server and client processes are overlaid.
 """
     if node.distribute:
         debug(self.debug, 'd before server = {}'.format(d))
         e = self.stmt(node.server, parent, d)
         debug(self.debug, 'd after server = {}'.format(e))
         node.client = ast.StmtOn(ast.ExprSingle(ast.ElemNumber(d)),
                                  node.client)
         e += self.stmt(node.client, parent, d)
         debug(self.debug, 'd after client = {}'.format(e))
         node.distribute = False
         return e
     else:
         debug(self.debug, 'd before server = {}'.format(d))
         x = self.stmt(node.server, parent, d)
         debug(self.debug, 'd after server = {}'.format(x))
         y = self.stmt(node.client, parent, d)
         debug(self.debug, 'd after client = {}'.format(y))
     return max(x, y)
コード例 #10
0
 def stmt_par(self, node, parent, d):
     """
 For processes in parallel composition, add 'on' prefixes to provide simple
 compile-time distribution. If any process is already prefixed with an 'on',
 then do not add any (this is mainly for the test cases).
 """
     if node.distribute:
         if any([isinstance(x, ast.StmtOn) for x in node.stmt]):
             self.errorlog.report_error(
                 "parallel composition contains 'on's")
             return 0
         e = self.stmt(node.stmt[0], parent, d)
         debug(self.debug, 'd before par = {}'.format(d))
         for (i, x) in enumerate(node.stmt[1:]):
             node.stmt[i + 1] = ast.StmtOn(
                 ast.ExprSingle(ast.ElemNumber(d + e)), x)
             e += self.stmt(x, parent, d + e)
         debug(self.debug, 'd after par = {}'.format(d))
         node.distribute = False
         return e
     else:
         return 0
コード例 #11
0
ファイル: labelprocs.py プロジェクト: jameshanlon/tool_sire
 def stmt_on(self, node, l):
     node.location = l
     # Try and evaluate this 'target' expression
     v = EvalExpr().expr(node.expr)
     k = ast.ExprSingle(ast.ElemNumber(v)) if v != None else l
     self.stmt(node.stmt, k)
コード例 #12
0
ファイル: labelprocs.py プロジェクト: jameshanlon/tool_sire
 def defn(self, node):
     node.location = ast.ElemNumber(0)
     if node.name == 'main':
         self.stmt(node.stmt, ast.ExprSingle(node.location))
     else:
         self.stmt(node.stmt, ast.ExprSingle(node.location))
コード例 #13
0
    def distribute_stmt(self, m, elem_t, elem_n, elem_m, base, indices,
                        proc_actuals, formals, pcall):
        """
    Create the distribution process body statement.
    """

        # Setup some useful expressions
        name = self.sig.unique_process_name()
        elem_x = ast.ElemId('_x')
        expr_x = ast.ExprSingle(elem_x)
        expr_t = ast.ExprSingle(elem_t)
        expr_n = ast.ExprSingle(elem_n)
        expr_m = ast.ExprSingle(elem_m)
        elem_base = ast.ElemNumber(base)
        expr_base = ast.ExprSingle(elem_base)

        # Replace ocurrances of index variables i with i = f(_t)
        divisor = m
        for x in indices:
            divisor = floor(divisor / x.count_value)
            # Calculate the index i as a function of _t and the dimensions.
            e = ast.ExprBinop(
                'rem',
                ast.ElemGroup(
                    ast.ExprBinop('/', elem_t,
                                  ast.ExprSingle(ast.ElemNumber(divisor)))),
                ast.ExprSingle(ast.ElemNumber(x.count_value)))
            if x.base_value > 0:
                e = ast.ExprBinop('+', ast.ElemNumber(x.base_value),
                                  ast.ExprSingle(ast.ElemGroup(e)))
            # Then replace it for each ocurrance of i
            for y in pcall.args:
                y.accept(SubElem(ast.ElemId(x.name), ast.ElemGroup(e)))

        d = ast.ExprBinop('+', elem_t, ast.ExprSingle(elem_x))
        d = form_location(self.sym, elem_base, d, 1)

        # Create on the on statement
        on_stmt = ast.StmtOn(
            d,
            ast.StmtPcall(name, [
                ast.ExprBinop('+', elem_t, ast.ExprSingle(elem_x)), expr_x,
                ast.ExprBinop('-', elem_m, ast.ExprSingle(elem_x))
            ] + proc_actuals))
        on_stmt.location = None

        # Conditionally recurse {d()|d()} or d()
        s1 = ast.StmtIf(
            # if m > n/2
            ast.ExprBinop('>', elem_m, ast.ExprSingle(elem_x)),
            # then
            ast.StmtPar(
                [],
                [
                    # on id()+t+n/2 do d(t+n/2, n/2, m-n/2, ...)
                    on_stmt,
                    # d(t, n/2, n/2)
                    ast.StmtPcall(name,
                                  [expr_t, expr_x, expr_x] + proc_actuals),
                ],
                False),
            # else d(t, n/2, m)
            ast.StmtPcall(name, [expr_t, expr_x, expr_m] + proc_actuals))

        # _x = n/2 ; s1
        n_div_2 = ast.ExprBinop('>>', elem_n,
                                ast.ExprSingle(ast.ElemNumber(1)))
        s2 = ast.StmtSeq([], [ast.StmtAss(elem_x, n_div_2), s1])

        # if n = 1 then process() else s1
        s3 = ast.StmtIf(
            ast.ExprBinop('=', elem_n, ast.ExprSingle(ast.ElemNumber(1))),
            pcall, s2)

        # Create the local declarations
        decls = [ast.VarDecl(elem_x.name, T_VAR_SINGLE, None)]

        s4 = ast.StmtSeq(decls, [s3])

        # Create the definition
        d = ast.ProcDef(name, T_PROC, formals, s4)

        return d
コード例 #14
0
    def transform_rep(self, stmt):
        """
    Convert a replicated parallel statement into a divide-and-conquer form.
     - Return the tuple (process-def, process-call)
    We only allow replicators where their location is known; i.e. stmt.location
    is an Expr(Number(x)).
    """
        assert isinstance(stmt, ast.StmtRep)
        assert isinstance(stmt.stmt, ast.StmtPcall)
        assert isinstance(stmt.location, ast.ExprSingle)
        assert isinstance(stmt.location.elem, ast.ElemNumber)
        pcall = stmt.stmt

        # The context of the procedure call is each variable occurance in the
        # set of arguments.
        context = FreeVars().compute(pcall)

        assert not stmt.m == None
        #assert not stmt.f == None
        n = util.next_power_of_2(stmt.m)

        # Create new variables
        formals = []  # Formals for the new distribution process
        actuals = []  # Actuals for the new distribution process
        proc_actuals = []  # All other live-in variables
        elem_t = ast.ElemId('_t')  # Interval base
        elem_n = ast.ElemId('_n')  # Interval width
        elem_m = ast.ElemId('_m')  # Processes in interval
        #print(Printer().expr(stmt.location))
        base = stmt.location.elem.value

        # Populate the distribution and replicator indices
        formals.append(ast.Param('_t', T_VAL_SINGLE, None))
        formals.append(ast.Param('_n', T_VAL_SINGLE, None))
        formals.append(ast.Param('_m', T_VAL_SINGLE, None))
        actuals.append(ast.ExprSingle(ast.ElemNumber(0)))
        actuals.append(ast.ExprSingle(ast.ElemNumber(n)))
        actuals.append(ast.ExprSingle(ast.ElemNumber(stmt.m)))

        # For each non-index free-variable of the process call
        for x in context - set([x for x in stmt.indices]):

            # Add each unique variable ocurrance from context as a formal param
            formals.append(
                ast.Param(x.name, rep_var_to_param[x.symbol.type],
                          x.symbol.expr))

            # If the actual is an array subscript or slice, we only pass the id.
            if isinstance(x, ast.ElemSlice) or isinstance(x, ast.ElemSub):
                e = ast.ElemId(x.name)
                e.symbol = x.symbol
                proc_actuals.append(ast.ExprSingle(e))
            else:
                proc_actuals.append(ast.ExprSingle(copy.copy(x)))

        # Add the extra actual params to the distribution actuals
        actuals.extend(proc_actuals)

        # Create the process definition and perform semantic analysis to
        # update symbol bindings.
        d = self.distribute_stmt(stmt.m, elem_t, elem_n, elem_m, base,
                                 stmt.indices, proc_actuals, formals, pcall)
        #Printer().defn(d, 0)
        self.sem.defn(d)

        # Create the corresponding call.
        c = ast.StmtPcall(d.name, actuals)
        self.sig.insert(d.type, d)
        return (d, c)
コード例 #15
0
 def p_elem_number(self, p):
   '''elem : HEXLITERAL
           | DECLITERAL
           | BINLITERAL'''
   p[0] = ast.ElemNumber(p[1], self.coord(p))