def test_buffer_link(self): s = Scheduler() bl = BufferLink(s, 2) # Can only send self.assertTrue(bl.can_send()) self.assertFalse(bl.can_receive()) bl.send(123) # Have something to recieve and space left self.assertTrue(bl.can_send()) self.assertTrue(bl.can_receive()) bl.send(456) # Have something to recieve and no space left self.assertFalse(bl.can_send()) self.assertTrue(bl.can_receive()) # Can peek self.assertEqual(bl.peek(), 123) self.assertFalse(bl.can_send()) self.assertTrue(bl.can_receive()) self.assertEqual(bl.peek(), 123) self.assertFalse(bl.can_send()) self.assertTrue(bl.can_receive()) # In queue order self.assertEqual(bl.receive(), 123) # Still have something to recieve and space left again self.assertTrue(bl.can_send()) self.assertTrue(bl.can_receive()) # Can peek self.assertEqual(bl.peek(), 456) self.assertTrue(bl.can_send()) self.assertTrue(bl.can_receive()) self.assertEqual(bl.peek(), 456) self.assertTrue(bl.can_send()) self.assertTrue(bl.can_receive()) # In queue order self.assertEqual(bl.receive(), 456) # Nothing to recieve and space in buffer self.assertTrue(bl.can_send()) self.assertFalse(bl.can_receive()) # Didn't schedule anything self.assertRaises(StopIteration, s.run().next)
def test_normal(self): # Test that packets are generated appropriately when distributing with a # normal distribution. scheduler = Scheduler() system = SpiNNakerSystem(scheduler, 10) # Share the same link for sending and receiving, that way the module cleans # up after itself! link = BufferLink(scheduler) # Uniform generator node tg = SpiNNakerTrafficGenerator( scheduler , system , 1 , 0.1 , link , link , 10 ) tg.set_mesh_dimensions(100,100) tg.set_mesh_position(50,50) it = scheduler.run() # Perform 1000 cycles while it.next() < 2000 and tg.counters["generator_cycles"] < 1000: # We may have a packet if link.can_receive(): # Check the packet is targeted somewhere in the mesh packet = link.receive() self.assertTrue(all(0 <= dimension < 100 for dimension in packet.destination)) # XXX: Should probably check that distribution is appropriate too but meh... # Should have done 1000 cycles self.assertEqual(tg.counters["generator_cycles"], 1000) # We should have sent some number of packets that isn't all the time and not # never (well, in theory we might not but hey, if this is going wrong you've # got a bad day on your hands). self.assertTrue(10 < tg.counters["generator_injected_packets"] < 1000) # None should be dropped self.assertEqual(tg.counters["generator_dropped_packets"], 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)