Beispiel #1
0
	def test_get_all_routes_empty(self):
		"""
		Test that model.get_all_routes finds some in a system containing some
		"""
		chips = model.make_rectangular_board(2,2)
		
		# A set of test routes
		ref_routes = {
			# Unicast self loop
			model.Route(0): (chips[(0,0)].cores[0], set([chips[(0,0)].cores[0]])),
			
			# Broadcast to all cores on a chip
			model.Route(1): (chips[(0,0)].cores[0], set(chips[(0,0)].cores.itervalues())),
			
			# Multicast messages from everyone from them to two other chips
			model.Route(2): (chips[(0,0)].cores[0], set([chips[(1,0)].cores[0], chips[(1,1)].cores[1]])),
			model.Route(3): (chips[(1,0)].cores[0], set([chips[(0,0)].cores[0], chips[(0,1)].cores[1]])),
			model.Route(4): (chips[(0,1)].cores[0], set([chips[(1,1)].cores[0], chips[(1,0)].cores[1]])),
			model.Route(5): (chips[(1,1)].cores[0], set([chips[(0,1)].cores[0], chips[(0,0)].cores[1]])),
		}
		
		# Add the reference routes to the network
		for route, (source, sinks) in ref_routes.iteritems():
			source.sources.add(route)
			for sink in sinks:
				sink.sinks.add(route)
		
		# Check that the routes found match the routes added
		found_routes = model.get_all_routes(chips)
		self.assertEqual(len(found_routes), len(ref_routes))
		for route, (source, sinks) in found_routes.iteritems():
			self.assertEqual(ref_routes[route][0], source)
			self.assertEqual(ref_routes[route][1], sinks)
Beispiel #2
0
	def test_get_all_routes_empty(self):
		"""
		Test that model.get_all_routes finds some in a system containing some
		"""
		chips = model.make_rectangular_board(2,2)
		
		# A set of test routes
		ref_routes = {
			# Unicast self loop
			model.Route(0): (chips[(0,0)][1][0], set([chips[(0,0)][1][0]])),
			
			# Broadcast to all cores on a chip
			model.Route(1): (chips[(0,0)][1][0], set(chips[(0,0)][1])),
			
			# Multicast messages from everyone from them to two other chips
			model.Route(2): (chips[(0,0)][1][0], set([chips[(1,0)][1][0], chips[(1,1)][1][1]])),
			model.Route(3): (chips[(1,0)][1][0], set([chips[(0,0)][1][0], chips[(0,1)][1][1]])),
			model.Route(4): (chips[(0,1)][1][0], set([chips[(1,1)][1][0], chips[(1,0)][1][1]])),
			model.Route(5): (chips[(1,1)][1][0], set([chips[(0,1)][1][0], chips[(0,0)][1][1]])),
		}
		
		# Add the reference routes to the network
		for route, (source, sinks) in ref_routes.iteritems():
			source.sources.add(route)
			for sink in sinks:
				sink.sinks.add(route)
		
		# Check that the routes found match the routes added
		found_routes = model.get_all_routes(chips)
		self.assertEqual(len(found_routes), len(ref_routes))
		for route, (source, sinks) in found_routes.iteritems():
			self.assertEqual(ref_routes[route][0], source)
			self.assertEqual(ref_routes[route][1], sinks)
Beispiel #3
0
	def test_is_path_connected(self):
		"""
		Test that the is_path_connected function works on a set of example cases.
		"""
		
		chips = model.make_rectangular_board(4,1)
		
		for is_connected, path in [ # Self-loop
		                            (True, [chips[(0,0)].cores[0], chips[(0,0)].router, chips[(0,0)].cores[0]]),
		                            # From one end to another
		                            (True, [ chips[(0,0)].cores[10], chips[(0,0)].router, chips[(1,0)].router
		                                   , chips[(2,0)].router, chips[(3,0)].router, chips[(3,0)].cores[11]
		                                   ]),
		                            # Reverse direction...
		                            (True, [ chips[(3,0)].cores[10], chips[(3,0)].router, chips[(2,0)].router
		                                   , chips[(1,0)].router, chips[(0,0)].router, chips[(0,0)].cores[11]
		                                   ]),
		                            # Self loop without router
		                            (False, [chips[(0,0)].cores[0], chips[(0,0)].cores[0]]),
		                            # From one chip to another non-adjacent chip
		                            (False, [ chips[(0,0)].cores[10], chips[(0,0)].router
		                                    , chips[(2,0)].router, chips[(2,0)].cores[11]
		                                    ]),
		                          ]:
			self.assertEqual(is_connected, model.is_path_connected(path))
