def _build_data(self, routing_table): """ Convert the router table into the data needed by the router\ compressor c code. :param ~.MulticastRoutingTables routing_table: the pacman router table instance :return: The byte array of data :rtype: bytearray """ # write header data of the app ID to load the data, if to store # results in SDRAM and the router table entries data = b'' if self._compress_only_when_needed is None: data += _THREE_WORDS.pack( self._app_id, int(self._compress_as_much_as_possible), # Write the size of the table routing_table.number_of_entries) else: # Mundys compressor can not be changed so uses it own structure data += _FOUR_WORDS.pack( self._app_id, int(self._compress_only_when_needed), int(self._compress_as_much_as_possible), # Write the size of the table routing_table.number_of_entries) for entry in routing_table.multicast_routing_entries: data += _FOUR_WORDS.pack( entry.routing_entry_key, entry.mask, Router.convert_routing_table_entry_to_spinnaker_route(entry), make_source_hack(entry=entry)) return bytearray(data)
def _process_edge( self, placements, source_placement, net_graph, edge, chip_route_nets, machine, routing_by_partition, out_going_partition): dest_placement = placements.get_placement_of_vertex( edge.post_vertex) traversal = self._recursive_trace_to_destination( source_placement.x, source_placement.y, out_going_partition, dest_placement.x, dest_placement.y, machine, routing_by_partition) for (chip, entry) in traversal: route = Router.convert_routing_table_entry_to_spinnaker_route( entry) chip_route_nets[chip][route].append(out_going_partition) net_graph[out_going_partition] = set() # Add constraints to the net graph dependent on which nets take # different routes at this point. routes_in_chip = chip_route_nets[chip] for other_route, other_partitions in iteritems(routes_in_chip): if other_route != route: for other_partition in other_partitions: # This partition cannot share an identifier with any of # the other partitions who take a different route at # this point. if other_partition != out_going_partition: net_graph[out_going_partition].add(other_partition) net_graph[other_partition].add(out_going_partition)
def test_partition_with_more_sdram_than_default(self): """ test that the partitioner works when its machine is slightly malformed in that it has more SDRAM available """ n_processors = 18 (e, ne, n, w, _, _) = range(6) links = list() links.append(Link(0, 0, e, 0, 1)) _sdram = SDRAM(128 * (2**21)) links = list() links.append(Link(0, 0, e, 1, 1)) links.append(Link(0, 1, ne, 1, 0)) links.append(Link(1, 1, n, 0, 0)) links.append(Link(1, 0, w, 0, 1)) r = Router(links, False, 1024) ip = "192.162.240.253" chips = list() for x in range(5): for y in range(5): if x == y == 0: chips.append(Chip(x, y, n_processors, r, _sdram, 0, 0, ip)) else: chips.append(Chip(x, y, n_processors, r, _sdram, 0, 0)) self.machine = machine_from_chips(chips) splitter_partitioner(self.graph, self.machine, 3000, PreAllocatedResourceContainer())
def test_partition_with_more_sdram_than_default(self): """ test that the partitioner works when its machine is slightly malformed in that it has more sdram avilable """ self.setup() flops = 20000000 (e, _, n, w, _, s) = range(6) processors = list() for i in range(18): processors.append(Processor(i, flops)) links = list() links.append(Link(0, 0, 0, 0, 1, s, s)) _sdram = SDRAM(128 * (2**21)) links = list() links.append(Link(0, 0, 0, 1, 1, n, n)) links.append(Link(0, 1, 1, 1, 0, s, s)) links.append(Link(1, 1, 2, 0, 0, e, e)) links.append(Link(1, 0, 3, 0, 1, w, w)) r = Router(links, False, 100, 1024) ip = TestBasicPartitioner.TheTestAddress chips = list() for x in range(5): for y in range(5): chips.append(Chip(x, y, processors, r, _sdram, 0, 0, ip)) self.machine = Machine(chips, 0, 0) self.bp(self.graph, self.machine)
def _build_routing_table_data(self, app_id, routing_table): """ builds routing data as needed for the compressor cores :param int app_id: appid of the application to load entries with :param ~.AbsractMulticastRoutingTable routing_table: the uncompressed routing table :return: data array :rtype: bytearray """ data = b'' data += self._TWO_WORDS.pack(app_id, routing_table.number_of_entries) # sort entries based on generality sorted_routing_table = sorted( routing_table.multicast_routing_entries, key=lambda rt_entry: ordered_covering_generality( rt_entry.routing_entry_key, rt_entry.mask)) # write byte array for the sorted table for entry in sorted_routing_table: data += self._FOUR_WORDS.pack( entry.routing_entry_key, entry.mask, Router.convert_routing_table_entry_to_spinnaker_route(entry), make_source_hack(entry=entry)) return bytearray(data)
def test_partition_with_more_sdram_than_default(self): """ test that the partitioner works when its machine is slightly malformed in that it has more SDRAM available """ self.setup() n_processors = 18 (e, ne, n, w, _, _) = range(6) links = list() links.append(Link(0, 0, e, 0, 1)) _sdram = SDRAM(128 * (2**21)) links = list() links.append(Link(0, 0, e, 1, 1)) links.append(Link(0, 1, ne, 1, 0)) links.append(Link(1, 1, n, 0, 0)) links.append(Link(1, 0, w, 0, 1)) r = Router(links, False, 1024) ip = TestBasicPartitioner.TheTestAddress chips = list() for x in range(5): for y in range(5): if x == y == 0: chips.append(Chip(x, y, n_processors, r, _sdram, 0, 0, ip)) else: chips.append(Chip(x, y, n_processors, r, _sdram, 0, 0)) self.machine = machine_from_chips(chips) self.sp(self.graph, self.machine, 3000)
def __encode_route(self, entry): """ :param ~spinn_machine.MulticastRoutingEntry entry: :rtype: int """ route = self._app_id << _BIT_SHIFT_TO_MOVE_APP_ID route |= Router.convert_routing_table_entry_to_spinnaker_route(entry) return route
def create_virtual_chip(machine, link_data, virtual_chip_x, virtual_chip_y): # If the chip already exists, return the data if machine.is_chip_at(virtual_chip_x, virtual_chip_y): if not machine.get_chip_at(virtual_chip_x, virtual_chip_y).virtual: raise Exception( "Attempting to add virtual chip in place of a real chip") return # Create link to the virtual chip from the real chip virtual_link_id = (link_data.connected_link + 3) % 6 to_virtual_chip_link = Link( destination_x=virtual_chip_x, destination_y=virtual_chip_y, source_x=link_data.connected_chip_x, source_y=link_data.connected_chip_y, multicast_default_from=virtual_link_id, multicast_default_to=virtual_link_id, source_link_id=link_data.connected_link) # Create link to the real chip from the virtual chip from_virtual_chip_link = Link( destination_x=link_data.connected_chip_x, destination_y=link_data.connected_chip_y, source_x=virtual_chip_x, source_y=virtual_chip_y, multicast_default_from=link_data.connected_link, multicast_default_to=link_data.connected_link, source_link_id=virtual_link_id) # create the router links = [from_virtual_chip_link] router_object = Router( links=links, emergency_routing_enabled=False, clock_speed=Router.ROUTER_DEFAULT_CLOCK_SPEED, n_available_multicast_entries=sys.maxsize) # create the processors processors = list() for virtual_core_id in range(0, constants.CORES_PER_VIRTUAL_CHIP): processors.append(Processor.factory(virtual_core_id)) # connect the real chip with the virtual one connected_chip = machine.get_chip_at( link_data.connected_chip_x, link_data.connected_chip_y) connected_chip.router.add_link(to_virtual_chip_link) machine.add_chip(Chip( processors=processors, router=router_object, sdram=SDRAM(size=0), x=virtual_chip_x, y=virtual_chip_y, virtual=True, nearest_ethernet_x=None, nearest_ethernet_y=None))
def setUp(self): """ setup for all basic partitioner tests """ unittest_setup() self.vert1 = SimpleTestVertex(10, "New AbstractConstrainedVertex 1") self.vert1.splitter = SplitterSliceLegacy() self.vert2 = SimpleTestVertex(5, "New AbstractConstrainedVertex 2") self.vert2.splitter = SplitterSliceLegacy() self.vert3 = SimpleTestVertex(3, "New AbstractConstrainedVertex 3") self.vert3.splitter = SplitterSliceLegacy() self.edge1 = ApplicationEdge(self.vert1, self.vert2, label="First edge") self.edge2 = ApplicationEdge(self.vert2, self.vert1, label="Second edge") self.edge3 = ApplicationEdge(self.vert1, self.vert3, label="Third edge") self.verts = [self.vert1, self.vert2, self.vert3] self.edges = [self.edge1, self.edge2, self.edge3] self.graph = ApplicationGraph("Graph") self.graph.add_vertices(self.verts) self.graph.add_edges(self.edges, "foo") n_processors = 18 (e, ne, n, w, _, _) = range(6) links = list() links.append(Link(0, 0, e, 0, 1)) _sdram = SDRAM(128 * (2**20)) links = list() links.append(Link(0, 0, e, 1, 1)) links.append(Link(0, 1, ne, 1, 0)) links.append(Link(1, 1, n, 0, 0)) links.append(Link(1, 0, w, 0, 1)) r = Router(links, False, 1024) ip = TestBasicPartitioner.TheTestAddress chips = list() for x in range(5): for y in range(5): if x == y == 0: chips.append(Chip(x, y, n_processors, r, _sdram, 0, 0, ip)) else: chips.append(Chip(x, y, n_processors, r, _sdram, 0, 0)) self.machine = machine_from_chips(chips)
def create_virtual_chip(machine, link_data, virtual_chip_x, virtual_chip_y): """ Create a virtual chip on a real machine. :param ~spinn_machine.Machine machine: :param ~spinn_machine.link_data_objects.AbstractLinkData link_data: Describes the link from the real machine. :param int virtual_chip_x: Virtual chip coordinate :param int virtual_chip_y: Virtual chip coordinate """ # If the chip already exists, return the data if machine.is_chip_at(virtual_chip_x, virtual_chip_y): if not machine.get_chip_at(virtual_chip_x, virtual_chip_y).virtual: raise Exception( "Attempting to add virtual chip in place of a real chip") return # Create link to the virtual chip from the real chip virtual_link_id = (link_data.connected_link + 3) % 6 to_virtual_chip_link = Link(destination_x=virtual_chip_x, destination_y=virtual_chip_y, source_x=link_data.connected_chip_x, source_y=link_data.connected_chip_y, source_link_id=link_data.connected_link) # Create link to the real chip from the virtual chip from_virtual_chip_link = Link(destination_x=link_data.connected_chip_x, destination_y=link_data.connected_chip_y, source_x=virtual_chip_x, source_y=virtual_chip_y, source_link_id=virtual_link_id) # create the router links = [from_virtual_chip_link] router_object = Router(links=links, emergency_routing_enabled=False, n_available_multicast_entries=sys.maxsize) # connect the real chip with the virtual one connected_chip = machine.get_chip_at(link_data.connected_chip_x, link_data.connected_chip_y) connected_chip.router.add_link(to_virtual_chip_link) machine.add_virtual_chip( Chip(n_processors=constants.CORES_PER_VIRTUAL_CHIP, router=router_object, sdram=SDRAM(size=0), x=virtual_chip_x, y=virtual_chip_y, virtual=True, nearest_ethernet_x=None, nearest_ethernet_y=None))
def _add_routing_entry(self, route_no, offset, app_id, route, key, mask): # pylint: disable=too-many-arguments if route >= 0xFF000000: return if self._app_id is not None and self._app_id != app_id: return # Convert bit-set into list of (set) IDs processor_ids, link_ids = \ Router.convert_spinnaker_route_to_routing_ids(route) self._entries[route_no + offset] = MulticastRoutingEntry( key, mask, processor_ids, link_ids, False)
def test_creating_new_router(self): links = list() (e, ne, n, w, sw, s) = range(6) links.append(Link(0, 0, 0, 1, 1, n, n)) links.append(Link(0, 1, 1, 1, 0, s, s)) links.append(Link(1, 1, 2, 0, 0, e, e)) links.append(Link(1, 0, 3, 0, 1, w, w)) r = Router(links, False, 100, 1024) self.assertEqual(len(r), 4) for i in range(4): self.assertTrue(r.is_link(i)) self.assertTrue(i in r) self.assertEqual(r.get_link(i), links[i]) self.assertEqual(r[i], links[i]) self.assertEqual([l[0] for l in r], [0, 1, 2, 3]) self.assertEqual([l[1].source_link_id for l in r], [0, 1, 2, 3]) self.assertFalse(r.emergency_routing_enabled) self.assertEqual(r.clock_speed, 100) self.assertEqual(r.n_available_multicast_entries, 1024) self.assertFalse(r.is_link(-1)) self.assertFalse(r.is_link(links.__len__() + 1)) self.assertEqual(r.get_link(-1), None) self.assertEqual(r.get_link(links.__len__() + 1), None) self.assertEqual(r.get_neighbouring_chips_coords(), [{'x': 1, 'y': 1}, {'x': 1, 'y': 0}, {'x': 0, 'y': 0}, {'x': 0, 'y': 1}]) self.assertEqual( r.__repr__(), "[Router: clock_speed=0 MHz, emergency_routing=False, " "available_entries=1024, links=[[Link: source_x=0, source_y=0, " "source_link_id=0, destination_x=1, destination_y=1, " "default_from=2, default_to=2], [Link: source_x=0, source_y=1, " "source_link_id=1, destination_x=1, destination_y=0, " "default_from=5, default_to=5], [Link: source_x=1, source_y=1, " "source_link_id=2, destination_x=0, destination_y=0, " "default_from=0, default_to=0], [Link: source_x=1, source_y=0, " "source_link_id=3, destination_x=0, destination_y=1, " "default_from=3, default_to=3]]]")
def load_fixed_route(self, x, y, fixed_route, app_id=0): """ :param int x: The x-coordinate of the chip, between 0 and 255; this is not checked due to speed restrictions. :param int y: The y-coordinate of the chip, between 0 and 255; this is not checked due to speed restrictions. :param ~spinn_machine.FixedRouteEntry fixed_route: the fixed route entry :param int app_id: The ID of the application with which to associate the routes. If not specified, defaults to 0. """ route_entry = \ Router.convert_routing_table_entry_to_spinnaker_route(fixed_route) self._send_request(FixedRouteInit(x, y, route_entry, app_id)) self._finish() self.check_for_error()
def setup(self): """ setup for all basic partitioner tests """ self.vert1 = SimpleTestVertex(10, "New AbstractConstrainedVertex 1") self.vert2 = SimpleTestVertex(5, "New AbstractConstrainedVertex 2") self.vert3 = SimpleTestVertex(3, "New AbstractConstrainedVertex 3") self.edge1 = ApplicationEdge(self.vert1, self.vert2, None, "First edge") self.edge2 = ApplicationEdge(self.vert2, self.vert1, None, "Second edge") self.edge3 = ApplicationEdge(self.vert1, self.vert3, None, "Third edge") self.verts = [self.vert1, self.vert2, self.vert3] self.edges = [self.edge1, self.edge2, self.edge3] self.graph = ApplicationGraph("Graph") self.graph.add_vertices(self.verts) self.graph.add_edges(self.edges, "foo") flops = 200000000 (e, _, n, w, _, s) = range(6) processors = list() for i in range(18): processors.append(Processor(i, flops)) links = list() links.append(Link(0, 0, 0, 0, 1, s, s)) _sdram = SDRAM(128 * (2**20)) links = list() links.append(Link(0, 0, 0, 1, 1, n, n)) links.append(Link(0, 1, 1, 1, 0, s, s)) links.append(Link(1, 1, 2, 0, 0, e, e)) links.append(Link(1, 0, 3, 0, 1, w, w)) r = Router(links, False, 100, 1024) ip = TestBasicPartitioner.TheTestAddress chips = list() for x in range(5): for y in range(5): chips.append(Chip(x, y, processors, r, _sdram, 0, 0, ip)) self.machine = Machine(chips, 0, 0) self.bp = BasicPartitioner()
def test_partition_with_barely_sufficient_space(self): """ test that partitioning will work when close to filling the machine """ self.setup() n_processors = 18 (e, ne, n, w, _, _) = range(6) links = list() links.append(Link(0, 0, e, 0, 1)) _sdram = SDRAM(2**12) links = list() links.append(Link(0, 0, e, 1, 1)) links.append(Link(0, 1, ne, 1, 0)) links.append(Link(1, 1, n, 0, 0)) links.append(Link(1, 0, w, 0, 1)) r = Router(links, False, 1024) ip = "192.162.240.253" chips = list() for x in range(5): for y in range(5): if x == y == 0: chips.append(Chip(x, y, n_processors, r, _sdram, 0, 0, ip)) else: chips.append(Chip(x, y, n_processors, r, _sdram, 0, 0)) self.machine = machine_from_chips(chips) n_neurons = 17 * 5 * 5 singular_vertex = SimpleTestVertex(n_neurons, "Large vertex", max_atoms_per_core=1) singular_vertex.splitter = SplitterSliceLegacy() self.assertEqual(singular_vertex._model_based_max_atoms_per_core, 1) self.graph = ApplicationGraph("Graph with large vertex") self.graph.add_vertex(singular_vertex) graph, _ = self.bp( self.graph, self.machine, plan_n_time_steps=100, pre_allocated_resources=PreAllocatedResourceContainer()) self.assertEqual(singular_vertex._model_based_max_atoms_per_core, 1) self.assertEqual(len(list(graph.vertices)), n_neurons)
def load_routes(self, x, y, routes, app_id): """ :param int x: :param int y: :param list(~spinn_machine.MulticastRoutingEntry) routes: :param int app_id: """ # Create the routing data - 16 bytes per entry plus one for the end # entry routing_data = bytearray(16 * (len(routes) + 1)) n_entries = 0 for route in routes: route_entry = \ Router.convert_routing_table_entry_to_spinnaker_route(route) _ROUTE_PATTERN.pack_into( routing_data, n_entries * 16, n_entries, route_entry, route.routing_entry_key, route.mask) n_entries += 1 # Add an entry to mark the end _END_PATTERN.pack_into( routing_data, n_entries * 16, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF) # Upload the data process = WriteMemoryProcess(self._conn_selector) process.write_memory_from_bytearray( x, y, 0, _TABLE_ADDRESS, routing_data, 0, len(routing_data)) # Allocate space in the router table self._send_request(RouterAlloc(x, y, app_id, n_entries), self.__handle_router_alloc_response) self._finish() self.check_for_error() if self._base_address == 0: raise SpinnmanInvalidParameterException( "Allocation base address", str(self._base_address), "Not enough space to allocate the entries") # Load the entries self._send_request( RouterInit( x, y, n_entries, _TABLE_ADDRESS, self._base_address, app_id)) self._finish() self.check_for_error()
def test_allocate_resources_when_chip_used(self): router = Router([]) sdram = SDRAM() empty_chip = Chip(0, 0, 1, router, sdram, 0, 0, "127.0.0.1", virtual=False, tag_ids=[1]) machine = machine_from_chips([empty_chip]) resource_tracker = ResourceTracker(machine, plan_n_timesteps=None) with self.assertRaises(PacmanValueError): resource_tracker.allocate_resources( ResourceContainer(sdram=ConstantSDRAM(1024)))
def test_partition_with_insufficient_space(self): """ test that if there's not enough space, the test the partitioner will raise an error """ self.setup() n_processors = 18 (e, ne, n, w, _, _) = range(6) links = list() links.append(Link(0, 0, e, 0, 1)) _sdram = SDRAM(2**11) links = list() links.append(Link(0, 0, e, 1, 1)) links.append(Link(0, 1, ne, 1, 0)) links.append(Link(1, 1, n, 0, 0)) links.append(Link(1, 0, w, 0, 1)) r = Router(links, False, 1024) ip = "192.162.240.253" chips = list() for x in range(5): for y in range(5): if x == y == 0: chips.append(Chip(x, y, n_processors, r, _sdram, 0, 0, ip)) else: chips.append(Chip(x, y, n_processors, r, _sdram, 0, 0)) self.machine = machine_from_chips(chips) large_vertex = SimpleTestVertex(3000, "Large vertex", max_atoms_per_core=1) large_vertex.splitter = SplitterSliceLegacy() self.assertEqual(large_vertex._model_based_max_atoms_per_core, 1) self.graph = ApplicationGraph("Graph with large vertex") self.graph.add_vertex(large_vertex) with self.assertRaises(PacmanValueError): self.bp(self.graph, self.machine, 3000, PreAllocatedResourceContainer())
def load_fixed_route(self, x, y, fixed_route, app_id=0): """ Load a fixed route routing entry onto a chip. :param x: The x-coordinate of the chip, between 0 and 255; \ this is not checked due to speed restrictions. :type x: int :param y: The y-coordinate of the chip, between 0 and 255; \ this is not checked due to speed restrictions. :type y: int :param fixed_route: the fixed route entry :param app_id: The ID of the application with which to associate the\ routes. If not specified, defaults to 0. :type app_id: int :rtype: None """ route_entry = \ Router.convert_routing_table_entry_to_spinnaker_route(fixed_route) self._send_request(FixedRouteInit(x, y, route_entry, app_id)) self._finish() self.check_for_error()
def test_partition_with_insufficient_space(self): """ test that if there's not enough space, the test the partitioner will raise an error """ self.setup() flops = 1000 (e, _, n, w, _, s) = range(6) processors = list() for i in range(18): processors.append(Processor(i, flops)) links = list() links.append(Link(0, 0, 0, 0, 1, s, s)) _sdram = SDRAM(2**11) links = list() links.append(Link(0, 0, 0, 1, 1, n, n)) links.append(Link(0, 1, 1, 1, 0, s, s)) links.append(Link(1, 1, 2, 0, 0, e, e)) links.append(Link(1, 0, 3, 0, 1, w, w)) r = Router(links, False, 100, 1024) ip = TestBasicPartitioner.TheTestAddress chips = list() for x in range(5): for y in range(5): chips.append(Chip(x, y, processors, r, _sdram, 0, 0, ip)) self.machine = Machine(chips, 0, 0) large_vertex = SimpleTestVertex(3000, "Large vertex", max_atoms_per_core=1) self.assertEqual(large_vertex._model_based_max_atoms_per_core, 1) self.graph = ApplicationGraph("Graph with large vertex") self.graph.add_vertex(large_vertex) with self.assertRaises(PacmanPartitionException): self.bp(self.graph, self.machine)
def test_partition_with_barely_sufficient_space(self): """ test that partitioning will work when close to filling the machine """ self.setup() flops = 20000000 (e, _, n, w, _, s) = range(6) processors = list() for i in range(18): processors.append(Processor(i, flops)) links = list() links.append(Link(0, 0, 0, 0, 1, s, s)) _sdram = SDRAM(2**12) links = list() links.append(Link(0, 0, 0, 1, 1, n, n)) links.append(Link(0, 1, 1, 1, 0, s, s)) links.append(Link(1, 1, 2, 0, 0, e, e)) links.append(Link(1, 0, 3, 0, 1, w, w)) r = Router(links, False, 100, 1024) ip = TestBasicPartitioner.TheTestAddress chips = list() for x in range(5): for y in range(5): chips.append(Chip(x, y, processors, r, _sdram, 0, 0, ip)) self.machine = Machine(chips, 0, 0) singular_vertex = SimpleTestVertex(450, "Large vertex", max_atoms_per_core=1) self.assertEqual(singular_vertex._model_based_max_atoms_per_core, 1) self.graph = ApplicationGraph("Graph with large vertex") self.graph.add_vertex(singular_vertex) graph, _, _ = self.bp(self.graph, self.machine) self.assertEqual(singular_vertex._model_based_max_atoms_per_core, 1) self.assertEqual(len(list(graph.vertices)), 450)
def load_routes(self, x, y, routes, app_id): # Create the routing data - 16 bytes per entry plus one for the end # entry routing_data = bytearray(16 * (len(routes) + 1)) n_entries = 0 for route in routes: route_entry = \ Router.convert_routing_table_entry_to_spinnaker_route(route) _ROUTE_PATTERN.pack_into( routing_data, n_entries * 16, n_entries, route_entry, route.routing_entry_key, route.mask) n_entries += 1 # Add an entry to mark the end _END_PATTERN.pack_into( routing_data, n_entries * 16, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF) # Upload the data table_address = 0x67800000 process = WriteMemoryProcess(self._next_connection_selector) process.write_memory_from_bytearray( x, y, 0, table_address, routing_data, 0, len(routing_data)) # Allocate space in the router table self._send_request(RouterAlloc(x, y, app_id, n_entries), self.handle_router_alloc_response) self._finish() self.check_for_error() if self._base_address == 0: raise SpinnmanInvalidParameterException( "Allocation base address", str(self._base_address), "Not enough space to allocate the entries") # Load the entries self._send_request( RouterInit( x, y, n_entries, table_address, self._base_address, app_id)) self._finish() self.check_for_error()
def _make_router(self, chip_info, machine): """ :param ChipSummaryInfo chip_info: :param ~spinn_machine.Machine machine: :rtype: ~spinn_machine.Router """ links = list() for link in chip_info.working_links: dest_xy = machine.xy_over_link(chip_info.x, chip_info.y, link) if dest_xy in self._chip_info: links.append( Link(chip_info.x, chip_info.y, link, dest_xy[0], dest_xy[1])) else: logger.warning( "Link {},{}:{} points to {} but that is not included ", chip_info.x, chip_info.y, link, dest_xy) return Router(links=links, n_available_multicast_entries=( chip_info.n_free_multicast_routing_entries))
def _build_data( self, routing_table, app_id, compress_only_when_needed, compress_as_much_as_possible): """ Convert the router table into the data needed by the router\ compressor c code. :param routing_table: the pacman router table instance :param app_id: the application ID to load the entries in by :param compress_only_when_needed:\ If True, the compressor will only compress if the table doesn't\ fit in the current router space, otherwise it will just load\ the table :type compress_only_when_needed: bool :param compress_as_much_as_possible:\ If False, the compressor will only reduce the table until it fits\ in the router space, otherwise it will try to reduce until it\ until it can't reduce it any more :type compress_as_much_as_possible: bool :return: The byte array of data """ # write header data of the app ID to load the data, if to store # results in SDRAM and the router table entries data = b'' data += _FOUR_WORDS.pack( app_id, int(compress_only_when_needed), int(compress_as_much_as_possible), # Write the size of the table routing_table.number_of_entries) for entry in routing_table.multicast_routing_entries: data += _FOUR_WORDS.pack( entry.routing_entry_key, entry.mask, Router.convert_routing_table_entry_to_spinnaker_route(entry), self._make_source_hack(entry)) return bytearray(data)
def test_convert_to_route(self): e = MulticastRoutingEntry(28, 60, [4, 5, 7], [1, 3, 5], True) r = Router.convert_routing_table_entry_to_spinnaker_route(e) self.assertEqual(r, 11306)
def setUp(self): ####################################################################### # Setting up vertices, edges and graph # ####################################################################### self.vert1 = T_AppVertex(100, "New AbstractConstrainedVertex 1") self.vert2 = T_AppVertex(5, "New AbstractConstrainedVertex 2") self.vert3 = T_AppVertex(3, "New AbstractConstrainedVertex 3") self.edge1 = ApplicationEdge(self.vert1, self.vert2, "First edge") self.edge2 = ApplicationEdge(self.vert2, self.vert1, "Second edge") self.edge3 = ApplicationEdge(self.vert1, self.vert3, "Third edge") self.verts = [self.vert1, self.vert2, self.vert3] self.edges = [self.edge1, self.edge2, self.edge3] self.graph = ApplicationGraph("Graph", self.verts, self.edges) ####################################################################### # Setting up machine # ####################################################################### flops = 1000 (_, _, n, _, _, s) = range(6) processors = list() for i in range(18): processors.append(Processor(i, flops)) _sdram = SDRAM(128 * (2**20)) ip = "192.168.240.253" chips = list() for x in range(10): for y in range(10): links = list() links.append(Link(x, y, 0, (x + 1) % 10, y, n, n)) links.append(Link(x, y, 1, (x + 1) % 10, (y + 1) % 10, s, s)) links.append(Link(x, y, 2, x, (y + 1) % 10, n, n)) links.append(Link(x, y, 3, (x - 1) % 10, y, s, s)) links.append(Link(x, y, 4, (x - 1) % 10, (y - 1) % 10, n, n)) links.append(Link(x, y, 5, x, (y - 1) % 10, s, s)) r = Router(links, False, 100, 1024) chips.append(Chip(x, y, processors, r, _sdram, ip)) self.machine = Machine(chips) ####################################################################### # Setting up graph and graph_mapper # ####################################################################### self.vertices = list() self.vertex1 = T_MachineVertex(0, 1, get_resources_used_by_atoms(0, 1, []), "First vertex") self.vertex2 = T_MachineVertex(1, 5, get_resources_used_by_atoms(1, 5, []), "Second vertex") self.vertex3 = T_MachineVertex(5, 10, get_resources_used_by_atoms(5, 10, []), "Third vertex") self.vertex4 = T_MachineVertex( 10, 100, get_resources_used_by_atoms(10, 100, []), "Fourth vertex") self.vertices.append(self.vertex1) self.vertices.append(self.vertex2) self.vertices.append(self.vertex3) self.vertices.append(self.vertex4) self.edges = list() self.graph = MachineGraph(self.vertices, self.edges) self.graph_mapper = GraphMapper() self.graph_mapper.add_vertices(self.vertices)
def _build_cluster_graph( self, outgoing_partitions, placements, machine, routing_tables): """Build a graph the nodes of which represent the chips on which the vertices representing a single operator have been placed and the edges of which represent constraints upon which of these chips may share routing identifiers for the purposes of this set of vertices. :param outgoing_partitions : list of outgoing partitions :param placements: :param machine: :param routing_tables: Returns ------- {(x, y): {(x, y), ...}, ...} An adjacency list representation of the graph described above. """ # Adjacency list represent of the graph cluster_graph = defaultdict(set) for outgoing_partition in outgoing_partitions: # Build up a dictionary which maps each chip to a mapping of the # routes from this chip to the source cluster of the multicast # nets which take these routes. This will allow us to determine # which clusters need to be uniquely identified. chips_routes_clusters = defaultdict(lambda: defaultdict(set)) source_placement = placements.get_placement_of_vertex( outgoing_partition.pre_vertex) for edge in outgoing_partition.edges: dest_placement = placements.get_placement_of_vertex( edge.post_vertex) path = self._recursive_trace_to_destination( source_placement.x, source_placement.y, outgoing_partition, dest_placement.x, dest_placement.y, machine, routing_tables) # Ensure every cluster is in the graph source_chip = machine.get_chip_at( source_placement.x, source_placement.y) for (chip, entry) in path: route = ( Router.convert_routing_table_entry_to_spinnaker_route( entry)) # Add this cluster to the set of clusters whose net takes # this route at this point. chips_routes_clusters[chip][route].add(source_chip) # Add constraints to the cluster graph dependent on which # multicast nets take different routes at this point. routes_from_chip = chips_routes_clusters[chip] for other_route, clusters in iteritems(routes_from_chip): # We care about different routes if other_route != route: for cluster in clusters: # This cluster cannot share an identifier with # any of the clusters whose nets take a # different route at this point. cluster_graph[source_chip].add(cluster) cluster_graph[cluster].add(source_chip) return cluster_graph
def __encode_route(self, entry): route = self._app_id << _BIT_SHIFT_TO_MOVE_APP_ID route |= Router.convert_routing_table_entry_to_spinnaker_route(entry) return route