def get_packet_destination(self, packet, in_dir): """ Given a packet, return the (link, emergency_link) pair to which the packet should be sent. The emergency link may be the same as the regular link. """ if packet.emergency: assert(in_dir is not None) # The packet is being emergency-routed, send it to its original target # which is the link counter-clockwise to the link it arrived route = self.out_links[topology.next_ccw(in_dir)] return (route, route) elif packet.destination == self.mesh_position: # Packet was destined to end up at this node return (self.exit_link, self.exit_link) else: # Find the shortest path to the destination shortest_path = topology.get_path(topology.zero_pad(self.mesh_position), topology.zero_pad(packet.destination), self.mesh_dimensions) # Do direction-order-routing if shortest_path[0] > 0: direction = topology.EAST elif shortest_path[0] < 0: direction = topology.WEST elif shortest_path[1] > 0: direction = topology.NORTH elif shortest_path[1] < 0: direction = topology.SOUTH elif shortest_path[2] > 0: direction = topology.SOUTH_WEST elif shortest_path[2] < 0: direction = topology.NORTH_EAST else: assert(False) # The emergency route takes the link counter-clockwise to the intended # direction return (self.out_links[direction], self.out_links[topology.next_ccw(direction)])
def test_connections(self): # Try with several sizes for torus_size in SpiNNakerTorusTests.TORUS_SIZES: self.generate_torus(*torus_size) # Get a dictionary of chips to their locations chips = {} for board in self.torus.boards.itervalues(): for chip in board.chips.itervalues(): chips[chip.get_mesh_position()] = chip # Check each chip is connected with their neighbours N, NE, W for pos, chip in chips.iteritems(): for direction in [topology.NORTH, topology.NORTH_EAST, topology.WEST]: other_pos = topology.to_xy( topology.add_direction(topology.zero_pad(pos), direction)) other_chip = chips[( other_pos[0]%(self.torus.width*12) , other_pos[1]%(self.torus.height*12) , )] other_direction = topology.opposite(direction) # Make sure we share links self.assertEqual(chip.get_in_link(direction), other_chip.get_out_link(other_direction)) self.assertEqual(chip.get_out_link(direction), other_chip.get_in_link(other_direction))
def test_hexagon_edge_link(self): # Get the set of edge nodes for a 4-layer hexagon all_nodes = set(topology.hexagon(4)) inner_nodes = set(topology.hexagon(3)) outer_nodes = all_nodes - inner_nodes directions = [ topology.EAST, topology.NORTH_EAST, topology.NORTH, topology.WEST, topology.SOUTH_WEST, topology.SOUTH ] edges = [ topology.EDGE_TOP_LEFT, topology.EDGE_TOP, topology.EDGE_TOP_RIGHT, topology.EDGE_BOTTOM_RIGHT, topology.EDGE_BOTTOM, topology.EDGE_BOTTOM_LEFT, ] # Get the set of outward-facing links as (node_xy,direction) pairs outward_facing_links = [] for node in all_nodes: for direction in directions: # Get the node that this link would connect to facing_node = topology.to_xy( topology.add_direction(topology.zero_pad(node), direction)) # If that node isn't part of our set, it is an edge link if facing_node not in all_nodes: outward_facing_links.append((node, direction)) # Get the set of outward facing links according to the function under test all_links = [] for edge in edges: for num in range(8): all_links.append(topology.hexagon_edge_link(edge, num, 4)) # No duplicates self.assertEqual(len(all_links), len(set(all_links))) # The algorithm gets every outward facing edge self.assertEqual(set(all_links), set(outward_facing_links))
def test_chips(self): # A board should have chips in the correct locations and no repeats self.assertEqual(len(self.board.chips), 48) self.assertEqual(set(self.board.chips.iterkeys()), set(topology.hexagon(4))) # For all inputs & outputs, if there is a chip in that direction it must be # connected via a SilistixLink and if not it should be attached to a # DeadLink. for src_pos, src_chip in self.board.chips.iteritems(): for direction in ( topology.EAST , topology.NORTH_EAST , topology.NORTH , topology.WEST , topology.SOUTH_WEST , topology.SOUTH ): in_link = src_chip.get_in_link(direction) out_link = src_chip.get_out_link(direction) dst_pos = topology.to_xy(topology.add_direction(topology.zero_pad(src_pos), direction)) if dst_pos in self.board.chips: # There is a chip opposite this connection dst_chip = self.board.chips[dst_pos] direction = topology.opposite(direction) # Check that they have the same link (connected to opposite ports) self.assertEqual(out_link, dst_chip.get_in_link(direction)) self.assertEqual(in_link, dst_chip.get_out_link(direction)) # And that they're SilistixLinks self.assertEqual(type(in_link), SilistixLink) self.assertEqual(type(out_link), SilistixLink) else: # No adjacent chip so should be DeadLinks self.assertEqual(type(in_link), DeadLink) self.assertEqual(type(out_link), DeadLink)
def __init__( self , scheduler , system , link_send_cycles # SilistixLink , link_ack_cycles # SilistixLink , injection_buffer_length # SpiNNaker101 , router_period # SpiNNakerRouter , wait_before_emergency # SpiNNakerRouter , wait_before_drop # SpiNNakerRouter , core_period # SpiNNakerTrafficGenerator , packet_prob # SpiNNakerTrafficGenerator , distance_std = None # SpiNNakerTrafficGenerator ): """ link_send_cycles see SilistixLink link_ack_cycles see SilistixLink injection_buffer_length see SpiNNaker101 router_period see SpiNNakerRouter wait_before_emergency see SpiNNakerRouter wait_before_drop see SpiNNakerRouter core_period see SpiNNakerTrafficGenerator packet_prob see SpiNNakerTrafficGenerator distance_std see SpiNNakerTrafficGenerator """ self.scheduler = scheduler self.system = system # A dictionary { (x,y): SpiNNaker101, ... } of all contained chips. The # coordinates are relative to the central chip (created first in the # hexagon). self.chips = { } # Utility function to add a new chip to the chips dict. def add_chip(position): "Add a chip at the specified position" self.chips[position] = SpiNNaker101( self.scheduler , self.system , injection_buffer_length , router_period , wait_before_emergency , wait_before_drop , core_period , packet_prob , distance_std ) # Create the chips in a hexagonal pattern for position in topology.hexagon(4): add_chip(position) # Put SilistixLinks between them for src_pos, src_chip in self.chips.iteritems(): # Try and link this chip to all other neighbours which are towards the # top/right of the chip for direction in (topology.NORTH, topology.NORTH_EAST, topology.EAST): dst_pos = topology.to_xy( topology.add_direction(topology.zero_pad(src_pos), direction)) # If the chip exists, put links in this direction if dst_pos in self.chips: dst_chip = self.chips[dst_pos] in_link = SilistixLink(self.scheduler, link_send_cycles, link_ack_cycles) out_link = SilistixLink(self.scheduler, link_send_cycles, link_ack_cycles) src_chip.set_out_link(direction, out_link) src_chip.set_in_link(direction, in_link) dst_chip.set_in_link(topology.opposite(direction), out_link) dst_chip.set_out_link(topology.opposite(direction), in_link)