def __add_fixed(self, partition, constraint): """ Precomputes and caches FixedKeyAndMask for easier use later Saves a map of partition to the constraint records these in a dict by Partition so they can be found easier in future passes. Saves a list of the keys and their n_keys so these zones can be blocked :param pacman.model.graphs.AbstractEdgePartition partition: :param FixedKeyAndMaskConstraint constraint: """ self.__fixed_partitions[partition] = constraint.keys_and_masks for key_and_mask in constraint.keys_and_masks: # Go through the mask sets and save keys and n_keys for key, n_keys in get_key_ranges(key_and_mask.key, key_and_mask.mask): self.__fixed_keys.append((key, n_keys))
def _allocate_fixed_keys_and_masks(self, keys_and_masks, fixed_mask): """ Allocate fixed keys and masks. :param iterable(BaseKeyAndMask) keys_and_masks: the fixed keys and masks combos :param fixed_mask: fixed mask :type fixed_mask: int or None :rtype: None :raises PacmanRouteInfoAllocationException: """ # If there are fixed keys and masks, allocate them for key_and_mask in keys_and_masks: # If there is a fixed mask, check it doesn't clash if fixed_mask is not None and fixed_mask != key_and_mask.mask: raise PacmanRouteInfoAllocationException( "Cannot meet conflicting constraints") # Go through the mask sets and allocate for key, n_keys in get_key_ranges(key_and_mask.key, key_and_mask.mask): self._allocate_elements(key, n_keys)
def _allocate_keys_and_masks(self, fixed_mask, fields, partition_n_keys, contiguous_keys=True): """ :param fixed_mask: :type fixed_mask: int or None :param fields: :type fields: iterable(Field) or None :param int partition_n_keys: :param bool contiguous_keys: :rtype: list(BaseKeyAndMask) :raises PacmanRouteInfoAllocationException: """ # If there isn't a fixed mask, generate a fixed mask based # on the number of keys required masks_available = [fixed_mask] if fixed_mask is None: masks_available = get_possible_masks( partition_n_keys, contiguous_keys=contiguous_keys) # For each usable mask, try all of the possible keys and # see if a match is possible mask_found = None key_found = None mask = None for mask in masks_available: logger.debug("Trying mask {} for {} keys", hex(mask), partition_n_keys) key_found = None key_generator = KeyFieldGenerator(mask, fields, self._free_space_tracker) for key in key_generator: logger.debug("Trying key {}", hex(key)) # Check if all the key ranges can be allocated matched_all = True index = 0 for (base_key, n_keys) in get_key_ranges(key, mask): logger.debug("Finding slot for {}, n_keys={}", hex(base_key), n_keys) index = self._find_slot(base_key, lo=index) logger.debug("Slot for {} is {}", hex(base_key), index) if index is None: matched_all = False break space = self._check_allocation(index, base_key, n_keys) logger.debug("Space for {} is {}", hex(base_key), space) if space is None: matched_all = False break if matched_all: logger.debug("Matched key {}", hex(key)) key_found = key break # If we found a matching key, store the mask that worked if key_found is not None: logger.debug("Matched mask {}", hex(mask)) mask_found = mask break # If we found a working key and mask that can be assigned, # Allocate them if key_found is not None and mask_found is not None: for (base_key, n_keys) in get_key_ranges(key_found, mask): self._allocate_elements(base_key, n_keys) # If we get here, we can assign the keys to the edges return [BaseKeyAndMask(base_key=key_found, mask=mask)] raise PacmanRouteInfoAllocationException( "Could not find space to allocate keys")