Exemple #1
0
class Design(NamedIDObject):
    def __init__(self, comp_list, routing_list, fabric, position_type, name='', constraint_generators=(), optimizers=()):
        '''
        adj_dict :: {str : [(str, int)]}
        adj_dict[x] := out edges of x with the their width
        fabric :: Fabric
        position_type ::  str -> Fabric -> PositionBase

        constraints_gen :: [([Component] -> [Wire] -> fabric -> z3.Bool)]
        constraint_generators := an iterable of keys, functions that generate hard
            constraints

        optimizers :: [([Component] -> [Wire] -> fabric -> (z3.Bool, z3.Object), bool)]
        optimizers := [k, f, b]
            where
                k is the key
                f(components, wires) := an Iterable of functions that
                    generate hard constraint / optimizing parameters pairs,
                b := a bool which indicating whether Optimizing parameter is minimized or maximized
        '''

        super().__init__(name)
        self._fabric = fabric
        self._position_type = position_type

        self._comp_list = comp_list #is kinda redundant to keep this around but it might be useful
        self._routing_list = routing_list

        self._comps = dict()
        self._wires = dict()

        self._p_constraints = ValidContainer()
        self._cg = dict()
        self._opt = dict()
        self._pinned_comps = []

        self._r_constraints = ValidContainer()
        self._rcg = dict()
        self._ropt = dict()

        self._max_degree = 0

        for k,f in constraint_generators:
            self.add_constraint_generator(k,f)

        for k,f,b in optimizers:
            self.add_optimizer(k,f,b)

        #build graph
        self._gen_graph()

    def _gen_graph(self):
        #reset constraints
        self._reset_constraints()

        for comp_dict in self._comp_list:
            name = comp_dict['name']
            width = comp_dict['width']
            height = comp_dict['height']
            if comp_dict['x'] is not None and comp_dict['y'] is not None:
                self._comps[name] = Component(name, True, width, height, comp_dict['x'], comp_dict['y'])
                self._pinned_comps.append(name)
            else:
                self._comps[name] = Component(name, False, width, height)

        #need to generate positons for each component
        self._gen_pos()
        

    def _gen_pos(self):
        #reset constraints
        self._reset_constraints()
        for c in self.components:
            if c.width and c.height:
                c.pos = self._position_type(c.name, self.fabric, c.width, c.height)
            else:
                c.pos = self._position_type(c.name, self.fabric)
            # also find maximum (in or out) degree
            if self._max_degree < c.degree:
                self._max_degree = c.degree

    def get_sorted_components(self, descend):
        '''returns components sorted by their degree in descending order if descend = True'''
        return sorted(list(self._comps.values()), key = lambda c: c.degree, reverse=descend)

    @property
    def components(self):
        return iter(self._comps.values())

    @property
    def wires(self):
        return iter(self._wires.values())

    @property
    def fabric(self):
        return self._fabric

    @fabric.setter
    def fabric(self, fabric):
        if self.fabric != fabirc:
            self._fabric = fabric
            #position representation is dependent on fabric
            self._gen_pos()

    @property
    def constraints(self):
        '''returns all hard constraints'''
        if self._pinned_comps:
            return z3.And(self.p_constraints, self.g_constraints, self.o_constraints, self.r_constraints, self.pinned_constraints)
        else:
            return z3.And(self.p_constraints, self.g_constraints, self.o_constraints, self.r_constraints)

    @property
    def max_degree(self):
        return self._max_degree

    def _reset_constraints(self):
        self._reset_p_constraints()
        self._reset_g_constraints()
        self._reset_o_constraints()

    '''
        -----------------------------------------------------------------------
        Position Related Stuff
        -----------------------------------------------------------------------
    '''

    @property
    def position_type(self):
        return self._position_type

    @position_type.setter
    def position_type(self, position_type):
        if position_type != self.position_type:
            self._position_type = position_type
            #regenerate positions for each node
            self._gen_pos()

    @property
    def p_constraints(self):
        if not self._p_constraints.valid:
            cl = []
            for c in self.components:
                if not c.is_fixed:
                    cl.append(c.pos.invariants)
            self._p_constraints.data = z3.And(*cl)

        return self._p_constraints.data

    def _reset_p_constraints(self):
        self._p_constraints.mark_invalid()

    @property
    def pinned_constraints(self):
        if self._pinned_comps:
            c = []
            for src_name in self._pinned_comps:
                comp = self._comps[src_name]
                c.append(comp.pos.x == self._position_type.pos_repr(comp.x))
                c.append(comp.pos.y == self._position_type.pos_repr(comp.y))
                c.append(comp.pos.horiz_var == comp.pos.width)
                c.append(comp.pos.vert_var == comp.pos.height)
                c.append(z3.And(comp.pos._d0 == True,
                                comp.pos._d90 == False,
                                comp.pos._d180 == False,
                                comp.pos._d270 == False))
            return z3.And(c)
        else:
            return []    
            
    '''
        -----------------------------------------------------------------------
        General constraints related stuff
        -----------------------------------------------------------------------
    '''
    @property
    def constraint_generators(self):
        return set((k, f) for k,(f,_) in self._cg.items())

    def add_constraint_generator(self, k, f):
        self._cg[k] = (f, ValidContainer())

    def remove_constraint_generator(self, k):
        del self._cg[k]

    @property
    def g_constraints(self):
        cl = []
        for k,(f, c) in self._cg.items():
            if not c.valid:
                c.data = f(self.components, self.wires, self.fabric)
            cl.append(c.data)
        return z3.And(cl)

    def _reset_g_constraints(self):
        for _,c in self._cg.values():
            c.mark_invalid()

    '''
        -----------------------------------------------------------------------
        Optimization Related Stuff
        -----------------------------------------------------------------------
    '''

    @property
    def optimizers(self):
        return set((k, f, b) for k,(f,_,b) in self._cg.items())

    def add_optimizer(self, k, f, minimize):
        self._opt[k] = (f, ValidContainer(), minimize)

    def remove_optimizer(self, k):
        del self._opt[k]

    @property
    def o_constraints(self):
        cl = []
        for f,c,m in self._opt.values():
            # f := functiom
            # c := ValidContainer(constraints, parameter)
            # m := minimize flag
            if not c.valid:
                c.data = f(self.components, self.wires, self.fabric)
            if c.data[0]:
                #check that list nonempty to avoid appending an empty list
                cl.append(c.data[0])
        return z3.And(cl)

    @property
    def opt_parameters(self):
        cl = []
        for f,c,m in self._opt.values():
            # f := functiom
            # c := ValidContainer(constraints, parameter)
            # m := minimize flag
            if not c.valid:
                c.data = f(self.components, self.wires, self.fabric)
            cl.append((c.data[1], m))
        return cl

    def _reset_o_constraints(self):
        for _,c,_ in self._opt.values():
            c.mark_invalid()

    '''
        -----------------------------------------------------------------------
        Pad-Routing Related Stuff
        -----------------------------------------------------------------------
    '''

    
    @property
    def r_constraints(self):
        cl = []
        for k,(f, c) in self._rcg.items():
            if not c.valid:
                c.data = f(self._comps, self._routing_list)
            cl.append(c.data)
        return z3.And(cl)
    
    def add_pad_cg(self, k, f):
        '''
            Adds a constraint generator for pad-level connectivity
        '''
        self._rcg[k] = (f, ValidContainer())


    def remove_pad_cg(self, k):
        del self._rcg[k]


    @property
    def r_opt_param(self):
        cl = []
        for k,(f, c) in self._ropt.items():
            if not c.valid:
                c.data = f(self._comps, self._routing_list)
            cl.append(c.data)
        return cl

    def add_pad_opt(self, k, f):
        '''
            Adds a constraint generator for pad-level connectivity
        '''
        self._ropt[k] = (f, ValidContainer())


    def remove_pad_opt(self, k):
        del self._ropt[k]
