예제 #1
0
    def test_new_multicast_routing_tables(self):
        key_combo = 0xff35
        mask = 0xffff
        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_entries1 = MulticastRoutingEntry(key_combo, mask, proc_ids,
                                                   link_ids, True)
        multicast_entries2 = MulticastRoutingEntry(key_combo - 1, mask - 1,
                                                   proc_ids, link_ids, True)
        mrt = list()

        t1 = UnCompressedMulticastRoutingTable(0, 0, [multicast_entries1])
        t2 = UnCompressedMulticastRoutingTable(1, 0, [multicast_entries2])
        mrt.append(t1)
        mrt.append(t2)
        tables = MulticastRoutingTables(mrt)
        retrieved_tables = tables.routing_tables
        self.assertEqual(len(retrieved_tables), len(mrt))
        for tab in retrieved_tables:
            self.assertIn(tab, mrt)

        self.assertEqual(tables.get_routing_table_for_chip(0, 0), t1)
        self.assertEqual(tables.get_routing_table_for_chip(1, 0), t2)
        self.assertEqual(tables.get_routing_table_for_chip(2, 0), None)

        json_obj = to_json(tables)
        file_format_schemas.validate(json_obj, "routing_tables.json")
        new_tables = from_json(json_obj)
        self.assertEqual(new_tables.get_routing_table_for_chip(0, 0), t1)
        self.assertEqual(new_tables.get_routing_table_for_chip(1, 0), t2)
        self.assertEqual(new_tables.get_routing_table_for_chip(2, 0), None)
    def test_new_multicast_routing_tables(self):
        key_combo = 0xff35
        mask = 0xffff
        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_entries1 = MulticastRoutingEntry(
            key_combo, mask, proc_ids, link_ids, True)
        multicast_entries2 = MulticastRoutingEntry(
            key_combo - 1, mask - 1, proc_ids, link_ids, True)
        mrt = list()

        t1 = MulticastRoutingTable(0, 0, [multicast_entries1])
        t2 = MulticastRoutingTable(1, 0, [multicast_entries2])
        mrt.append(t1)
        mrt.append(t2)
        tables = MulticastRoutingTables(mrt)
        retrieved_tables = tables.routing_tables
        self.assertEqual(len(retrieved_tables), len(mrt))
        for tab in retrieved_tables:
            self.assertIn(tab, mrt)

        self.assertEqual(tables.get_routing_table_for_chip(0, 0), t1)
        self.assertEqual(tables.get_routing_table_for_chip(1, 0), t2)
        self.assertEqual(tables.get_routing_table_for_chip(2, 0), None)
    def test_new_multicast_routing_tables(self):
        key_combo = 0xff35
        mask = 0xffff
        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_entries1 = MulticastRoutingEntry(key_combo, mask, proc_ids,
                                                   link_ids, True)
        multicast_entries2 = MulticastRoutingEntry(key_combo - 1, mask - 1,
                                                   proc_ids, link_ids, True)
        mrt = list()

        t1 = MulticastRoutingTable(0, 0, [multicast_entries1])
        t2 = MulticastRoutingTable(1, 0, [multicast_entries2])
        mrt.append(t1)
        mrt.append(t2)
        tables = MulticastRoutingTables(mrt)
        retrieved_tables = tables.routing_tables
        self.assertEqual(len(retrieved_tables), len(mrt))
        for tab in retrieved_tables:
            self.assertIn(tab, mrt)

        self.assertEqual(tables.get_routing_table_for_chip(0, 0), t1)
        self.assertEqual(tables.get_routing_table_for_chip(1, 0), t2)
        self.assertEqual(tables.get_routing_table_for_chip(2, 0), None)