Beispiel #4
0
	def test_is_path_connected(self):
		"""
		Test that the is_path_connected function works on a set of example cases.
		"""
		
		chips = model.make_rectangular_board(4,1)
		
		for is_connected, path in [ # Self-loop
		                            (True, [chips[(0,0)][1][0], chips[(0,0)][0], chips[(0,0)][1][0]]),
		                            # From one end to another
		                            (True, [ chips[(0,0)][1][10], chips[(0,0)][0], chips[(1,0)][0]
		                                   , chips[(2,0)][0], chips[(3,0)][0], chips[(3,0)][1][11]
		                                   ]),
		                            # Reverse direction...
		                            (True, [ chips[(3,0)][1][10], chips[(3,0)][0], chips[(2,0)][0]
		                                   , chips[(1,0)][0], chips[(0,0)][0], chips[(0,0)][1][11]
		                                   ]),
		                            # Self loop without router
		                            (False, [chips[(0,0)][1][0], chips[(0,0)][1][0]]),
		                            # From one chip to another non-adjacent chip
		                            (False, [ chips[(0,0)][1][10], chips[(0,0)][0]
		                                    , chips[(2,0)][0], chips[(2,0)][1][11]
		                                    ]),
		                          ]:
			self.assertEqual(is_connected, model.is_path_connected(path))
Beispiel #5
0
	def test_make_rectangular_board(self):
		"""
		Test that a model.make_rectangular_board creates the appropriate formation
		of chips.
		"""
		for (w,h) in [(1,1), (1,2), (2,1), (2,2)]:
			chips = model.make_rectangular_board(w,h)
			
			# Ensure correct number of nodes
			self.assertEqual(len(chips), w*h)
			
			# Ensure nodes exist in correct places
			for y in range(h):
				for x in range(w):
					self.assertIn((x,y), chips.keys())
Beispiel #6
0
	def test_make_rectangular_board(self):
		"""
		Test that a model.make_rectangular_board creates the appropriate formation
		of chips.
		"""
		for (w,h) in [(1,1), (1,2), (2,1), (2,2)]:
			chips = model.make_rectangular_board(w,h)
			
			# Ensure correct number of nodes
			self.assertEqual(len(chips), w*h)
			
			# Ensure nodes exist in correct places
			for y in range(h):
				for x in range(w):
					self.assertIn((x,y), chips.keys())
Beispiel #7
0
	def setUp(self):
		"""
		Create a small network with a few routes within it.
		"""
		
		self.chips = model.make_rectangular_board(3,3)
		
		# A self-loop on 0,1,0
		model.add_route(model.Route(0), [ self.chips[(0,1)].cores[0]
		                                , self.chips[(0,1)].router
		                                , self.chips[(0,1)].cores[0]
		                                ])
		
		# A straight route from 0,0,0 to 2,0,0
		model.add_route(model.Route(1), [ self.chips[(0,0)].cores[0]
		                                , self.chips[(0,0)].router
		                                , self.chips[(1,0)].router
		                                , self.chips[(2,0)].router
		                                , self.chips[(2,0)].cores[0]
		                                ])
		
		# A multicast from from 0,2,0 to 1,2,0,  2,2,0 and 1,1,0
		r = model.Route(2)
		model.add_route(r, [ self.chips[(0,2)].cores[0]
		                   , self.chips[(0,2)].router
		                   , self.chips[(1,2)].router
		                   , self.chips[(1,2)].cores[0]
		                   ])
		model.add_route(r, [ self.chips[(0,2)].cores[0]
		                   , self.chips[(0,2)].router
		                   , self.chips[(1,2)].router
		                   , self.chips[(2,2)].router
		                   , self.chips[(2,2)].cores[0]
		                   ])
		model.add_route(r, [ self.chips[(0,2)].cores[0]
		                   , self.chips[(0,2)].router
		                   , self.chips[(1,2)].router
		                   , self.chips[(1,1)].router
		                   , self.chips[(1,1)].cores[0]
		                   ])
		
		# A self-loop on 1,1,1 to result in 1,1 having multiple routing entries
		model.add_route(model.Route(3), [ self.chips[(1,1)].cores[1]
		                                , self.chips[(1,1)].router
		                                , self.chips[(1,1)].cores[1]
		                                ])
