def make_multi_board_torus(width = 1, height = 1, layers = 4, num_cores = 18): """ Produce a system containing multiple boards arranged as a given number of "threeboards" wide and high arrangement of of boards with the given number of layers. Defaults to a single threeboard system of 48-node boards with 18 cores. Returns a dict {(x,y): (router, cores), ...}. """ chips = {} width_nodes = width*12 height_nodes = height*12 for (board_x, board_y, board_z) in topology.threeboards(width, height): assert(board_z == 0) for (x,y) in topology.hexagon(layers): x += (board_x*4 ) + (board_y*4) y += (board_x*-4) + (board_y*8) x %= width_nodes y %= height_nodes chips[(x,y)] = make_chip((x,y), (board_x,board_y), num_cores) fully_connect_chips(chips, wrap_around = True) return chips
def make_multi_board_torus(width=1, height=1, layers=4, num_cores=18): """ Produce a system containing multiple boards arranged as a given number of "threeboards" wide and high arrangement of of boards with the given number of layers. Defaults to a single threeboard system of 48-node boards with 18 cores. Returns a dict {(x,y): (router, cores), ...}. """ chips = {} width_nodes = width * 12 height_nodes = height * 12 for (board_x, board_y, board_z) in topology.threeboards(width, height): assert (board_z == 0) for (x, y) in topology.hexagon(layers): x += (board_x * 4) + (board_y * 4) y += (board_x * -4) + (board_y * 8) x %= width_nodes y %= height_nodes chips[(x, y)] = make_chip((x, y), (board_x, board_y), num_cores) fully_connect_chips(chips, wrap_around=True) return chips
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_make_hexagonal_board(self): """ Test that model.make_hexagonal_board creates the appropriate formation of chips. """ for layers in [2,3,4]: chips = model.make_hexagonal_board(layers) ref_positions = list(topology.hexagon(layers)) # Ensure correct number of nodes self.assertEqual(len(chips), len(ref_positions)) # Ensure nodes exist in correct places for ref_position in ref_positions: self.assertIn(ref_position, chips.keys())
def make_hexagonal_board(layers = 4, board = (0,0), num_cores = 18): """ Produce a system containing a hexagonal system of chips (without wrap-around links) of a given number of layers. Defaults to a 4-layer (48 chip) board (like the SpiNN-4/SpiNN-5 boards). Returns a dict {(x,y): (router, cores), ...}. """ chips = {} for position in topology.hexagon(layers): chips[position] = make_chip(position, board, num_cores) fully_connect_chips(chips) return chips
def make_hexagonal_board(layers=4, board=(0, 0), num_cores=18): """ Produce a system containing a hexagonal system of chips (without wrap-around links) of a given number of layers. Defaults to a 4-layer (48 chip) board (like the SpiNN-4/SpiNN-5 boards). Returns a dict {(x,y): (router, cores), ...}. """ chips = {} for position in topology.hexagon(layers): chips[position] = make_chip(position, board, num_cores) fully_connect_chips(chips) return chips
def test_hexagon(self): it = topology.hexagon(2) # Inner layer self.assertEqual(it.next(), ( 0, 0)) self.assertEqual(it.next(), (-1, 0)) self.assertEqual(it.next(), ( 0, 1)) # Outer layer self.assertEqual(it.next(), ( 1, 1)) self.assertEqual(it.next(), ( 1, 0)) self.assertEqual(it.next(), ( 0,-1)) self.assertEqual(it.next(), (-1,-1)) self.assertEqual(it.next(), (-2,-1)) self.assertEqual(it.next(), (-2, 0)) self.assertEqual(it.next(), (-1, 1)) self.assertEqual(it.next(), ( 0, 2)) self.assertEqual(it.next(), ( 1, 2)) # Stop now self.assertRaises(StopIteration, it.next)
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)