class SystemMulticastRoutingGenerator(object):
    """ Generates routing table entries used by the data in processes with the\
        extra monitor cores.

    :param ~spinn_machine.Machine machine:
    :param extra_monitor_cores:
    :type extra_monitor_cores:
        dict(tuple(int,int),ExtraMonitorSupportMachineVertex)
    :param ~pacman.model.placements.Placements placements:
    :return: routing tables, destination-to-key map,
        board-locn-to-timeout-key map
    :rtype: tuple(MulticastRoutingTables,
        dict(tuple(int,int),int), dict(tuple(int,int),int))
    """
    __slots__ = ["_monitors", "_machine", "_key_to_destination_map",
                 "_placements", "_routing_tables", "_time_out_keys_by_board"]

    def __call__(self, machine, extra_monitor_cores, placements):
        """
        :param ~spinn_machine.Machine machine:
        :param dict(tuple(int,int),ExtraMonitorSupportMachineVertex) \
                extra_monitor_cores:
        :param ~pacman.model.placements.Placements placements:
        :rtype: tuple(MulticastRoutingTables,
            dict(tuple(int,int),int), dict(tuple(int,int),int))
        """
        # pylint: disable=attribute-defined-outside-init
        self._machine = machine
        self._placements = placements
        self._monitors = extra_monitor_cores
        self._routing_tables = MulticastRoutingTables()
        self._key_to_destination_map = dict()
        self._time_out_keys_by_board = dict()

        # create progress bar
        progress = ProgressBar(
            machine.ethernet_connected_chips,
            "Generating routing tables for data in system processes")

        for ethernet_chip in progress.over(machine.ethernet_connected_chips):
            tree = self._generate_routing_tree(ethernet_chip)
            self._add_routing_entries(ethernet_chip, tree)

        return (self._routing_tables, self._key_to_destination_map,
                self._time_out_keys_by_board)

    def _generate_routing_tree(self, ethernet_chip):
        """ Generates a map for each chip to over which link it gets its data.

        :param ~spinn_machine.Chip ethernet_chip:
        :return: Map of chip.x, chip.y tp (source.x, source.y, source.link)
        :rtype: dict(tuple(int, int), tuple(int, int, int))
        """
        eth_x = ethernet_chip.x
        eth_y = ethernet_chip.y
        tree = dict()

        to_reach = set(
            self._machine.get_existing_xys_by_ethernet(eth_x, eth_y))
        reached = set()
        reached.add((eth_x, eth_y))
        to_reach.remove((eth_x, eth_y))
        found = set()
        found.add((eth_x, eth_y))
        while len(to_reach) > 0:
            just_reached = found
            found = set()
            for x, y in just_reached:
                # Check links starting with the most direct from 0,0
                for link_id in [1, 0, 2, 5, 3, 4]:
                    # Get protential destination
                    destination = self._machine.xy_over_link(x, y, link_id)
                    # If it is useful
                    if destination in to_reach:
                        # check it actually exits
                        if self._machine.is_link_at(x, y, link_id):
                            # Add to tree and record chip reachable
                            tree[destination] = (x, y, link_id)
                            to_reach.remove(destination)
                            found.add(destination)
            if len(found) == 0:
                raise PacmanRoutingException(
                    "Unable to do data in routing on {}.".format(
                        ethernet_chip.ip_address))
        return tree

    def _add_routing_entry(self, x, y, key, processor_id=None, link_ids=None):
        """ Adds a routing entry on this chip, creating the table if needed.

        :param int x: chip.x
        :param int y: chip.y
        :param int key: The key to use
        :param int processor_id:
            placement.p of the monitor vertex if applicable
        :param int link_id: If of the link out if applicable
        """
        table = self._routing_tables.get_routing_table_for_chip(x, y)
        if table is None:
            table = UnCompressedMulticastRoutingTable(x, y)
            self._routing_tables.add_routing_table(table)
        if processor_id is None:
            processor_ids = []
        else:
            processor_ids = [processor_id]
        if link_ids is None:
            link_ids = []
        entry = MulticastRoutingEntry(
            routing_entry_key=key, mask=ROUTING_MASK,
            processor_ids=processor_ids, link_ids=link_ids, defaultable=False)
        table.add_multicast_routing_entry(entry)

    def _add_routing_entries(self, ethernet_chip, tree):
        """ Adds the routing entires based on the tree.

        For every chip with this ethernet:
            - A key is generated (and saved) for this chip.
            - A local route to the monitor core is added.
            - The tree is walked adding a route on each source to get here

        :param ~spinn_machine.Chip ethernet_chip:
            the ethernet chip to make entries for
        :param dict(tuple(int,int),tuple(int,int,int)) tree:
            map of chips and links
        """
        eth_x = ethernet_chip.x
        eth_y = ethernet_chip.y
        key = KEY_START_VALUE
        for (x, y) in self._machine.get_existing_xys_by_ethernet(
                eth_x, eth_y):
            self._key_to_destination_map[x, y] = key
            placement = self._placements.get_placement_of_vertex(
                self._monitors[x, y])
            self._add_routing_entry(x, y, key, processor_id=placement.p)
            while (x, y) in tree:
                x, y, link = tree[(x, y)]
                self._add_routing_entry(x, y, key, link_ids=[link])
            key += N_KEYS_PER_PARTITION_ID

        # accum links to make a broad cast
        links_per_chip = defaultdict(list)
        for chip_key in tree:
            x, y, link = tree[chip_key]
            links_per_chip[x, y].append(link)

        # add broadcast router timeout keys
        time_out_key = key
        for (x, y) in self._machine.get_existing_xys_by_ethernet(
                eth_x, eth_y):
            placement = self._placements.get_placement_of_vertex(
                self._monitors[x, y])
            self._add_routing_entry(
                x, y, time_out_key, processor_id=placement.p,
                link_ids=links_per_chip[x, y])
            # update tracker
            self._time_out_keys_by_board[(eth_x, eth_y)] = key
        key += N_KEYS_PER_REINJECTION_PARTITION