def test_get_net_keyspaces_fails_for_inconsistent_cluster(): """Test specification of keyspaces for nets fails in the case that inconsistent cluster IDs are assigned (this is unlikely to happen unless a Net somehow ends up having two different Nengo objects in its source list).""" # Create the vertices vertex_A = [Vertex() for _ in range(4)] vertex_B = Vertex() # Create placements such that vertex A and B fall on two chips and A[0] and # A[1] are on the same chip. placements = { vertex_A[0]: (0, 0), vertex_A[1]: (0, 0), vertex_A[2]: (0, 1), vertex_A[3]: (0, 1), vertex_B: (0, 0) } resources = {v: {} for v in placements} allocations = {v: {} for v in placements} # Create a container for the keyspaces ksc = KeyspaceContainer() # Create the signals and nets signal_a = Signal(object(), [], SignalParameters(keyspace=ksc["nengo"](connection_id=0))) signal_b = Signal(object(), [], SignalParameters(keyspace=ksc["nengo"](connection_id=1))) signal_c = Signal(object(), [], SignalParameters(keyspace=ksc["spam"])) nets = { signal_a: NMNet(vertex_A, vertex_B, 1.0), signal_b: NMNet(vertex_B, vertex_A, 2.0), signal_c: NMNet(vertex_A, vertex_A, 3.0), } # Identify groups groups = [set(vertex_A)] # Manually identify clusters (and do it such that it is inconsistent) vertex_A[0].cluster = 0 vertex_A[1].cluster = 1 vertex_A[2].cluster = 2 vertex_A[3].cluster = 3 # Get the routing nets _, _, _, _, derived_nets = utils.get_nets_for_routing( resources, nets, placements, allocations) # Get the net keyspaces with pytest.raises(AssertionError): utils.get_net_keyspaces(placements, nets, derived_nets)
def test_get_net_keyspaces_fails_for_inconsistent_cluster(): """Test specification of keyspaces for nets fails in the case that inconsistent cluster IDs are assigned (this is unlikely to happen unless a Net somehow ends up having two different Nengo objects in its source list).""" # Create the vertices vertex_A = [Vertex() for _ in range(4)] vertex_B = Vertex() # Create placements such that vertex A and B fall on two chips and A[0] and # A[1] are on the same chip. placements = { vertex_A[0]: (0, 0), vertex_A[1]: (0, 0), vertex_A[2]: (0, 1), vertex_A[3]: (0, 1), vertex_B: (0, 0) } resources = {v: {} for v in placements} allocations = {v: {} for v in placements} # Create a container for the keyspaces ksc = KeyspaceContainer() # Create the signals and nets signal_a = Signal( object(), [], SignalParameters(keyspace=ksc["nengo"](connection_id=0)) ) signal_b = Signal( object(), [], SignalParameters(keyspace=ksc["nengo"](connection_id=1)) ) signal_c = Signal(object(), [], SignalParameters(keyspace=ksc["spam"])) nets = { signal_a: NMNet(vertex_A, vertex_B, 1.0), signal_b: NMNet(vertex_B, vertex_A, 2.0), signal_c: NMNet(vertex_A, vertex_A, 3.0), } # Identify groups groups = [set(vertex_A)] # Manually identify clusters (and do it such that it is inconsistent) vertex_A[0].cluster = 0 vertex_A[1].cluster = 1 vertex_A[2].cluster = 2 vertex_A[3].cluster = 3 # Get the routing nets _, _, _, _, derived_nets = utils.get_nets_for_routing( resources, nets, placements, allocations) # Get the net keyspaces with pytest.raises(AssertionError): utils.get_net_keyspaces(placements, nets, derived_nets)
def test_get_net_keyspaces(): """Test the correct specification of keyspaces for nets.""" # Create the vertices vertex_A = [Vertex() for _ in range(4)] vertex_B = Vertex() # Create placements such that vertex A and B fall on two chips and A[0] and # A[1] are on the same chip. placements = { vertex_A[0]: (0, 0), vertex_A[1]: (0, 0), vertex_A[2]: (0, 1), vertex_A[3]: (0, 1), vertex_B: (0, 0) } resources = {v: {} for v in placements} allocations = {v: {} for v in placements} # Create a container for the keyspaces ksc = KeyspaceContainer() # Create the nets nets = [ NMNet(vertex_A, vertex_B, 1.0, ksc["nengo"](connection_id=0)), NMNet(vertex_B, vertex_A, 2.0, ksc["nengo"](connection_id=1)), NMNet(vertex_A, vertex_A, 3.0, ksc["spam"]), ] # Identify groups groups = [set(vertex_A)] # Identify clusters utils.identify_clusters(groups, placements) assert vertex_B.cluster is None # Not clustered # Get the routing nets _, _, _, _, derived_nets = utils.get_nets_for_routing( resources, nets, placements, allocations) # Get the net keyspaces net_keyspaces = utils.get_net_keyspaces(placements, derived_nets) # Check the net keyspaces are correct # A -> B for xy, vertex in [((0, 0), vertex_A[0]), ((0, 1), vertex_A[2])]: net = derived_nets[nets[0]][xy] cluster = vertex.cluster assert net_keyspaces[net] == nets[0].keyspace(cluster=cluster) # B -> A net = derived_nets[nets[1]][(0, 0)] assert net_keyspaces[net] == nets[1].keyspace(cluster=0) # A -> A for xy in [(0, 0), (0, 1)]: net = derived_nets[nets[2]][xy] assert net_keyspaces[net] == nets[2].keyspace # No change
def place_and_route(self, system_info, place=place_and_route.place, place_kwargs={}, allocate=place_and_route.allocate, allocate_kwargs={}, route=place_and_route.route, route_kwargs={}): """Place and route the netlist onto the given SpiNNaker machine. Parameters ---------- system_info : \ :py:class:`~rig.machine_control.MachineController.SystemInfo` Describes the system onto which the netlist should be placed and routed. Other Parameters ---------------- place : function Placement function. Must support the interface defined by Rig. place_kwargs : dict Keyword arguments for the placement method. allocate : function Resource allocation function. Must support the interface defined by Rig. allocate_kwargs : dict Keyword arguments for the allocation function. route : function Router function. Must support the interface defined by Rig. route_kwargs : dict Keyword arguments for the router function. """ # Generate a Machine and set of core-reserving constraints to prevent # the use of non-idle cores. machine = build_machine(system_info) core_constraints = build_core_constraints(system_info) constraints = self.constraints + core_constraints # Build a map of vertices to the resources they require, get a list of # constraints. vertices_resources = {v: v.resources for v in self.vertices} # Perform placement and allocation place_nets = list(utils.get_nets_for_placement(self.nets)) self.placements = place(vertices_resources, place_nets, machine, constraints, **place_kwargs) self.allocations = allocate(vertices_resources, place_nets, machine, constraints, self.placements, **allocate_kwargs) # Identify clusters and modify vertices appropriately utils.identify_clusters(self.groups, self.placements) # Get the nets for routing (route_nets, vertices_resources, # Can safely overwrite the resource dictionary extended_placements, extended_allocations, derived_nets) = utils.get_nets_for_routing( vertices_resources, self.nets, self.placements, self.allocations) # Get a map from the nets we will route with to keyspaces self.net_keyspaces = utils.get_net_keyspaces(self.placements, derived_nets) # Fix all keyspaces self.keyspaces.assign_fields() # Finally, route all nets using the extended resource dictionary, # placements and allocations. self.routes = route(vertices_resources, route_nets, machine, constraints, extended_placements, extended_allocations, **route_kwargs)
def test_get_net_keyspaces(): """Test the correct specification of keyspaces for nets.""" # Create the vertices vertex_A = [Vertex() for _ in range(4)] vertex_B = Vertex() # Create placements such that vertex A and B fall on two chips and A[0] and # A[1] are on the same chip. placements = { vertex_A[0]: (0, 0), vertex_A[1]: (0, 0), vertex_A[2]: (0, 1), vertex_A[3]: (0, 1), vertex_B: (0, 0) } resources = {v: {} for v in placements} allocations = {v: {} for v in placements} # Manually assign cluster IDs vertex_A[0].cluster = 0 vertex_A[1].cluster = 0 vertex_A[2].cluster = 1 vertex_A[3].cluster = 1 # Create a container for the keyspaces ksc = KeyspaceContainer() # Create the signals and nets signal_a = Signal( object(), [], SignalParameters(keyspace=ksc["nengo"](connection_id=0)) ) signal_b = Signal( object(), [], SignalParameters(keyspace=ksc["nengo"](connection_id=1)) ) signal_c = Signal(object(), [], SignalParameters(keyspace=ksc["spam"])) nets = { signal_a: NMNet(vertex_A, vertex_B, 1.0), signal_b: NMNet(vertex_B, vertex_A, 2.0), signal_c: NMNet(vertex_A, vertex_A, 3.0), } # Get the routing nets _, _, _, _, derived_nets = utils.get_nets_for_routing( resources, nets, placements, allocations) # Get the net keyspaces net_keyspaces = utils.get_net_keyspaces(placements, nets, derived_nets) # Check the net keyspaces are correct # A -> B for xy, vertex in [((0, 0), vertex_A[0]), ((0, 1), vertex_A[2])]: net = derived_nets[nets[signal_a]][xy] cluster = vertex.cluster assert net_keyspaces[net] == signal_a.keyspace(cluster=cluster) # B -> A net = derived_nets[nets[signal_b]][(0, 0)] assert net_keyspaces[net] == signal_b.keyspace(cluster=0) # A -> A for xy in [(0, 0), (0, 1)]: net = derived_nets[nets[signal_c]][xy] assert net_keyspaces[net] == signal_c.keyspace # No change
def place_and_route(self, system_info, place=place_and_route.place, place_kwargs={}, allocate=place_and_route.allocate, allocate_kwargs={}, route=place_and_route.route, route_kwargs={}): """Place and route the netlist onto the given SpiNNaker machine. Parameters ---------- system_info : \ :py:class:`~rig.machine_control.MachineController.SystemInfo` Describes the system onto which the netlist should be placed and routed. Other Parameters ---------------- place : function Placement function. Must support the interface defined by Rig. place_kwargs : dict Keyword arguments for the placement method. allocate : function Resource allocation function. Must support the interface defined by Rig. allocate_kwargs : dict Keyword arguments for the allocation function. route : function Router function. Must support the interface defined by Rig. route_kwargs : dict Keyword arguments for the router function. """ # Generate a Machine and set of core-reserving constraints to prevent # the use of non-idle cores. machine = build_machine(system_info) core_constraints = build_core_constraints(system_info) constraints = self.constraints + core_constraints # Build a map of vertices to the resources they require, get a list of # constraints. vertices_resources = {v: v.resources for v in self.vertices} # Perform placement and allocation place_nets = list(utils.get_nets_for_placement(itervalues(self.nets))) self.placements = place(vertices_resources, place_nets, machine, constraints, **place_kwargs) self.allocations = allocate(vertices_resources, place_nets, machine, constraints, self.placements, **allocate_kwargs) # Get the nets for routing ( route_nets, vertices_resources, # Can safely overwrite the resource dictionary extended_placements, extended_allocations, derived_nets) = utils.get_nets_for_routing(vertices_resources, self.nets, self.placements, self.allocations) # Finally, route all nets using the extended resource dictionary, # placements and allocations. self.routes = route(vertices_resources, route_nets, machine, constraints, extended_placements, extended_allocations, **route_kwargs) # Assign keyspaces based on the placement signal_routes = collections.defaultdict(collections.deque) for signal, nmnet in iteritems(self.nets): for net in itervalues(derived_nets[nmnet]): signal_routes[signal].append(self.routes[net]) key_allocation.allocate_signal_keyspaces(signal_routes, self.signal_id_constraints, self.keyspaces) # Assign cluster IDs based on the placement and the routing key_allocation.assign_cluster_ids(self.operator_vertices, signal_routes, self.placements) # Get a map from the nets we will route with to keyspaces self.net_keyspaces = utils.get_net_keyspaces(self.placements, self.nets, derived_nets) # Fix all keyspaces self.keyspaces.assign_fields()
def test_get_net_keyspaces(): """Test the correct specification of keyspaces for nets.""" # Create the vertices vertex_A = [Vertex() for _ in range(4)] vertex_B = Vertex() # Create placements such that vertex A and B fall on two chips and A[0] and # A[1] are on the same chip. placements = { vertex_A[0]: (0, 0), vertex_A[1]: (0, 0), vertex_A[2]: (0, 1), vertex_A[3]: (0, 1), vertex_B: (0, 0) } resources = {v: {} for v in placements} allocations = {v: {} for v in placements} # Manually assign cluster IDs vertex_A[0].cluster = 0 vertex_A[1].cluster = 0 vertex_A[2].cluster = 1 vertex_A[3].cluster = 1 # Create a container for the keyspaces ksc = KeyspaceContainer() # Create the signals and nets signal_a = Signal(object(), [], SignalParameters(keyspace=ksc["nengo"](connection_id=0))) signal_b = Signal(object(), [], SignalParameters(keyspace=ksc["nengo"](connection_id=1))) signal_c = Signal(object(), [], SignalParameters(keyspace=ksc["spam"])) nets = { signal_a: NMNet(vertex_A, vertex_B, 1.0), signal_b: NMNet(vertex_B, vertex_A, 2.0), signal_c: NMNet(vertex_A, vertex_A, 3.0), } # Get the routing nets _, _, _, _, derived_nets = utils.get_nets_for_routing( resources, nets, placements, allocations) # Get the net keyspaces net_keyspaces = utils.get_net_keyspaces(placements, nets, derived_nets) # Check the net keyspaces are correct # A -> B for xy, vertex in [((0, 0), vertex_A[0]), ((0, 1), vertex_A[2])]: net = derived_nets[nets[signal_a]][xy] cluster = vertex.cluster assert net_keyspaces[net] == signal_a.keyspace(cluster=cluster) # B -> A net = derived_nets[nets[signal_b]][(0, 0)] assert net_keyspaces[net] == signal_b.keyspace(cluster=0) # A -> A for xy in [(0, 0), (0, 1)]: net = derived_nets[nets[signal_c]][xy] assert net_keyspaces[net] == signal_c.keyspace # No change