Exemple #2
0
class Design(NamedIDObject):
    def __init__(self,
                 adj_dict,
                 fabric,
                 position_type,
                 name='',
                 constraint_generators=(),
                 optimizers=()):
        '''
        adj_dict :: {str : [(str, int)]}
        adj_dict[x] := out edges of x with the their width
        fabric :: Fabric
        position_type ::  str -> Frabric -> PositionBase

        constraints_gen :: [([Component] -> [Wire] -> fabric -> z3.Bool)]
        constraint_generators := an iterable of keys, functions that generate hard
            constraints

        optimizers :: [([Component] -> [Wire] -> fabric -> (z3.Bool, z3.Object), bool)]
        optimizers := [k, f, b]
            where
                k is the key
                f(components, wires) := an Iterable of functions that
                    generate hard constraint / optimizing parameters pairs,
                b := a bool which indicating whether Optimizing parameter is minimized or maximized
        '''

        super().__init__(name)
        self._fabric = fabric
        self._position_type = position_type

        self._adj_dict = adj_dict  #is kinda redundent to keep this around but it might be useful

        self._comps = dict()
        self._wires = dict()

        self._p_constraints = ValidContainer()
        self._cg = dict()
        self._opt = dict()

        self._max_degree = 0

        for k, f in constraint_generators:
            self.add_constraint_generator(k, f)

        for k, f, b in optimizers:
            self.add_optimizer(k, f, b)

        #build graph
        self._gen_graph()

    def _gen_graph(self):
        #reset constraints
        self._reset_constraints()

        for src_name, adj_list in self._adj_dict.items():
            if not isinstance(src_name, str):
                raise TypeError(
                    'component_graph must be a dictionary of str to [(str, int)]'
                )

            if src_name not in self._comps:
                self._comps[src_name] = Component(src_name)
            src = self._comps[src_name]

            for pair in adj_list:
                if not isinstance(pair, tuple) or len(pair) != 2:
                    raise TypeError(
                        'component_graph must be a dictionary of str to [(str, int)]'
                    )

                dst_name = pair[0]
                width = pair[1]
                if not isinstance(dst_name, str) or not isinstance(width, int):
                    raise TypeError(
                        'component_graph must be a dictionary of str to [(str, int)]'
                    )

                if dst_name not in self._comps:
                    self._comps[dst_name] = Component(dst_name)
                dst = self._comps[dst_name]

                self._wires[(src_name, dst_name)] = Wire(src, dst, width)

        #need to generate positons for each component
        self._gen_pos()

    def _gen_pos(self):
        #reset constraints
        self._reset_constraints()
        for c in self.components:
            c.pos = self._position_type(c.name, self.fabric)
            # also find maximum (in or out) degree
            if self._max_degree < c.degree:
                self._max_degree = c.degree

    def get_sorted_components(self, descend):
        '''returns components sorted by their degree in descending order if descend = True'''
        return sorted(list(self._comps.values()),
                      key=lambda c: c.degree,
                      reverse=descend)

    @property
    def components(self):
        return iter(self._comps.values())

    @property
    def wires(self):
        return iter(self._wires.values())

    @property
    def fabric(self):
        return self._fabric

    @fabric.setter
    def fabric(self, fabric):
        if self.fabric != fabirc:
            self._fabric = fabric
            #position representation is dependent on fabric
            self._gen_pos()

    @property
    def constraints(self):
        '''returns all hard constraints'''
        return z3.And(self.p_constraints, self.g_constraints,
                      self.o_constraints)

    @property
    def max_degree(self):
        return self._max_degree

    def _reset_constraints(self):
        self._reset_p_constraints()
        self._reset_g_constraints()
        self._reset_o_constraints()

    '''
        -----------------------------------------------------------------------
        Position Related Stuff
        -----------------------------------------------------------------------
    '''

    @property
    def position_type(self):
        return self._position_type

    @position_type.setter
    def position_type(self, position_type):
        if position_type != self.position_type:
            self._position_type = position_type
            #regenerate positions for each node
            self._gen_pos()

    @property
    def p_constraints(self):
        if not self._p_constraints.valid:
            cl = []
            for c in self.components:
                cl.append(c.pos.invariants)
            self._p_constraints.data = z3.And(*cl)

        return self._p_constraints.data

    def _reset_p_constraints(self):
        self._p_constraints.mark_invalid()

    '''
        -----------------------------------------------------------------------
        General constraints related stuff
        -----------------------------------------------------------------------
    '''

    @property
    def constraint_generators(self):
        return set((k, f) for k, (f, _) in self._cg.items())

    def add_constraint_generator(self, k, f):
        self._cg[k] = (f, ValidContainer())

    def remove_constraint_generator(self, k):
        del self._cg[k]

    @property
    def g_constraints(self):
        cl = []
        for k, (f, c) in self._cg.items():
            if not c.valid:
                c.data = f(self.components, self.wires, self.fabric)
            cl.append(c.data)
        return z3.And(cl)

    def _reset_g_constraints(self):
        for _, c in self._cg.values():
            c.mark_invalid()

    '''
        -----------------------------------------------------------------------
        Optimization Related Stuff
        -----------------------------------------------------------------------
    '''

    @property
    def optimizers(self):
        return set((k, f, b) for k, (f, _, b) in self._cg.items())

    def add_optimizer(self, k, f, minimize):
        self._opt[k] = (f, ValidContainer(), minimize)

    def remove_optimizer(self, k):
        del self._opt[k]

    @property
    def o_constraints(self):
        cl = []
        for f, c, m in self._opt.values():
            # f := functiom
            # c := ValidContainer(constraints, parameter)
            # m := minimize flag
            if not c.valid:
                c.data = f(self.components, self.wires, self.fabric)
            if c.data[0]:
                #check that list nonempty to avoid appending an empty list
                cl.append(c.data[0])
        return z3.And(cl)

    @property
    def opt_parameters(self):
        cl = []
        for f, c, m in self._opt.values():
            # f := functiom
            # c := ValidContainer(constraints, parameter)
            # m := minimize flag
            if not c.valid:
                c.data = f(self.components, self.wires, self.fabric)
            cl.append((c.data[1], m))
        return cl

    def _reset_o_constraints(self):
        for _, c, _ in self._opt.values():
            c.mark_invalid()