def _convert_to_pacman_router_table( self, mundy_compressed_router_table_entries, router_x_coord, router_y_coord): """ :param mundy_compressed_router_table_entries: rig version of the table :param router_x_coord: the x coord of this routing table :param router_y_coord: the y coord of this routing table :return: pacman version of the table """ table = MulticastRoutingTable(router_x_coord, router_y_coord) if (len(mundy_compressed_router_table_entries) > self.max_supported_length): raise exceptions.PacmanElementAllocationException( "The routing table {}:{} after compression will still not fit" " within the machines router ({} entries)".format( router_x_coord, router_y_coord, len(mundy_compressed_router_table_entries))) for entry in mundy_compressed_router_table_entries: table.add_mutlicast_routing_entry( MulticastRoutingEntry( entry.key, entry.mask, # Key and mask ((int(c) - 6) for c in entry.route if c.is_core), # Cores (int(l) for l in entry.route if l.is_link), # Links False)) # NOT defaultable return table
def __call__(self, routing_infos, routing_table_by_partitions, machine): """ :param routing_infos: :param routing_table_by_partitions: :param machine: :return: """ progress_bar = ProgressBar(len(list(machine.chips)), "Generating routing tables") routing_tables = MulticastRoutingTables() for chip in machine.chips: partitions_in_table = routing_table_by_partitions.\ get_entries_for_router(chip.x, chip.y) if len(partitions_in_table) != 0: routing_table = MulticastRoutingTable(chip.x, chip.y) for partition in partitions_in_table: keys_and_masks = routing_infos.\ get_keys_and_masks_from_partition(partition) entry = partitions_in_table[partition] for key_and_mask in keys_and_masks: multicast_routing_entry = MulticastRoutingEntry( routing_entry_key=key_and_mask.key_combo, defaultable=entry.defaultable, mask=key_and_mask.mask, link_ids=entry.out_going_links, processor_ids=entry.out_going_processors) routing_table.add_mutlicast_routing_entry( multicast_routing_entry) routing_tables.add_routing_table(routing_table) progress_bar.update() progress_bar.end() return {"router_tables": routing_tables}
def test_new_multicast_routing_table_duplicate_entry(self): """ test that adding multiple identical entries into a multicast table causes an error :return: """ key_combo = 0xff35 mask = 0xff35 proc_ids = list() link_ids = list() for i in range(18): proc_ids.append(i) for i in range(6): link_ids.append(i) multicast_entries = list() for i in range(5): multicast_entries.append(MulticastRoutingEntry( key_combo + i, mask + i, proc_ids, link_ids, True)) mrt = MulticastRoutingTable(0, 0, multicast_entries) with self.assertRaises(PacmanAlreadyExistsException): mrt.add_mutlicast_routing_entry(multicast_entries[0])
def add_routing_key_entries( routing_paths, subedge_routing_info, out_going_subedge, routing_tables): """ creates and adds entries for routing tables as required for the path :param routing_paths: the routing paths object generated from routing info :param subedge_routing_info: the subedge info object that contains keys :param out_going_subedge: the edge this is aossicated with :param routing_tables: the routing tables to adjust :return: None """ path_entries = routing_paths.get_entries_for_edge(out_going_subedge) # iterate through the entries in each path, adding a router entry if # required for path_entry in path_entries: # locate the router router = routing_tables.get_routing_table_for_chip( path_entry.router_x, path_entry.router_y) if router is None: router = MulticastRoutingTable( path_entry.router_x, path_entry.router_y) routing_tables.add_routing_table(router) # add entries as required, or merge them if entries already exist for key_and_mask in subedge_routing_info.keys_and_masks: multicast_routing_entry = MulticastRoutingEntry( routing_entry_key=key_and_mask.key_combo, defaultable=path_entry.defaultable, mask=key_and_mask.mask, link_ids=path_entry.out_going_links, processor_ids=path_entry.out_going_processors) stored_entry = \ router.get_multicast_routing_entry_by_routing_entry_key( key_and_mask.key_combo, key_and_mask.mask) if stored_entry is None: router.add_mutlicast_routing_entry(MulticastRoutingEntry( routing_entry_key=key_and_mask.key_combo, defaultable=path_entry.defaultable, mask=key_and_mask.mask, link_ids=path_entry.out_going_links, processor_ids=path_entry.out_going_processors)) else: merged_entry = stored_entry.merge(multicast_routing_entry) router.remove_multicast_routing_entry(stored_entry) router.add_mutlicast_routing_entry(merged_entry)
def test_new_multicast_routing_table(self): """ test that creating a multicast routing entry and adding it to the table works :return: """ key_combo = 0xff000 mask = 0xff000 proc_ids = list() link_ids = list() for i in range(18): proc_ids.append(i) for i in range(6): link_ids.append(i) multicast_entries = list() for i in range(5): multicast_entries.append( MulticastRoutingEntry(key_combo + i, mask + i, proc_ids, link_ids, True)) mrt = MulticastRoutingTable(0, 0, multicast_entries) self.assertEqual(mrt.x, 0) self.assertEqual(mrt.y, 0) mre = mrt.multicast_routing_entries for entry in mre: self.assertIn(entry, multicast_entries) self.assertEqual(len(mre), len(multicast_entries)) for i in range(5): self.assertEqual( mrt.get_multicast_routing_entry_by_routing_entry_key( key_combo + i, mask + i), multicast_entries[i]) self.assertEqual(mrt.get_multicast_routing_entry_by_routing_entry_key( key_combo + 5, mask + 5), None) self.assertEqual(mrt.get_multicast_routing_entry_by_routing_entry_key( key_combo - 1, mask - 1), None)
def _merge_routes(self, router_table, previous_masks): merged_routes = MulticastRoutingTable(router_table.x, router_table.y) keys_merged = set() entries = router_table.multicast_routing_entries for router_entry in entries: if router_entry.routing_entry_key in keys_merged: continue # print "key =", hex(router_entry.routing_entry_key) mask = router_entry.mask if mask & 0xFFFF0000L == 0xFFFF0000L: merge_done = False for extra_bits in self._get_merge_masks(mask, previous_masks): new_mask = 0xFFFF0000L | extra_bits # print "trying mask =", hex(new_mask), hex(extra_bits) new_key = router_entry.routing_entry_key & new_mask new_n_keys = ~new_mask & 0xFFFFFFFFL new_last_key = new_key + new_n_keys # Check that all the cores on this chip have the same route # as this is the only way we can merge here mergable = True potential_merges = set() for router_entry_2 in entries: key = router_entry_2.routing_entry_key n_keys = ~router_entry_2.mask & 0xFFFFFFFFL last_key = key + n_keys masked_key = (router_entry_2.routing_entry_key & new_mask) overlap = (min(new_last_key, last_key) - max(new_key, key)) > 0 in_range = new_key <= key and new_last_key >= last_key if (new_key == masked_key and (not in_range or (router_entry_2.routing_entry_key in keys_merged) or (router_entry.processor_ids != router_entry_2.processor_ids) or (router_entry.link_ids != router_entry_2.link_ids))): # print( # " ", hex(key), "and", hex(key2), # "have mismatched routes") mergable = False break elif new_key == masked_key: # print( # " ", hex(key), "and", hex(key2), # "can be merged") potential_merges.add(router_entry_2) elif overlap: mergable = False break if mergable and len(potential_merges) > 1: # print("Merging", [ # hex(route.routing_entry_key) # for route in potential_merges], "using mask =", # hex(new_mask), "and key =", hex(masked_key), # "and route =", router_entry.processor_ids, # router_entry.link_ids) # if masked_key in merged_routes: # raise Exception( # "Attempting to merge an existing key") merged_routes.add_mutlicast_routing_entry( MulticastRoutingEntry(new_key, new_mask, router_entry.processor_ids, router_entry.link_ids, defaultable=False)) keys_merged.update([ route.routing_entry_key for route in potential_merges ]) merge_done = True break if not merge_done: # print "Was not able to merge", hex(key) merged_routes.add_mutlicast_routing_entry(router_entry) keys_merged.add(router_entry.routing_entry_key) else: merged_routes.add_mutlicast_routing_entry(router_entry) keys_merged.add(router_entry.routing_entry_key)
def _merge_routes(self, router_table, previous_masks): merged_routes = MulticastRoutingTable(router_table.x, router_table.y) # Order the routes by key entries = sorted( router_table.multicast_routing_entries, key=lambda entry: entry.routing_entry_key) # Find adjacent entries that can be merged pos = 0 last_key_added = 0 while pos < len(entries): links = entries[pos].link_ids processors = entries[pos].processor_ids next_pos = pos + 1 # Keep going until routes are not the same or too many keys are # generated base_key = long(entries[pos].routing_entry_key) while (next_pos < len(entries) and entries[next_pos].link_ids == links and entries[next_pos].processor_ids == processors and (base_key & entries[next_pos].routing_entry_key) > last_key_added): base_key = ( base_key & entries[next_pos].routing_entry_key) next_pos += 1 next_pos -= 1 # print "Pre decision", hex(base_key) # If there is something to merge, merge it if possible merge_done = False if next_pos != pos: # print "At merge, base_key =", hex(base_key) # Find the next nearest power of 2 to the number of keys # that will be covered last_key = ( entries[next_pos].routing_entry_key + (~entries[next_pos].mask & 0xFFFFFFFFL)) n_keys = (last_key - base_key) + 1 next_log_n_keys = int(math.ceil(math.log(n_keys, 2))) n_keys = (1 << next_log_n_keys) - 1 n_keys_mask = ~n_keys & 0xFFFFFFFFL base_key = base_key & n_keys_mask if ((base_key + n_keys) >= last_key and base_key > last_key_added and (next_pos + 1 >= len(entries) or entries[pos].routing_entry_key + n_keys < entries[next_pos + 1].routing_entry_key)): # print "Merged into", hex(base_key), hex(n_keys_mask) # for i in range(pos, next_pos + 1): # print " ", hex(entries[i].routing_entry_key) last_key_added = base_key + n_keys # print " Last key:", hex(last_key_added) merged_routes.add_mutlicast_routing_entry( MulticastRoutingEntry( base_key, n_keys_mask, processors, links, defaultable=False)) pos = next_pos merge_done = True if not merge_done: merged_routes.add_mutlicast_routing_entry(entries[pos]) last_key_added = ( entries[pos].routing_entry_key + (~entries[pos].mask & 0xFFFFFFFFL)) # print "Not Merged", hex(entries[pos].routing_entry_key),\ # hex(entries[pos].mask) pos += 1 return merged_routes