def test_sata_link(self): s = Scheduler() sys = SpiNNakerSystem(s, 1000) num_channels = 2 dll = SATALink( s , num_channels # num_channels , 2 # sata_accept_period , 1 # sata_buffer_length , 40 # sata_latency , 10 # silistix_send_cycles , 5 # silistix_ack_cycles ) # Example packets packets = [SpiNNakerP2PPacket(sys, "Data %d"%n, (0,0), 1) for n in range(num_channels)] channels = [dll.get_channel_link(n) for n in range(num_channels)] it = s.run() it_next = 0 # Can only send initially while it.next() < it_next + 100: for c in channels: self.assertTrue(c.can_send()) self.assertFalse(c.can_receive()) it_next += 100 # Can send packets down each channel individually? for p,c in zip(packets,channels): # Put the packet in the channel self.assertTrue(c.can_send()) c.send(p) self.assertFalse(c.can_send()) while it.next() < it_next + 100: # Check nothing happens on the other channels for c_ in channels: if c != c_: self.assertTrue(c_.can_send()) self.assertFalse(c_.can_receive()) it_next += 100 # Check the packet arrived self.assertTrue(c.can_receive()) self.assertEqual(c.receive(), p) self.assertFalse(c.can_receive()) # Can send packets down each channels all at once? for p,c in zip(packets,channels): self.assertTrue(c.can_send()) c.send(p) self.assertFalse(c.can_send()) # Wait for them all to get there while it.next() < it_next + 100: pass it_next += 100 # Check the packets arrived for p,c in zip(packets,channels): self.assertTrue(c.can_receive()) self.assertEqual(c.receive(), p) self.assertFalse(c.can_receive()) # Can a single channel block while all others don't? while channels[0].can_send(): self.assertTrue(channels[0].can_send()) channels[0].send(p) self.assertFalse(channels[0].can_send()) # Wait for the packet to get buffered while it.next() < it_next + 100: pass it_next += 100 # Channel is blocked self.assertFalse(channels[0].can_send()) # Other channels are not for c in channels[1:]: self.assertTrue(c.can_send())
def __init__( self , scheduler , system , width , height , use_sata_links , sata_accept_period # SATALink , sata_buffer_length # SATALink , sata_latency # SATALink , silistix_send_cycles # SilistixLink , silistix_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 ): """ width is the number of three-board board-sets wide the system will be. height is the number of three-board board-sets tall the system will be. use_sata_links is a decision whether or not to use sata links to connect boards. If false, regular links are used. sata_accept_period see SATALink sata_buffer_length see SATALink sata_latency see SATALink silistix_send_cycles see SilistixLink silistix_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 self.width = width self.height = height # A dictionary { (x,y): SpiNNaker103, ... } of all contained boards. The # coordinates are relative to the bottom-leftmost board (which is not # wrapped around). A full board is two units wide and two units tall in this # coordinate system. self.boards = { } # The size of the mesh of chips: twelve chips per board set mesh_dimensions = (self.width * 12, self.height * 12) # Initially create all the boards for y in range(self.height): for x in range(self.width): # z is the index of the board within the set. 0 is the bottom left, 1 is # the top, 2 is the right for z in range(3): # Odd-rows start offset by one unit right, odd columns start offset one # unit up. board = SpiNNaker103( scheduler , system , silistix_send_cycles , silistix_ack_cycles , injection_buffer_length , router_period , wait_before_emergency , wait_before_drop , core_period , packet_prob , distance_std ) # The coordinates of a board within the set of boards x_coord = x*3 + z y_coord = y*3 + (3-z)%3 self.boards[(x_coord, y_coord)] = board # Set the board's position in terms of the whole system board.set_mesh_dimensions(*mesh_dimensions) x_mesh_coord = x_coord*4 y_mesh_coord = y_coord*4 board.set_mesh_position(x_mesh_coord, y_mesh_coord) # If the board is on a right/top edge, the right/top half of its chips are # actually on the left-hand-side/bottom of the system if x_coord == (self.width*3)-1: board.set_mesh_position_right(0, y_mesh_coord) if y_coord == (self.height*3)-1: # Plus one is due to the bottom edge of the hexagons being longer than # the left-edge board.set_mesh_position_top(x_mesh_coord+1, 0) # Now link every board with all those above and to the right for board_coords, board in self.boards.iteritems(): top_board_coords = ( (board_coords[0]+1) % (self.width*3) , (board_coords[1]+2) % (self.height*3) ) top_right_board_coords = ( (board_coords[0]+2) % (self.width*3) , (board_coords[1]+1) % (self.height*3) ) btm_right_board_coords = ( (board_coords[0]+1) % (self.width*3) , (board_coords[1]-1) % (self.height*3) ) # Create the links for these edges for other_coords, edge in ( (top_board_coords, topology.EDGE_TOP) , (top_right_board_coords, topology.EDGE_TOP_RIGHT) , (btm_right_board_coords, topology.EDGE_BOTTOM_RIGHT) ): other_board = self.boards[other_coords] if use_sata_links: # From board to other_board in_link = SATALink( self.scheduler , 8 # num_channels , sata_accept_period , sata_buffer_length , sata_latency , silistix_send_cycles , silistix_ack_cycles ) # From other_board to board out_link = SATALink( self.scheduler , 8 # num_channels , sata_accept_period , sata_buffer_length , sata_latency , silistix_send_cycles , silistix_ack_cycles ) # Link up each of the channels on this edge in both directions for channel in range(8): in_channel = in_link.get_channel_link(channel) out_channel = out_link.get_channel_link(channel) board.set_in_link(edge, channel, in_channel) board.set_out_link(edge, channel, out_channel) other_board.set_out_link(topology.opposite(edge), channel, in_channel) other_board.set_in_link(topology.opposite(edge), channel, out_channel) else: # Link up each of the channels on this edge in both directions with # SilistixLinks for channel in range(8): in_link = SilistixLink( self.scheduler , silistix_send_cycles , silistix_ack_cycles ) out_link = SilistixLink( self.scheduler , silistix_send_cycles , silistix_ack_cycles ) board.set_in_link(edge, channel, in_link) board.set_out_link(edge, channel, out_link) other_board.set_out_link(topology.opposite(edge), channel, in_link) other_board.set_in_link(topology.opposite(edge), channel, out_link)