Exemple #1
0
	def setUp(self):
		# Before each test build a new scheduler, system and router
		self.scheduler = Scheduler()
		self.system    = SpiNNakerSystem(self.scheduler, RouterTests.TIME_PHASE_PERIOD)
		
		self.injection_link = BufferLink(self.scheduler,1)
		self.exit_link      = BufferLink(self.scheduler,1)
		self.in_links       = [BufferLink(self.scheduler,1) for _ in range(6)]
		self.out_links      = [BufferLink(self.scheduler,1) for _ in range(6)]
		
		# All links
		self.links = ( [self.injection_link, self.exit_link]
		             + self.in_links
		             + self.out_links)
		
		self.router = SpiNNakerRouter( self.scheduler
		                             , self.system
		                             , self.injection_link
		                             , self.exit_link
		                             , self.in_links
		                             , self.out_links
		                             , RouterTests.ROUTER_PERIOD
		                             , RouterTests.WAIT_BEFORE_EMERGENCY
		                             , RouterTests.WAIT_BEFORE_DROP
		                             )
		self.router.set_mesh_dimensions(*RouterTests.MESH_DIMENSIONS)
		self.router.set_mesh_position(*RouterTests.MESH_POSITION)
Exemple #2
0
	def __init__( self
	            , scheduler
	            , system
	            
	            , injection_buffer_length
	            
	            , router_period          # SpiNNakerRouter
	            , wait_before_emergency  # SpiNNakerRouter
	            , wait_before_drop       # SpiNNakerRouter
	            
	            , core_period            # SpiNNakerTrafficGenerator
	            , packet_prob            # SpiNNakerTrafficGenerator
	            , distance_std = None    # SpiNNakerTrafficGenerator
	            ):
		"""
		injection_buffer_length is the number of packets that can be buffered internally
		before they're routed.
		
		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
		
		# Links between the router and traffic generator
		injection_link = BufferLink(self.scheduler, injection_buffer_length)
		exit_link      = BufferLink(self.scheduler)
		
		# The external connections to the rest of the world
		self.in_links = [DeadLink(self.scheduler)]*6
		self.out_links = [DeadLink(self.scheduler)]*6
		
		self.traffic_generator = SpiNNakerTrafficGenerator( self.scheduler
		                                                  , self.system
		                                                  , core_period
		                                                  , packet_prob
		                                                  , injection_link
		                                                  , exit_link
		                                                  , distance_std
		                                                  )
		
		self.router = SpiNNakerRouter( self.scheduler
		                             , self.system
		                             , injection_link
		                             , exit_link
		                             , self.in_links
		                             , self.out_links
		                             , router_period
		                             , wait_before_emergency
		                             , wait_before_drop
		                             )
Exemple #3
0
class RouterTests(unittest.TestCase):
	"""
	Tests the router
	"""
	
	TIME_PHASE_PERIOD     = 200
	ROUTER_PERIOD         = 10
	WAIT_BEFORE_EMERGENCY = 3
	WAIT_BEFORE_DROP      = 6
	
	# We're right in the middle
	MESH_DIMENSIONS       = (3,3)
	MESH_POSITION         = (1,1)
	
	def setUp(self):
		# Before each test build a new scheduler, system and router
		self.scheduler = Scheduler()
		self.system    = SpiNNakerSystem(self.scheduler, RouterTests.TIME_PHASE_PERIOD)
		
		self.injection_link = BufferLink(self.scheduler,1)
		self.exit_link      = BufferLink(self.scheduler,1)
		self.in_links       = [BufferLink(self.scheduler,1) for _ in range(6)]
		self.out_links      = [BufferLink(self.scheduler,1) for _ in range(6)]
		
		# All links
		self.links = ( [self.injection_link, self.exit_link]
		             + self.in_links
		             + self.out_links)
		
		self.router = SpiNNakerRouter( self.scheduler
		                             , self.system
		                             , self.injection_link
		                             , self.exit_link
		                             , self.in_links
		                             , self.out_links
		                             , RouterTests.ROUTER_PERIOD
		                             , RouterTests.WAIT_BEFORE_EMERGENCY
		                             , RouterTests.WAIT_BEFORE_DROP
		                             )
		self.router.set_mesh_dimensions(*RouterTests.MESH_DIMENSIONS)
		self.router.set_mesh_position(*RouterTests.MESH_POSITION)
	
	
	def test_nothing(self):
		# Test that the router does nothing if no packets are given...
		
		it = self.scheduler.run()
		while it.next() < 1000:
			pass
		
		# Nothing was sent/received
		for link in self.links:
			self.assertTrue(link.can_send())
			self.assertFalse(link.can_receive())
		
		# The router remained idle...
		self.assertEqual(self.router.counters["timestamp_packet_timeout"], 0)
		self.assertEqual(self.router.counters["router_packet_timeout"], 0)
		self.assertEqual(self.router.counters["packets_routed"], 0)
		self.assertEqual(self.router.counters["packet_emergency_routed"], 0)
		self.assertEqual(self.router.counters["router_blocked_cycles"], 0)
		
		# Some cycles occurred (i.e. it didn't stop after one)
		self.assertTrue(self.router.counters["router_cycles"] > 10)
		
		# Every cycle was idle
		self.assertEqual(self.router.counters["router_idle_cycles"],
		                 self.router.counters["router_cycles"])
	
	
	def test_loopback(self):
		# Test that the router can forward packets to itself
		
		# A packet to ourselves
		packet = SpiNNakerP2PPacket( self.system
		                           , "Example Data"
		                           , RouterTests.MESH_POSITION
		                           , 32)
		
		self.assertTrue(self.injection_link.can_send())
		self.injection_link.send(packet)
		
		# Run until the packet arrives
		it = self.scheduler.run()
		while it.next() < 1000 and not self.exit_link.can_receive():
			pass
		
		# We got our packet back
		self.assertTrue(self.exit_link.can_receive())
		rec_packet = self.exit_link.receive()
		self.assertEqual(packet, rec_packet)
		
		# Nothing else was sent/received
		for link in self.links:
			self.assertTrue(link.can_send())
			self.assertFalse(link.can_receive())
		
		# The router sent one packet...
		self.assertEqual(self.router.counters["timestamp_packet_timeout"], 0)
		self.assertEqual(self.router.counters["router_packet_timeout"], 0)
		self.assertEqual(self.router.counters["packets_routed"], 1)
		self.assertEqual(self.router.counters["packet_emergency_routed"], 0)
		self.assertEqual(self.router.counters["router_blocked_cycles"], 0)
		self.assertEqual(self.router.counters["router_idle_cycles"], 0)
		
		# This all happened in one cycle
		self.assertEqual(self.router.counters["router_cycles"], 1)
		
		# The packet took one hop
		self.assertEqual(packet.distance, 1)
		
		# Wait counter reset
		self.assertEqual(packet.wait, 0)
		
		# Not emergency routed
		self.assertFalse(packet.emergency)
	
	
	def test_normal_route(self):
		# Test that the router can forward packets to another router
		
		directions = [
			((2,1), topology.EAST),
			((0,1), topology.WEST),
			((1,2), topology.NORTH),
			((1,0), topology.SOUTH),
			((2,2), topology.NORTH_EAST),
			((0,0), topology.SOUTH_WEST),
		]
		
		for router_pos, direction in directions:
			# Reset everything...
			self.setUp()
			
			# A packet to ourselves
			packet = SpiNNakerP2PPacket( self.system
			                           , "Example Data"
			                           , router_pos
			                           , 32)
			
			# Send packet via an arbitrary input (east)
			self.assertTrue(self.in_links[0].can_send())
			self.in_links[0].send(packet)
			
			# Run until the packet arrives
			it = self.scheduler.run()
			while it.next() < 1000 and not self.out_links[direction].can_receive():
				pass
			
			# We got our packet back
			self.assertTrue(self.out_links[direction].can_receive())
			rec_packet = self.out_links[direction].receive()
			self.assertEqual(packet, rec_packet)
			
			# Nothing else was sent/received
			for link in self.links:
				self.assertTrue(link.can_send())
				self.assertFalse(link.can_receive())
			
			# The router sent one packet...
			self.assertEqual(self.router.counters["timestamp_packet_timeout"], 0)
			self.assertEqual(self.router.counters["router_packet_timeout"], 0)
			self.assertEqual(self.router.counters["packets_routed"], 1)
			self.assertEqual(self.router.counters["packet_emergency_routed"], 0)
			self.assertEqual(self.router.counters["router_blocked_cycles"], 0)
			self.assertEqual(self.router.counters["router_idle_cycles"], 0)
			
			# This all happened in one cycle
			self.assertEqual(self.router.counters["router_cycles"], 1)
			
			# The packet took one hop
			self.assertEqual(packet.distance, 1)
			
			# Wait counter reset
			self.assertEqual(packet.wait, 0)
			
			# Not emergency routed
			self.assertFalse(packet.emergency)
	
	
	def test_emergency_on_block(self):
		# Test that the router uses emergency mode when the target link is blocked
		
		directions = [
			((2,1), topology.EAST,      topology.NORTH_EAST),
			((0,1), topology.WEST,      topology.SOUTH_WEST),
			((1,2), topology.NORTH,     topology.WEST),
			((1,0), topology.SOUTH,     topology.EAST),
			((2,2), topology.NORTH_EAST,topology.NORTH),
			((0,0), topology.SOUTH_WEST,topology.SOUTH),
		]
		
		for router_pos, direction, emergency in directions:
			# Reset everything...
			self.setUp()
			
			# A dud packet
			dud = SpiNNakerP2PPacket( self.system , "Dud" , None , 1)
			
			# A packet to ourselves
			packet = SpiNNakerP2PPacket( self.system
			                           , "Example Data"
			                           , router_pos
			                           , 32)
			
			# Send packet via an arbitrary input (east)
			self.assertTrue(self.in_links[0].can_send())
			self.in_links[0].send(packet)
			
			# Block the target port with a dud packet
			self.assertTrue(self.out_links[direction].can_send())
			self.out_links[direction].send(dud)
			
			# Run until the packet arrives
			it = self.scheduler.run()
			while it.next() < 1000 and not self.out_links[emergency].can_receive():
				pass
			
			# We got our packet back
			self.assertTrue(self.out_links[emergency].can_receive())
			rec_packet = self.out_links[emergency].receive()
			self.assertEqual(packet, rec_packet)
			
			# Remove the blockage and make sure it wasn't changed...
			self.assertTrue(self.out_links[direction].can_receive())
			rec_dud = self.out_links[direction].receive()
			self.assertEqual(dud, rec_dud)
			
			# Nothing else was sent/received
			for link in self.links:
				self.assertTrue(link.can_send())
				self.assertFalse(link.can_receive())
			
			# The router sent one packet...
			self.assertEqual(self.router.counters["timestamp_packet_timeout"], 0)
			self.assertEqual(self.router.counters["router_packet_timeout"], 0)
			self.assertEqual(self.router.counters["packets_routed"], 0)
			self.assertEqual(self.router.counters["packet_emergency_routed"], 1)
			self.assertEqual(self.router.counters["router_idle_cycles"], 0)
			
			# We waited only until we could emergency route
			self.assertEqual(self.router.counters["router_blocked_cycles"],
			                 RouterTests.WAIT_BEFORE_EMERGENCY)
			
			# We executed until we waited long enough then sent the packet
			self.assertEqual(self.router.counters["router_cycles"],
			                 RouterTests.WAIT_BEFORE_EMERGENCY + 1)
			
			# The packet took one hop
			self.assertEqual(packet.distance, 1)
			
			# Wait counter reset
			self.assertEqual(packet.wait, 0)
			
			# Emergency routed
			self.assertTrue(packet.emergency)
	
	
	def test_emergency_forward(self):
		# Test that the router can forward packets received in emergency mode
		
		directions = [
			(topology.EAST,      topology.NORTH_EAST),
			(topology.WEST,      topology.SOUTH_WEST),
			(topology.NORTH,     topology.WEST),
			(topology.NORTH_EAST,topology.NORTH),
			(topology.SOUTH_WEST,topology.SOUTH),
		]
		
		for in_link, out_link in directions:
			# Reset everything...
			self.setUp()
			
			# A packet to ourselves
			packet = SpiNNakerP2PPacket( self.system
			                           , "Example Data"
			                           , (0,0) # Doesn't/Shouldn't matter
			                           , 32)
			
			# The packet is in emergency mode
			packet.emergency = True
			
			# Send packet via an arbitrary input (east)
			self.assertTrue(self.in_links[in_link].can_send())
			self.in_links[in_link].send(packet)
			
			# Run until the packet arrives
			it = self.scheduler.run()
			while it.next() < 1000 and not self.out_links[out_link].can_receive():
				pass
			
			# We got our packet back
			self.assertTrue(self.out_links[out_link].can_receive())
			rec_packet = self.out_links[out_link].receive()
			self.assertEqual(packet, rec_packet)
			
			# Nothing else was sent/received
			for link in self.links:
				self.assertTrue(link.can_send())
				self.assertFalse(link.can_receive())
			
			# The router sent one packet...
			self.assertEqual(self.router.counters["timestamp_packet_timeout"], 0)
			self.assertEqual(self.router.counters["router_packet_timeout"], 0)
			self.assertEqual(self.router.counters["packets_routed"], 1)
			self.assertEqual(self.router.counters["packet_emergency_routed"], 0)
			self.assertEqual(self.router.counters["router_idle_cycles"], 0)
			self.assertEqual(self.router.counters["router_blocked_cycles"], 0)
			
			# Routing took one cycle
			self.assertEqual(self.router.counters["router_cycles"], 1)
			
			# The packet took one hop
			self.assertEqual(packet.distance, 1)
			
			# Wait counter reset
			self.assertEqual(packet.wait, 0)
			
			# The packet is no-longer in emergency mode
			self.assertFalse(packet.emergency)
	
	
	def test_drop_on_block(self):
		# Test that the router drops packets which block
		
		directions = [
			((2,1), topology.EAST,      topology.NORTH_EAST),
			((0,1), topology.WEST,      topology.SOUTH_WEST),
			((1,2), topology.NORTH,     topology.WEST),
			((1,0), topology.SOUTH,     topology.EAST),
			((2,2), topology.NORTH_EAST,topology.NORTH),
			((0,0), topology.SOUTH_WEST,topology.SOUTH),
		]
		
		for router_pos, direction, emergency in directions:
			# Reset everything...
			self.setUp()
			
			# A dud packet
			dud = SpiNNakerP2PPacket( self.system , "Dud" , None , 1)
			
			# A packet to ourselves
			packet = SpiNNakerP2PPacket( self.system
			                           , "Example Data"
			                           , router_pos
			                           , 32)
			
			# Send packet via an arbitrary input (east)
			self.assertTrue(self.in_links[0].can_send())
			self.in_links[0].send(packet)
			
			# Block the target port with a dud packet
			self.assertTrue(self.out_links[direction].can_send())
			self.out_links[direction].send(dud)
			
			# Block the emergency port with a dud packet
			self.assertTrue(self.out_links[emergency].can_send())
			self.out_links[emergency].send(dud)
			
			# Run until the packet is dropped (the input becomes free again)
			it = self.scheduler.run()
			while it.next() < 1000 and self.in_links[0].can_receive():
				pass
			
			# Remove the blockages and make sure they weren't changed...
			self.assertTrue(self.out_links[direction].can_receive())
			rec_dud = self.out_links[direction].receive()
			self.assertEqual(dud, rec_dud)
			
			self.assertTrue(self.out_links[emergency].can_receive())
			rec_dud = self.out_links[emergency].receive()
			self.assertEqual(dud, rec_dud)
			
			# Nothing else was sent/received
			for link in self.links:
				self.assertTrue(link.can_send())
				self.assertFalse(link.can_receive())
			
			# The router dropped one packet...
			self.assertEqual(self.router.counters["timestamp_packet_timeout"], 0)
			self.assertEqual(self.router.counters["router_packet_timeout"], 1)
			self.assertEqual(self.router.counters["packets_routed"], 0)
			self.assertEqual(self.router.counters["packet_emergency_routed"], 0)
			
			# We blocked until the wait threshold was exhausted
			self.assertEqual(self.router.counters["router_blocked_cycles"],
			                 RouterTests.WAIT_BEFORE_DROP + 1)
			
			# One idle cycle where we actually drop the packet
			self.assertEqual(self.router.counters["router_idle_cycles"], 1)
			
			# We blocked until the wait threshold was exhausted plus one idle cycle
			# where we dropped the packet
			self.assertEqual(self.router.counters["router_cycles"],
			                 RouterTests.WAIT_BEFORE_DROP + 1 + 1)
			
			# The packet didn't hop
			self.assertEqual(packet.distance, 0)
			
			# The packet had to wait until the timeout expired
			self.assertEqual(packet.wait, RouterTests.WAIT_BEFORE_DROP + 1)
			
			# Not emergency routed
			self.assertFalse(packet.emergency)
Exemple #4
0
class SpiNNaker101(object):
	"""
	A single SpiNNaker chip, a 101 machine in SpiNNaker parlance.
	
	Contains a traffic generator and router. The links from the router are
	initially dead.
	"""
	
	def __init__( self
	            , scheduler
	            , system
	            
	            , injection_buffer_length
	            
	            , router_period          # SpiNNakerRouter
	            , wait_before_emergency  # SpiNNakerRouter
	            , wait_before_drop       # SpiNNakerRouter
	            
	            , core_period            # SpiNNakerTrafficGenerator
	            , packet_prob            # SpiNNakerTrafficGenerator
	            , distance_std = None    # SpiNNakerTrafficGenerator
	            ):
		"""
		injection_buffer_length is the number of packets that can be buffered internally
		before they're routed.
		
		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
		
		# Links between the router and traffic generator
		injection_link = BufferLink(self.scheduler, injection_buffer_length)
		exit_link      = BufferLink(self.scheduler)
		
		# The external connections to the rest of the world
		self.in_links = [DeadLink(self.scheduler)]*6
		self.out_links = [DeadLink(self.scheduler)]*6
		
		self.traffic_generator = SpiNNakerTrafficGenerator( self.scheduler
		                                                  , self.system
		                                                  , core_period
		                                                  , packet_prob
		                                                  , injection_link
		                                                  , exit_link
		                                                  , distance_std
		                                                  )
		
		self.router = SpiNNakerRouter( self.scheduler
		                             , self.system
		                             , injection_link
		                             , exit_link
		                             , self.in_links
		                             , self.out_links
		                             , router_period
		                             , wait_before_emergency
		                             , wait_before_drop
		                             )
		
	
	
	def set_mesh_dimensions(self, w, h):
		"""
		Set the size of the mesh of chips this system is in.
		"""
		self.traffic_generator.set_mesh_dimensions(w,h)
		self.router.set_mesh_dimensions(w,h)
	
	
	def set_mesh_position(self, x, y):
		"""
		Set the size of the mesh of chips this system is in.
		"""
		self.traffic_generator.set_mesh_position(x,y)
		self.router.set_mesh_position(x,y)
	
	
	def get_mesh_position(self):
		"""
		Set the size of the mesh of chips this system is in.
		"""
		return self.router.get_mesh_position()
	
	
	def set_in_link(self, direction, link):
		"""
		Set the given link to the link specified.
		"""
		self.in_links[direction] = link
	
	
	def set_out_link(self, direction, link):
		"""
		Set the given link to the link specified.
		"""
		self.out_links[direction] = link
	
	
	def get_in_link(self, direction):
		"""
		Get the link specified.
		"""
		return self.in_links[direction]
	
	
	def get_out_link(self, direction):
		"""
		Get the link specified.
		"""
		return self.out_links[direction]