Beispiel #8
0
	def setUp(self):
		"""
		Create a small network with a few routes within it.
		"""
		
		self.chips = model.make_rectangular_board(3,3)
		
		# A self-loop on 0,1,0
		model.add_route(model.Route(0), [ self.chips[(0,1)][1][0]
		                                , self.chips[(0,1)][0]
		                                , self.chips[(0,1)][1][0]
		                                ])
		
		# A straight route from 0,0,0 to 2,0,0
		model.add_route(model.Route(1), [ self.chips[(0,0)][1][0]
		                                , self.chips[(0,0)][0]
		                                , self.chips[(1,0)][0]
		                                , self.chips[(2,0)][0]
		                                , self.chips[(2,0)][1][0]
		                                ])
		
		# A multicast from from 0,2,0 to 1,2,0,  2,2,0 and 1,1,0
		r = model.Route(2)
		model.add_route(r, [ self.chips[(0,2)][1][0]
		                   , self.chips[(0,2)][0]
		                   , self.chips[(1,2)][0]
		                   , self.chips[(1,2)][1][0]
		                   ])
		model.add_route(r, [ self.chips[(0,2)][1][0]
		                   , self.chips[(0,2)][0]
		                   , self.chips[(1,2)][0]
		                   , self.chips[(2,2)][0]
		                   , self.chips[(2,2)][1][0]
		                   ])
		model.add_route(r, [ self.chips[(0,2)][1][0]
		                   , self.chips[(0,2)][0]
		                   , self.chips[(1,2)][0]
		                   , self.chips[(1,1)][0]
		                   , self.chips[(1,1)][1][0]
		                   ])
		
		# A self-loop on 1,1,1 to result in 1,1 having multiple routing entries
		model.add_route(model.Route(3), [ self.chips[(1,1)][1][1]
		                                , self.chips[(1,1)][0]
		                                , self.chips[(1,1)][1][1]
		                                ])
Beispiel #9
0
	def test_dor_dead_links(self):
		"""
		Test dimension-order-routing in the case where routing is not possible.
		"""
		# Create a square system with a hole in the x-axis for the 0th row of chips.
		chips = model.make_rectangular_board(3, 1)
		chips[(1,0)].router.connections[topology.EAST] = None
		
		# Should not be able to route along the x axis of the system.
		node_sequences, unrouted_sinks = \
			routers.dimension_order_route( chips[(0,0)].cores[0]
			                             , [chips[(2,0)].cores[0]]
			                             , chips
			                             , use_wrap_around = False
			                             , dimension_order = (0,1,2)
			                             )
		
		self.assertFalse(node_sequences)
		self.assertEqual(len(unrouted_sinks), 1)
Beispiel #10
0
	def test_dor_dead_links(self):
		"""
		Test dimension-order-routing in the case where routing is not possible.
		"""
		# Create a square system with a hole in the x-axis for the 0th row of chips.
		chips = model.make_rectangular_board(3, 1)
		chips[(1,0)][0].connections[topology.EAST] = None
		
		# Should not be able to route along the x axis of the system.
		node_sequences, unrouted_sinks = \
			routers.dimension_order_route( chips[(0,0)][1][0]
			                             , [chips[(2,0)][1][0]]
			                             , chips
			                             , use_wrap_around = False
			                             , dimension_order = (0,1,2)
			                             )
		
		self.assertFalse(node_sequences)
		self.assertEqual(len(unrouted_sinks), 1)
