Example #1
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)
Example #2
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)
Example #3
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)
Example #4
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)
Example #5
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)