Example #1
0
	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())
Example #2
0
	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)