Beispiel #11
0
	def test_dor_perfect_case(self):
		"""
		Test dimension-order-routing in the case where routing should be possible.
		"""
		
		width  = 5
		height = 5
		
		port_to_dimension = {
			topology.EAST: 0,
			topology.WEST: 0,
			topology.NORTH: 1,
			topology.SOUTH: 1,
			topology.NORTH_EAST: 2,
			topology.SOUTH_WEST: 2,
		}
		
		for wrap_around in (True, False):
			chips = model.make_rectangular_board(width, height, wrap_around = wrap_around)
			for dimension_order in ( (0,1,2), (2,1,0) ):
				for route, source, sinks in ( # Self-loop
				                              (model.Route(0), chips[(0,0)].cores[0], ( chips[(0,0)].cores[0], )),
				                              # One-to-one (same row)
				                              (model.Route(1), chips[(0,0)].cores[0], ( chips[(4,0)].cores[0], )),
				                              # One-to-one (different row)
				                              (model.Route(2), chips[(0,0)].cores[0], ( chips[(2,1)].cores[0], )),
				                              # One-to-one (may use wrap-around)
				                              (model.Route(3), chips[(0,0)].cores[0], ( chips[(4,4)].cores[0], )),
				                              # One-to-N
				                              (model.Route(4), chips[(0,0)].cores[0], ( chips[(0,0)].cores[0]
				                                                                   , chips[(4,0)].cores[0]
				                                                                   , chips[(0,4)].cores[0]
				                                                                   , chips[(4,4)].cores[0]
				                                                                   )),
				                            ):
					node_sequences, unrouted_sinks = \
						routers.dimension_order_route(source, sinks, chips
						                             , use_wrap_around = wrap_around
						                             , dimension_order = dimension_order
						                             )
					
					# Nothing should be unroutable
					self.assertFalse(unrouted_sinks)
					
					# Should be one route per sink
					self.assertEqual(len(sinks), len(node_sequences))
					
					# All node sequences should start from the source
					for node_sequence in node_sequences:
						self.assertEqual(node_sequence[0], source)
					
					sinks_routed = set()
					for node_sequence in node_sequences:
						sequence_sink = node_sequence[-1]
						# Each sink must not have multiple node sequences leading to it
						self.assertNotIn(sequence_sink, sinks_routed)
						sinks_routed.add(sequence_sink)
					
					# Every sink must have node sequence leading to it
					self.assertEqual(set(sinks), sinks_routed)
					
					# Test that the route follows the order of dimensions required
					for node_sequence in node_sequences:
						dimensions = list(dimension_order)
						for step in xrange(1, len(node_sequence) - 2):
							router = node_sequence[step]
							next_router = node_sequence[step+1]
							
							# Find the port to the next router
							for port, next_router_ in router.connections.iteritems():
								if next_router_ == next_router:
									break
								port = None
							
							# Whenever the direction changes, it must change to a direction
							# next in the ordering
							while dimensions[0] != port_to_dimension[port]:
								dimensions.pop(0)
								self.assertTrue(dimensions)
