def place_constraints(comps, fab_dims, wire_lengths): ''' place_constraints :: {Component} -> (int, int) -> [int] -> z3.z3.BoolRef ''' nnode = len(comps) #build bit mask mask, mrows, mcols, mwl = _build_standard_mask(fab_dims, wire_lengths) #print bitmask #for idx, v in enumerate(mask): # print(v, end='') # if (idx % mcols) == mcols - 1: # print() imask = int(~mask) mask = int(mask) for comp in comps: comp.pos = z3.BitVec(comp.name, mrows * mcols) constraints = [] for comp in comps: for adj in comp.inputs: #should dispatch to fabric to get the rules c = [] for wl in wire_lengths: #should probably be comp.pos & (shifted adj.pos) != 0, #so that components can have variable size c.append( z3.Or( comp.pos == z3.LShR(adj.pos, wl), comp.pos == adj.pos << wl, comp.pos == z3.LShR(adj.pos, wl * mcols), comp.pos == adj.pos << wl * mcols, )) constraints.append(z3.Or(c)) constraints.append(zu.hamming(comp.pos) == __COMP_AREA) #The following is insufficient to achieve the previous #constraints.append(comp.pos != 0) constraints.append(comp.pos & imask == 0) u = ft.reduce(lambda x, y: x | y, [c.pos for c in comps]) constraints.append(zu.hamming(u) == nnode) return z3.And(constraints)
def place_constraints_2d(comps, fab_dims, wire_lengths, pack=True): ''' place_constraints :: {Component} -> (int, int) -> [int] -> Bool? -> z3.z3.BoolRef ''' nnode = len(comps) frows, fcols = fab_dims constraints = [] if pack: def _get_x(bv): return z3.Extract(frows + fcols - 1, frows, bv) def _get_y(bv): return z3.Extract(frows - 1, 0, bv) for comp in comps: comp.pos = z3.BitVec(comp.name, frows + fcols) constraints.append( z3.simplify(z3.Distinct(*(c.pos for c in comps)), ':blast-distinct', True)) else: def _get_x(bv): return bv[0] def _get_y(bv): return bv[1] for comp in comps: comp.pos = (z3.BitVec(comp.name + '_x', frows), z3.BitVec(comp.name + '_y', fcols)) constraints.append( z3.simplify( z3.Distinct(*(z3.Concat(c.pos[0], c.pos[1]) for c in comps)), ':blast-distinct', True)) for comp in comps: constraints.append(zu.hamming(_get_x(comp.pos)) == __COMP_X) constraints.append(zu.hamming(_get_y(comp.pos)) == __COMP_Y) return z3.And(constraints)
def place_constraints_opt(comps, fab_dims, distinct_flag=True): ''' place_constraints_opt :: {Component} -> (int, int) -> [int] -> (z3.z3.BoolRef) ''' rows = fab_dims[0] cols = fab_dims[1] nnode = len(comps) constraints = [] if distinct_flag: c = [] for comp in comps: #add a tuple representing the x,y coordinates comp.pos = (z3.BitVec(comp.name + '_x', int(math.ceil(math.log(cols, 2)))), z3.BitVec(comp.name + '_y', int(math.ceil(math.log(rows, 2))))) c.append(z3.Concat(comp.pos[0], comp.pos[1])) constraints.append(z3.simplify(z3.Distinct(c), ':blast-distinct', True)) else: onehot_list = [] for comp in comps: comp.pos = (z3.BitVec(comp.name + '_x', int(math.ceil(math.log(cols, 2)))), z3.BitVec(comp.name + '_y', int(math.ceil(math.log(rows, 2))))) #one hot representation -- temporary var temp_1h = z3.BitVec(comp.name, rows * cols) onehot_list.append(temp_1h) constraints.append(zu.hamming(temp_1h) == __COMP_AREA) constraints.append( z3.Extract( 0, 0, z3.LShR(temp_1h, find_shift(comp.pos[0], comp.pos[1], rows, cols))) == 1) u = ft.reduce(lambda x, y: x | y, [bv for bv in onehot_list]) constraints.append(zu.hamming(u) == nnode) #check if number of rows/cols is a power of two (and thus placements can be any bit representation), if not, constrain the placements to be on fabric if not math.log(rows, 2).is_integer() and not math.log(cols, 2).is_integer(): for comp in comps: constraints.append( z3.And(z3.ULT(comp.pos[0], cols), z3.ULT(comp.pos[1], rows))) elif not math.log(rows, 2).is_integer(): for comp in comps: constraints.append(z3.ULT(comp.pos[1], rows)) elif not math.log(cols, 2).is_integer(): for comp in comps: constraints.append(z3.ULT(comp.pos[0], cols)) #form the manhattan distance manhattan_dist = 0 for comp in comps: for adj in comp.inputs: manhattan_dist += abs_diff(comp.pos[0], adj.pos[0], fab_dims) + abs_diff( comp.pos[1], adj.pos[1], fab_dims) return z3.And(constraints), manhattan_dist
def place_constraints_2d(comps, fab_dims, wire_lengths, pack=True): ''' place_constraints :: {Component} -> (int, int) -> [int] -> Bool? -> z3.z3.BoolRef ''' nnode = len(comps) frows, fcols = fab_dims constraints = [] if pack: def _get_x(bv): return z3.Extract(frows + fcols - 1, frows, bv) def _get_y(bv): return z3.Extract(frows - 1, 0, bv) for comp in comps: comp.pos = z3.BitVec(comp.name, frows + fcols) constraints.append(z3.Distinct(*(c.pos for c in comps))) else: def _get_x(bv): return bv[0] def _get_y(bv): return bv[1] for comp in comps: comp.pos = (z3.BitVec(comp.name + '_x', frows), z3.BitVec(comp.name + '_y', fcols)) constraints.append( z3.Distinct(*(z3.Concat(c.pos[0], c.pos[1]) for c in comps))) for comp in comps: for adj in comp.inputs: #should dispatch to fabric to get the rules c = [] for wl in wire_lengths: #should probably be comp.pos & (shifted adj.pos) != 0, #so that components can have variable size c.append( z3.Or( z3.And( _get_x(comp.pos) == z3.LShR(_get_x(adj.pos), wl), _get_y(comp.pos) == _get_y(adj.pos)), z3.And( _get_x(comp.pos) == _get_x(adj.pos) << wl, _get_y(comp.pos) == _get_y(adj.pos)), z3.And( _get_y(comp.pos) == z3.LShR(_get_y(adj.pos), wl), _get_x(comp.pos) == _get_x(adj.pos)), z3.And( _get_y(comp.pos) == _get_y(adj.pos) << wl, _get_x(comp.pos) == _get_x(adj.pos)), )) constraints.append(z3.Or(c)) constraints.append(zu.hamming(_get_x(comp.pos)) == __COMP_X) constraints.append(zu.hamming(_get_y(comp.pos)) == __COMP_Y) return z3.And(constraints)
def place_constraints_2d(comps, fab_dims, wire_lengths, pack=True): ''' place_constraints :: {Component} -> (int, int) -> [int] -> Bool? -> z3.z3.BoolRef ''' nnode = len(comps) frows, fcols = fab_dims constraints = [] if pack: def _get_x(bv): return z3.Extract(frows + fcols - 1, frows, bv) def _get_y(bv): return z3.Extract(frows - 1, 0, bv) for comp in comps: comp.pos = z3.BitVec(comp.name, frows + fcols) constraints.append( z3.simplify(z3.Distinct(*(c.pos for c in comps)), ':blast-distinct', True)) else: def _get_x(bv): return bv[0] def _get_y(bv): return bv[1] #for comp in comps: comp.pos = (z3.BitVec(comp.name + '_x', frows), z3.BitVec(comp.name + '_y', fcols)) #constraints.append(z3.simplify(z3.Distinct(*(z3.Concat(c.pos[0], c.pos[1]) for c in comps)), ':blast-distinct', True)) c = [] for comp in comps: #add a tuple representing the x,y coordinates comp.pos = (z3.BitVec(comp.name + '_x', frows), z3.BitVec(comp.name + '_y', fcols)) c.append(z3.Concat(comp.pos[0], comp.pos[1])) constraints.append(z3.simplify(z3.Distinct(c), ':blast-distinct', True)) shiftvars = [] for comp in comps: for adj in comp.inputs: #should dispatch to fabric to get the rules shx = z3.BitVec(comp.name + '-' + adj.name + '_shx', frows) shy = z3.BitVec(comp.name + '-' + adj.name + '_shy', fcols) shiftvars.append(shx) shiftvars.append(shy) constraints.append( z3.Or( _get_x(comp.pos) == z3.LShR(_get_x(adj.pos), shx), _get_x(comp.pos) == _get_x(adj.pos) << shx)) constraints.append( z3.Or( _get_y(comp.pos) == z3.LShR(_get_y(adj.pos), shy), _get_y(comp.pos) == _get_y(adj.pos) << shy)) constraints.append(zu.hamming(_get_x(comp.pos)) == __COMP_X) constraints.append(zu.hamming(_get_y(comp.pos)) == __COMP_Y) return z3.And(constraints), shiftvars
def invariants(self): return z3.And(zu.hamming(self.x) == 1, zu.hamming(self.y) == 1)