Пример #1
0
def init_routing_vars(cgra : MRRG, design : Design, vars : Modeler, solver : Solver) -> Term:
    bv1 = solver.BitVec(1)
    for node in cgra.all_nodes:
        for value in design.values:
            vars.init_var((node, value), bv1)
            for dst in value.dsts:
                vars.init_var((node, value, dst), bv1)
    return solver.TheoryConst(solver.Bool(), True)
Пример #2
0
def pe_exclusivity(cgra : MRRG, design : Design, vars : Modeler, solver : Solver) -> Term:
    ''' Assert all PEs are used at most one time '''
    bv = solver.BitVec(len(design.operations))
    c = []
    for pe in cgra.functional_units:
        pe_vars = vars.anonymous_var(bv)
        for idx, op in enumerate(design.operations):
            c.append(pe_vars[idx] == vars[pe, op])
        c.append(_is_one_hot_or_0(pe_vars, solver))

    return solver.And(c)
Пример #3
0
def op_placement(cgra : MRRG, design : Design, vars : Modeler, solver : Solver) -> Term:
    ''' Assert all ops are placed exactly one time
    unless they can be duplicated in which case assert they are placed '''
    bv = solver.BitVec(len(cgra.functional_units))
    c = []
    for op in design.operations:
        if op.duplicate:
            c.append(ft.reduce(solver.BVOr, (vars[pe, op] for pe in cgra.functional_units)) == 1)
        else:
            op_vars = vars.anonymous_var(bv)
            for idx,pe in enumerate(cgra.functional_units):
                c.append(op_vars[idx] == vars[pe, op])
            c.append(_is_one_hot(op_vars, solver))

    return solver.And(c)
Пример #4
0
def route_exclusivity(cgra : MRRG, design : Design, vars : Modeler, solver : Solver) -> Term:
    '''
        each routing node is used for at most one value

        for all node in nodes:
            popcount(vars[node, value] for value in values) <= 1
    '''
    bv = solver.BitVec(len(design.values))
    c = []
    for node in cgra.all_nodes:
        node_vars = vars.anonymous_var(bv)
        for idx, value in enumerate(design.values):
            c.append(node_vars[idx] == vars[node, value])
        c.append(_is_one_hot_or_0(node_vars, solver))

    return solver.And(c)
Пример #5
0
def pe_legality(cgra : MRRG, design : Design, vars : Modeler, solver : Solver) -> Term:
    ''' Assert ops are not placed on PE's that do not support them '''
    c = []
    for pe in cgra.functional_units:
        for op in design.operations:
            if op.opcode not in pe.ops:
                c.append(vars[pe, op] == 0)
    return solver.And(c)
Пример #6
0
def limit_popcount_total(
        node_filter : NodeFilter,
        l : int,
        n : int,
        cgra : MRRG,
        design : Design,
        vars : Modeler,
        solver : Solver) -> Term:
    v = vars[node_filter]
    if n is None:
        return solver.BVUle(l, v)

    if n < 0 or n < l:
        assert 0
    elif n.bit_length() > v.sort.width or l.bit_length() > v.sort.width:
        assert 0
    else:
    #    return solver.BVUle(v, n)
        return solver.And(solver.BVUle(l, v), solver.BVUle(v, n))
Пример #7
0
def output_connectivity(cgra : MRRG, design : Design, vars : Modeler, solver : Solver) -> Term:
    '''
        if node used to route a value then exactly one of its outputs also
        routes that value
    '''
    c = []
    for node in cgra.all_nodes:
        bv = solver.BitVec(len(node.outputs.values()))
        for value in design.values:
            if isinstance(node, mrrg.FU_Port):
                continue
            for dst in value.dsts:
                v = vars[node, value, dst]
                i_vars = vars.anonymous_var(bv)
                for idx, n in enumerate(node.outputs.values()):
                    c.append(i_vars[idx] == vars[n, value, dst])
                c.append(solver.Or(v == 0, _is_one_hot(i_vars, solver)))

    return solver.And(c)
Пример #8
0
def init_popcount_concat(
        node_filter : NodeFilter,
        cgra : MRRG,
        design : Design,
        vars : Modeler,
        solver : Solver) -> Term:

    nodes = [n for n in cgra.all_nodes if node_filter(n)]
    width = len(nodes).bit_length()
    zero = solver.TheoryConst(solver.BitVec(width - 1), 0)
    zeroExt = ft.partial(solver.Concat, zero)
    expr = ft.reduce(solver.BVAdd,
            map(zeroExt,
                (ft.reduce(solver.BVOr,
                    (vars[n, v] for v in design.values)
                ) for n in nodes)
            )
        )

    pop_count = vars.init_var(node_filter, expr.sort)
    return expr == pop_count
Пример #9
0
def freaze_fus(
    model : Model,
    cgra : MRRG,
    design : Design,
    vars : Modeler,
    solver : Solver) -> Term:

    c = []
    for pe in cgra.functional_units:
        for op in design.operations:
            c.append(vars[pe, op] == model[pe, op])
    return solver.And(c)
Пример #10
0
def routing_resource_usage(cgra : MRRG, design : Design, vars : Modeler, solver : Solver) -> Term:
    '''
        if a routing node is used to route a value to a dst then then it is used to
        route the value
    '''
    c = []
    for node in cgra.all_nodes:
        for value in design.values:
            v = vars[node, value]
            v_ = ft.reduce(solver.BVOr, (vars[node, value, dst] for dst in value.dsts))
            c.append(v == v_)

    return solver.And(c)