Beispiel #12
0
	def test_add_route(self):
		"""
		Test that model.add_route successfully works for a simple multicast route (and
		that defining the route twice has no ill-effects).
		"""
		chips = model.make_rectangular_board(2,2)
		
		# Make a path travelling round the system (do it twice to make sure nothing
		# gets duplicated)
		route = model.Route(0)
		for _ in range(2):
			model.add_route( route
			               , [ chips[(0,0)].cores[0]
			                 , chips[(0,0)].router
			                 , chips[(0,1)].router
			                 , chips[(1,1)].router
			                 , chips[(1,0)].router
			                 , chips[(1,0)].cores[17]
			                 ]
			               )
			model.add_route( route
			               , [ chips[(0,0)].cores[0]
			                 , chips[(0,0)].router
			                 , chips[(0,1)].router
			                 , chips[(1,1)].router
			                 , chips[(1,1)].cores[17]
			                 ]
			               )
		
		# Check that the route was added in the appropriate sink/source and nowhere
		# else
		for (position, core) in sum(( list((router.position, core) for core in cores.itervalues())
		                              for (router,cores) in chips.itervalues()
		                            ), []):
			# Source should be in chip (0,0)'s 0th core
			if position == (0,0) and core.core_id == 0:
				self.assertEqual(core.sources, set([route]))
			else:
				self.assertEqual(core.sources, set())
			
			# Sink should be in chips (1,0)'s and (1,1)'s 17th core
			if position in ((1,0), (1,1)) and core.core_id == 17:
				self.assertEqual(core.sinks, set([route]))
			else:
				self.assertEqual(core.sinks, set())
		
		
		# Check that all connecting edges between routers are valid (i.e. face in
		# opposite directions and make sense)
		for router, cores in chips.itervalues():
			for route, (input_port, output_ports) in router.routes.iteritems():
				# Test the input has a corresponding output in the router/core
				if input_port in model.Router.INTERNAL_PORTS:
					# If a route is from a core, make sure the core knows about it
					core = router.connections[input_port]
					self.assertIn(route, core.sources)
				else:
					# Check the corresponding router has an output for this route pointing
					# at this router.
					other_router = router.connections[input_port]
					self.assertIn( topology.opposite(input_port)
					             , other_router.routes[route][1]
					             )
				
				# Test all outputs have a coresponding input in another router/core
				for output_port in output_ports:
					if output_port in model.Router.INTERNAL_PORTS:
						# If a route is to a core, make sure the core knows about it
						core = router.connections[output_port]
						self.assertIn(route, core.sinks)
					else:
						# Check the corresponding router has an input for this route pointing
						# from this router.
						other_router = router.connections[output_port]
						self.assertEqual( topology.opposite(output_port)
						                , other_router.routes[route][0]
						                )
Beispiel #13
0
	def test_get_all_routes_empty(self):
		"""
		Test that model.get_all_routes finds none in a system without any...
		"""
		chips = model.make_rectangular_board()
		self.assertEqual(model.get_all_routes(chips), {})
Beispiel #14
0
	def test_dor_perfect_case(self):
		"""
		Test dimension-order-routing in the case where routing should be possible.
		"""
		
		width  = 5
		height = 5
		
		port_to_dimension = {
			topology.EAST: 0,
			topology.WEST: 0,
			topology.NORTH: 1,
			topology.SOUTH: 1,
			topology.NORTH_EAST: 2,
			topology.SOUTH_WEST: 2,
		}
		
		for wrap_around in (True, False):
			chips = model.make_rectangular_board(width, height, wrap_around = wrap_around)
			for dimension_order in ( (0,1,2), (2,1,0) ):
				for route, source, sinks in ( # Self-loop
				                              (model.Route(0), chips[(0,0)][1][0], ( chips[(0,0)][1][0], )),
				                              # One-to-one (same row)
				                              (model.Route(1), chips[(0,0)][1][0], ( chips[(4,0)][1][0], )),
				                              # One-to-one (different row)
				                              (model.Route(2), chips[(0,0)][1][0], ( chips[(2,1)][1][0], )),
				                              # One-to-one (may use wrap-around)
				                              (model.Route(3), chips[(0,0)][1][0], ( chips[(4,4)][1][0], )),
				                              # One-to-N
				                              (model.Route(4), chips[(0,0)][1][0], ( chips[(0,0)][1][0]
				                                                                   , chips[(4,0)][1][0]
				                                                                   , chips[(0,4)][1][0]
				                                                                   , chips[(4,4)][1][0]
				                                                                   )),
				                            ):
					node_sequences, unrouted_sinks = \
						routers.dimension_order_route(source, sinks, chips
						                             , use_wrap_around = wrap_around
						                             , dimension_order = dimension_order
						                             )
					
					# Nothing should be unroutable
					self.assertFalse(unrouted_sinks)
					
					# Should be one route per sink
					self.assertEqual(len(sinks), len(node_sequences))
					
					# All node sequences should start from the source
					for node_sequence in node_sequences:
						self.assertEqual(node_sequence[0], source)
					
					sinks_routed = set()
					for node_sequence in node_sequences:
						sequence_sink = node_sequence[-1]
						# Each sink must not have multiple node sequences leading to it
						self.assertNotIn(sequence_sink, sinks_routed)
						sinks_routed.add(sequence_sink)
					
					# Every sink must have node sequence leading to it
					self.assertEqual(set(sinks), sinks_routed)
					
					# Test that the route follows the order of dimensions required
					for node_sequence in node_sequences:
						dimensions = list(dimension_order)
						for step in xrange(1, len(node_sequence) - 2):
							router = node_sequence[step]
							next_router = node_sequence[step+1]
							
							# Find the port to the next router
							for port, next_router_ in router.connections.iteritems():
								if next_router_ == next_router:
									break
								port = None
							
							# Whenever the direction changes, it must change to a direction
							# next in the ordering
							while dimensions[0] != port_to_dimension[port]:
								dimensions.pop(0)
								self.assertTrue(dimensions)