Пример #11
0
def init_popcount_ite(
        node_filter : NodeFilter,
        cgra : MRRG,
        design : Design,
        vars : Modeler,
        solver : Solver) -> Term:

    nodes = [n for n in cgra.all_nodes if node_filter(n)]
    bv = solver.BitVec(len(nodes).bit_length())
    zero = solver.TheoryConst(bv, 0)
    one  = solver.TheoryConst(bv, 1)

    expr = ft.reduce(solver.BVAdd,
            map(lambda x : solver.Ite(x == 0, zero, one),
                (ft.reduce(solver.BVOr,
                    (vars[n, v] for v in design.values)
                ) for n in nodes)
            )
        )

    pop_count = vars.init_var(node_filter, bv)
    return expr == pop_count
Пример #12
0
def port_placement(cgra : MRRG, design : Design, vars : Modeler, solver : Solver) -> Term:
    '''
        values terminate at the input port of their op
    '''
    c = []
    for pe in cgra.functional_units:
        for value in design.values:
            for dst in value.dsts:
                op, operand = dst
                if op.opcode not in pe.ops:
                    for port in pe.operands.values():
                        v_ = vars[port, value, dst]
                        c.append(v_ == 0)
                else:
                    port = pe.operands[operand]
                    v = vars[pe, op]
                    v_ = vars[port, value, dst]
                    c.append(v == v_)

    return solver.And(c)
Пример #13
0
def init_value(cgra : MRRG, design : Design, vars : Modeler, solver : Solver) -> Term:
    '''
        values are routed from the pe which holds their source op
    '''
    c = []
    for pe in cgra.functional_units:
        for value in design.values:
            src = value.src
            v = vars[pe, src]
            if src.opcode not in pe.ops:
               c.append(vars[pe, value] == 0)
            elif src.duplicate:
                v_ = vars[pe, value]
                c.append(v == v_)
            else:
                for dst in value.dsts:
                    v_ = vars[pe, value, dst]
                    c.append(v == v_)

    return solver.And(c)
Пример #14
0
def init_popcount_bithack(
        node_filter : NodeFilter,
        cgra : MRRG,
        design : Design,
        vars : Modeler,
        solver : Solver) -> Term:

    def _build_grouped_mask(k, n):
        '''
        build_grouped_mask :: int -> int -> Term
        returns the unique int m of length n that matches the following RE
        ((0{0,k} 1{k}) | (1{0,k})) (0{k} 1{k})*
        '''
        m = 0
        for i in range(k):
            m |= 1 << i
        c = 2*k
        while c < n:
            m |= m << c
            c *= 2
        return solver.TheoryConst(solver.BitVec(n), m)

    def _is_power_of_2(x : int) -> bool:
        return x & (x - 1) == 0

    def _floor_log2(x : int) -> int:
        return x.bit_length() - 1

    def _prev_power_of_2(x : int) -> int:
        return 1 << _floor_log2(x - 1)

    def _next_power_of_2(x : int) -> int:
        return 1 << x.bit_length()


    constraints = []
    vs = [vars[n, v] for n in cgra.all_nodes if node_filter(n) for v in design.values]
    width = len(vs)
    # build a bitvector from the concanation of bits
    bv = vars.anonymous_var(solver.BitVec(width))

    for idx,v in enumerate(vs):
        constraints.append(bv[idx] == v)

    # Boolector can't handle lshr on non power of 2, so zero extend
    if solver.solver_name == 'Boolector' and not _is_power_of_2(width):
        l = _next_power_of_2(width)
        bv = solver.Concat(solver.TheoryConst(solver.BitVec(l - width), 0), bv)

    width = bv.sort.width
    pop_count = vars.init_var(node_filter, bv.sort)

    if width <= 1:
        constraints.append(pop_count == bv)
        return solver.And(constraints)
    elif width == 2:
        constraints.append(pop_count == (bv & 1) + (bv >> 1))
        return solver.And(constraints)

    max_shift = _prev_power_of_2(width)

    def _mask_shift_add(x, shift):
        mask = _build_grouped_mask(shift, width)
        return (x & mask) + ((x >> shift) & mask)

    shifts = it.takewhile(lambda n : n <= max_shift, (1 << i for i in it.count()))
    x = ft.reduce(_mask_shift_add, shifts, bv)

    constraints.append(pop_count == x)
    return solver.And(constraints)
Пример #15
0
def _is_one_hot(var : Term, solver : Solver) -> Term:
    return solver.And(_is_one_hot_or_0(var, solver), var != solver.TheoryConst(var.sort, 0))
Пример #16
0
def _is_one_hot_or_0(var : Term, solver : Solver):
    return (var & (var - 1)) == solver.TheoryConst(var.sort, 0)
Пример #17
0
def init_placement_vars(cgra : MRRG, design : Design, vars : Modeler, solver : Solver) -> Term:
    bv1 = solver.BitVec(1)
    for pe in cgra.functional_units:
        for op in design.operations:
            vars.init_var((pe, op), bv1)
    return solver.TheoryConst(solver.Bool(), True)