Beispiel #15
0
	def test_add_route(self):
		"""
		Test that model.add_route successfully works for a simple multicast route (and
		that defining the route twice has no ill-effects).
		"""
		chips = model.make_rectangular_board(2,2)
		
		# Make a path travelling round the system (do it twice to make sure nothing
		# gets duplicated)
		route = model.Route(0)
		for _ in range(2):
			model.add_route( route
			               , [ chips[(0,0)][1][0]
			                 , chips[(0,0)][0]
			                 , chips[(0,1)][0]
			                 , chips[(1,1)][0]
			                 , chips[(1,0)][0]
			                 , chips[(1,0)][1][17]
			                 ]
			               )
			model.add_route( route
			               , [ chips[(0,0)][1][0]
			                 , chips[(0,0)][0]
			                 , chips[(0,1)][0]
			                 , chips[(1,1)][0]
			                 , chips[(1,1)][1][17]
			                 ]
			               )
		
		# Check that the route was added in the appropriate sink/source and nowhere
		# else
		for (position, core) in sum(( list((router.position, core) for core in cores)
		                              for (router,cores) in chips.itervalues()
		                            ), []):
			# Source should be in chip (0,0)'s 0th core
			if position == (0,0) and core.core_id == 0:
				self.assertEqual(core.sources, set([route]))
			else:
				self.assertEqual(core.sources, set())
			
			# Sink should be in chips (1,0)'s and (1,1)'s 17th core
			if position in ((1,0), (1,1)) and core.core_id == 17:
				self.assertEqual(core.sinks, set([route]))
			else:
				self.assertEqual(core.sinks, set())
		
		
		# Check that all connecting edges between routers are valid (i.e. face in
		# opposite directions and make sense)
		for router, cores in chips.itervalues():
			for route, (input_port, output_ports) in router.routes.iteritems():
				# Test the input has a corresponding output in the router/core
				if input_port in model.Router.INTERNAL_PORTS:
					# If a route is from a core, make sure the core knows about it
					core = router.connections[input_port]
					self.assertIn(route, core.sources)
				else:
					# Check the corresponding router has an output for this route pointing
					# at this router.
					other_router = router.connections[input_port]
					self.assertIn( topology.opposite(input_port)
					             , other_router.routes[route][1]
					             )
				
				# Test all outputs have a coresponding input in another router/core
				for output_port in output_ports:
					if output_port in model.Router.INTERNAL_PORTS:
						# If a route is to a core, make sure the core knows about it
						core = router.connections[output_port]
						self.assertIn(route, core.sinks)
					else:
						# Check the corresponding router has an input for this route pointing
						# from this router.
						other_router = router.connections[output_port]
						self.assertEqual( topology.opposite(output_port)
						                , other_router.routes[route][0]
						                )
Beispiel #16
0
	def test_get_all_routes_empty(self):
		"""
		Test that model.get_all_routes finds none in a system without any...
		"""
		chips = model.make_rectangular_board()
		self.assertEqual(model.get_all_routes(chips), {})