def load_application(self, controller, system_info): """Load the netlist to a SpiNNaker machine. Parameters ---------- controller : :py:class:`~rig.machine_control.MachineController` Controller to use to communicate with the machine. """ # Build and load the routing tables, first by building a mapping from # nets to keys and masks. logger.debug("Loading routing tables") net_keys = { n: (ks.get_value(tag=self.keyspaces.routing_tag), ks.get_mask(tag=self.keyspaces.routing_tag)) for n, ks in iteritems(self.net_keyspaces) } routing_tables = routing_tree_to_tables(self.routes, net_keys) target_lengths = build_routing_table_target_lengths(system_info) routing_tables = minimise_tables(routing_tables, target_lengths) controller.load_routing_tables(routing_tables) # Assign memory to each vertex as required logger.debug("Assigning application memory") self.vertices_memory = sdram_alloc_for_vertices( controller, self.placements, self.allocations) # Call each loading function in turn logger.debug("Loading data") for fn in self.load_functions: fn(self, controller) # Load the applications onto the machine logger.debug("Loading application executables") vertices_applications = { v: v.application for v in self.vertices if v.application is not None } application_map = build_application_map(vertices_applications, self.placements, self.allocations) controller.load_application(application_map)
def load_application(self, controller, system_info): """Load the netlist to a SpiNNaker machine. Parameters ---------- controller : :py:class:`~rig.machine_control.MachineController` Controller to use to communicate with the machine. """ # Build and load the routing tables, first by building a mapping from # nets to keys and masks. logger.debug("Loading routing tables") net_keys = {n: (ks.get_value(tag=self.keyspaces.routing_tag), ks.get_mask(tag=self.keyspaces.routing_tag)) for n, ks in iteritems(self.net_keyspaces)} routing_tables = routing_tree_to_tables(self.routes, net_keys) target_lengths = build_routing_table_target_lengths(system_info) routing_tables = minimise_tables(routing_tables, target_lengths) controller.load_routing_tables(routing_tables) # Assign memory to each vertex as required logger.debug("Assigning application memory") self.vertices_memory = sdram_alloc_for_vertices( controller, self.placements, self.allocations ) # Call each loading function in turn logger.debug("Loading data") for fn in self.load_functions: fn(self, controller) # Load the applications onto the machine logger.debug("Loading application executables") vertices_applications = {v: v.application for v in self.vertices if v.application is not None} application_map = build_application_map( vertices_applications, self.placements, self.allocations ) controller.load_application(application_map)
def build_routing_tables(routes, net_keys, omit_default_routes=True): """**DEPRECATED** Convert a set of RoutingTrees into a per-chip set of routing tables. .. warning:: This method has been deprecated in favour of :py:meth:`rig.routing_table.routing_tree_to_tables` and :py:meth:`rig.routing_table.minimise`. E.g. most applications should use something like:: from rig.routing_table import routing_tree_to_tables, minimise tables = minimise(routing_tree_to_tables(routes, net_keys), target_lengths) Where target_length gives the number of available routing entries on the chips in your SpiNNaker system (see :py:func:~rig.routing_table.utils.build_routing_table_target_lengths) This command produces routing tables with entries optionally omitted when the route does not change direction (i.e. when default routing can be used). .. warning:: A :py:exc:`rig.routing_table.MultisourceRouteError` will be raised if entries with identical keys and masks but with differing routes are generated. This is not a perfect test, entries which would otherwise collide are not spotted. .. warning:: The routing trees provided are assumed to be correct and continuous (not missing any hops). If this is not the case, the output is undefined. .. note:: If a routing tree has a terminating vertex whose route is set to None, that vertex is ignored. Parameters ---------- routes : {net: :py:class:`~rig.place_and_route.routing_tree.RoutingTree`, \ ...} The complete set of RoutingTrees representing all routes in the system. (Note: this is the same datastructure produced by routers in the `place_and_route` module.) net_keys : {net: (key, mask), ...} The key and mask associated with each net. omit_default_routes : bool Do not create routing entries for routes which do not change direction (i.e. use default routing). Returns ------- {(x, y): [:py:class:`~rig.routing_table.RoutingTableEntry`, ...] """ from rig.routing_table import routing_tree_to_tables, remove_default_routes warnings.warn( "build_routing_tables() is deprecated, see " "rig.routing_table.routing_tree_to_tables()" "and rig.routing_table.minimise()", DeprecationWarning) # Build full routing tables and then remove default entries from them tables = dict() for chip, table in iteritems(routing_tree_to_tables(routes, net_keys)): if omit_default_routes: table = remove_default_routes.minimise(table, target_length=None) # If the table is empty don't add it to the dictionary of tables. if table: tables[chip] = table return tables
def make_routing_tables(): # Create a perfect SpiNNaker machine to build against machine = Machine(12, 12) # Assign a vertex to each of the 17 application cores on each chip vertices = OrderedDict( ((x, y, p), object()) for x, y in machine for p in range(1, 18) ) # Generate the vertex resources, placements and allocations (required for # routing) vertices_resources = OrderedDict( (vertex, {Cores: 1}) for vertex in itervalues(vertices) ) placements = OrderedDict( (vertex, (x, y)) for (x, y, p), vertex in iteritems(vertices) ) allocations = OrderedDict( (vertex, {Cores: slice(p, p+1)}) for (x, y, p), vertex in iteritems(vertices) ) # Compute the distance dependent probabilities - this is a geometric # distribution such that each core has a 50% chance of being connected to # each core on the same chip, 25% on chips one hop away, 12.5% on chips two # hops away, etc. p = 0.5 probs = {d: p*(1 - p)**d for d in range(max(machine.width, machine.height))} p = 0.3 dprobs = {d: p*(1 - p)**d for d in range(max(machine.width, machine.height))} # Compute offsets to get to centroids vector_centroids = list() for d in (5, 6, 7): for i in range(d + 1): for j in range(d + 1 - i): vector_centroids.append((i, j, d - i - j)) # Make the nets, each vertex is connected with distance dependent # probability to other vertices. random.seed(123) nets = OrderedDict() for source_coord, source in iteritems(vertices): # Convert source_coord to xyz form source_coord_xyz = minimise_xyz(to_xyz(source_coord[:-1])) # Add a number of centroids x, y, z = source_coord_xyz possible_centroids = [minimise_xyz((x + i, y + j, z + k)) for i, j, k in vector_centroids] n_centroids = random.choice(17*(0, ) + (1, 1) + (2, )) centroids = random.sample(possible_centroids, n_centroids) # Construct the sinks list sinks = list() for sink_coord, sink in iteritems(vertices): # Convert sink_coord to xyz form sink_coord = minimise_xyz(to_xyz(sink_coord[:-1])) # Get the path length to the original source dist = shortest_torus_path_length(source_coord_xyz, sink_coord, machine.width, machine.height) if random.random() < probs[dist]: sinks.append(sink) continue # See if the sink is connected to the centre of any of the # centroids. for coord in centroids: dist = shortest_torus_path_length( coord, sink_coord, machine.width, machine.height ) if random.random() < dprobs[dist]: sinks.append(sink) break # Add the net nets[source_coord] = Net(source, sinks) rig_nets = list(itervalues(nets)) # Just the nets # Determine how many bits to use in the keys xyp_fields = BitField(32) xyp_fields.add_field("x", length=8, start_at=24) xyp_fields.add_field("y", length=8, start_at=16) xyp_fields.add_field("p", length=5, start_at=11) xyzp_fields = BitField(32) xyzp_fields.add_field("x", length=8, start_at=24) xyzp_fields.add_field("y", length=8, start_at=16) xyzp_fields.add_field("z", length=8, start_at=8) xyzp_fields.add_field("p", length=5, start_at=3) hilbert_fields = BitField(32) hilbert_fields.add_field("index", length=16, start_at=16) hilbert_fields.add_field("p", length=5, start_at=11) random.seed(321) rnd_fields = BitField(32) rnd_fields.add_field("rnd", length=12, start_at=20) rnd_seen = set() # Generate the routing keys net_keys_xyp = OrderedDict() net_keys_xyzp = OrderedDict() net_keys_hilbert = OrderedDict() net_keys_rnd = OrderedDict() for i, (x, y) in enumerate(chip for chip in hilbert_chip_order(machine) if chip in machine): # Add the key for each net from each processor for p in range(1, 18): # Get the net net = nets[(x, y, p)] # Construct the xyp key/mask net_keys_xyp[net] = xyp_fields(x=x, y=y, p=p) # Construct the xyzp mask x_, y_, z_ = minimise_xyz(to_xyz((x, y))) net_keys_xyzp[net] = xyzp_fields(x=x_, y=y_, z=abs(z_), p=p) # Construct the Hilbert key/mask net_keys_hilbert[net] = hilbert_fields(index=i, p=p) # Construct the random 12 bit value field val = None while val is None or val in rnd_seen: val = random.getrandbits(12) rnd_seen.add(val) net_keys_rnd[net] = rnd_fields(rnd=val) # Route the network and then generate the routing tables constraints = list() print("Routing...") routing_tree = route(vertices_resources, rig_nets, machine, constraints, placements, allocations) # Write the routing tables to file for fields, desc in ((net_keys_xyp, "xyp"), (net_keys_xyzp, "xyzp"), (net_keys_hilbert, "hilbert"), (net_keys_rnd, "rnd")): print("Getting keys and masks...") keys = OrderedDict( (net, (bf.get_value(), bf.get_mask())) for net, bf in iteritems(fields) ) print("Constructing routing tables for {}...".format(desc)) tables = routing_tree_to_tables(routing_tree, keys) print([len(x) for x in itervalues(tables)]) print("Writing to file...") fn = "uncompressed/centroid_{}_{}_{}.bin".format( machine.width, machine.height, desc) with open(fn, "wb+") as f: dump_routing_tables(f, tables)
def make_routing_tables(): # Create a perfect SpiNNaker machine to build against machine = Machine(12, 12) # Assign a vertex to each of the 17 application cores on each chip vertices = OrderedDict( ((x, y, p), object()) for x, y in machine for p in range(1, 18)) # Generate the vertex resources, placements and allocations (required for # routing) vertices_resources = OrderedDict((vertex, { Cores: 1 }) for vertex in itervalues(vertices)) placements = OrderedDict( (vertex, (x, y)) for (x, y, p), vertex in iteritems(vertices)) allocations = OrderedDict((vertex, { Cores: slice(p, p + 1) }) for (x, y, p), vertex in iteritems(vertices)) # Compute the distance dependent probabilities - this is a geometric # distribution such that each core has a 50% chance of being connected to # each core on the same chip, 25% on chips one hop away, 12.5% on chips two # hops away, etc. p = 0.5 probs = { d: p * (1 - p)**d for d in range(max(machine.width, machine.height)) } p = 0.3 dprobs = { d: p * (1 - p)**d for d in range(max(machine.width, machine.height)) } # Compute offsets to get to centroids vector_centroids = list() for d in (5, 6, 7): for i in range(d + 1): for j in range(d + 1 - i): vector_centroids.append((i, j, d - i - j)) # Make the nets, each vertex is connected with distance dependent # probability to other vertices. random.seed(123) nets = OrderedDict() for source_coord, source in iteritems(vertices): # Convert source_coord to xyz form source_coord_xyz = minimise_xyz(to_xyz(source_coord[:-1])) # Add a number of centroids x, y, z = source_coord_xyz possible_centroids = [ minimise_xyz((x + i, y + j, z + k)) for i, j, k in vector_centroids ] n_centroids = random.choice(17 * (0, ) + (1, 1) + (2, )) centroids = random.sample(possible_centroids, n_centroids) # Construct the sinks list sinks = list() for sink_coord, sink in iteritems(vertices): # Convert sink_coord to xyz form sink_coord = minimise_xyz(to_xyz(sink_coord[:-1])) # Get the path length to the original source dist = shortest_torus_path_length(source_coord_xyz, sink_coord, machine.width, machine.height) if random.random() < probs[dist]: sinks.append(sink) continue # See if the sink is connected to the centre of any of the # centroids. for coord in centroids: dist = shortest_torus_path_length(coord, sink_coord, machine.width, machine.height) if random.random() < dprobs[dist]: sinks.append(sink) break # Add the net nets[source_coord] = Net(source, sinks) rig_nets = list(itervalues(nets)) # Just the nets # Determine how many bits to use in the keys xyp_fields = BitField(32) xyp_fields.add_field("x", length=8, start_at=24) xyp_fields.add_field("y", length=8, start_at=16) xyp_fields.add_field("p", length=5, start_at=11) xyzp_fields = BitField(32) xyzp_fields.add_field("x", length=8, start_at=24) xyzp_fields.add_field("y", length=8, start_at=16) xyzp_fields.add_field("z", length=8, start_at=8) xyzp_fields.add_field("p", length=5, start_at=3) hilbert_fields = BitField(32) hilbert_fields.add_field("index", length=16, start_at=16) hilbert_fields.add_field("p", length=5, start_at=11) random.seed(321) rnd_fields = BitField(32) rnd_fields.add_field("rnd", length=12, start_at=20) rnd_seen = set() # Generate the routing keys net_keys_xyp = OrderedDict() net_keys_xyzp = OrderedDict() net_keys_hilbert = OrderedDict() net_keys_rnd = OrderedDict() for i, (x, y) in enumerate(chip for chip in hilbert_chip_order(machine) if chip in machine): # Add the key for each net from each processor for p in range(1, 18): # Get the net net = nets[(x, y, p)] # Construct the xyp key/mask net_keys_xyp[net] = xyp_fields(x=x, y=y, p=p) # Construct the xyzp mask x_, y_, z_ = minimise_xyz(to_xyz((x, y))) net_keys_xyzp[net] = xyzp_fields(x=x_, y=y_, z=abs(z_), p=p) # Construct the Hilbert key/mask net_keys_hilbert[net] = hilbert_fields(index=i, p=p) # Construct the random 12 bit value field val = None while val is None or val in rnd_seen: val = random.getrandbits(12) rnd_seen.add(val) net_keys_rnd[net] = rnd_fields(rnd=val) # Route the network and then generate the routing tables constraints = list() print("Routing...") routing_tree = route(vertices_resources, rig_nets, machine, constraints, placements, allocations) # Write the routing tables to file for fields, desc in ((net_keys_xyp, "xyp"), (net_keys_xyzp, "xyzp"), (net_keys_hilbert, "hilbert"), (net_keys_rnd, "rnd")): print("Getting keys and masks...") keys = OrderedDict((net, (bf.get_value(), bf.get_mask())) for net, bf in iteritems(fields)) print("Constructing routing tables for {}...".format(desc)) tables = routing_tree_to_tables(routing_tree, keys) print([len(x) for x in itervalues(tables)]) print("Writing to file...") fn = "uncompressed/centroid_{}_{}_{}.bin".format( machine.width, machine.height, desc) with open(fn, "wb+") as f: dump_routing_tables(f, tables)
def make_routing_tables(): # Create a perfect SpiNNaker machine to build against machine = Machine(12, 12) # Assign a vertex to each of the 17 application cores on each chip vertices = OrderedDict( ((x, y, p), object()) for x, y in machine for p in range(1, 18) ) # Generate the vertex resources, placements and allocations (required for # routing) vertices_resources = OrderedDict( (vertex, {Cores: 1}) for vertex in itervalues(vertices) ) placements = OrderedDict( (vertex, (x, y)) for (x, y, p), vertex in iteritems(vertices) ) allocations = OrderedDict( (vertex, {Cores: slice(p, p+1)}) for (x, y, p), vertex in iteritems(vertices) ) # Compute the distance dependent probabilities probs = {d: .5*math.exp(-.65*d) for d in range(max(machine.width, machine.height))} # Make the nets, each vertex is connected with distance dependent # probability to other vertices. random.seed(123) nets = OrderedDict() for source_coord, source in iteritems(vertices): # Convert source_coord to xyz form source_coord_xyz = minimise_xyz(to_xyz(source_coord[:-1])) # Construct the sinks list sinks = list() for sink_coord, sink in iteritems(vertices): # Convert sink_coord to xyz form sink_coord = minimise_xyz(to_xyz(sink_coord[:-1])) # Get the path length dist = shortest_torus_path_length(source_coord_xyz, sink_coord, machine.width, machine.height) if random.random() < probs[dist]: sinks.append(sink) # Add the net nets[source_coord] = Net(source, sinks) rig_nets = list(itervalues(nets)) # Just the nets # Determine how many bits to use in the keys xyp_fields = BitField(32) xyp_fields.add_field("x", length=8, start_at=24) xyp_fields.add_field("y", length=8, start_at=16) xyp_fields.add_field("p", length=5, start_at=11) xyzp_fields = BitField(32) xyzp_fields.add_field("x", length=8, start_at=24) xyzp_fields.add_field("y", length=8, start_at=16) xyzp_fields.add_field("z", length=8, start_at=8) xyzp_fields.add_field("p", length=5, start_at=3) hilbert_fields = BitField(32) hilbert_fields.add_field("index", length=16, start_at=16) hilbert_fields.add_field("p", length=5, start_at=11) random.seed(321) rnd_fields = BitField(32) rnd_fields.add_field("rnd", length=12, start_at=20) rnd_seen = set() # Generate the routing keys net_keys_xyp = OrderedDict() net_keys_xyzp = OrderedDict() net_keys_hilbert = OrderedDict() net_keys_rnd = OrderedDict() for i, (x, y) in enumerate(chip for chip in hilbert_chip_order(machine) if chip in machine): # Add the key for each net from each processor for p in range(1, 18): # Get the net net = nets[(x, y, p)] # Construct the xyp key/mask net_keys_xyp[net] = xyp_fields(x=x, y=y, p=p) # Construct the xyzp mask x_, y_, z_ = minimise_xyz(to_xyz((x, y))) net_keys_xyzp[net] = xyzp_fields(x=x_, y=y_, z=abs(z_), p=p) # Construct the Hilbert key/mask net_keys_hilbert[net] = hilbert_fields(index=i, p=p) # Construct the random 12 bit value field val = None while val is None or val in rnd_seen: val = random.getrandbits(12) rnd_seen.add(val) net_keys_rnd[net] = rnd_fields(rnd=val) # Route the network and then generate the routing tables constraints = list() print("Routing...") routing_tree = route(vertices_resources, rig_nets, machine, constraints, placements, allocations) # Write the routing tables to file for fields, desc in ((net_keys_xyp, "xyp"), (net_keys_xyzp, "xyzp"), (net_keys_hilbert, "hilbert"), (net_keys_rnd, "rnd")): print("Getting keys and masks...") keys = {net: (bf.get_value(), bf.get_mask()) for net, bf in iteritems(fields)} print("Constructing routing tables for {}...".format(desc)) tables = routing_tree_to_tables(routing_tree, keys) print([len(x) for x in itervalues(tables)]) print("Writing to file...") fn = "uncompressed/gaussian_{}_{}_{}.bin".format( machine.width, machine.height, desc) with open(fn, "wb+") as f: dump_routing_tables(f, tables)
rng = np.random.RandomState(seed=2804) centroid_routes, local_routes = get_network(machine, rng) # Find the necessary number of random bits rnd_bits = int(np.ceil(np.log2(machine.width * machine.height * 17))) # Construct the keys and routing tables algs = (common.assign_xyp_keys, common.assign_xyzp_keys, common.assign_hilbert_keys, common.assign_random_keys, common.assign_random_keys) all_args = (tuple(), tuple(), (machine, ), (machine, 2804, 21), (machine, 2804, rnd_bits)) fps = ("xyp", "xyzp", "hilbert", "rnd21", "rnd{:d}".format(rnd_bits)) for routes, prefix in ((centroid_routes, "centroid"), (local_routes, "locally_connected")): for alg, args, fp in zip(algs, all_args, fps): logger.info("Generating keys...") keys = alg(iterkeys(routes), *args) # Generate the routing tables logger.info("Building routing tables...") tables = routing_tree_to_tables(routes, keys) # Dump to file logger.info("Writing to file...") with open("benchmarks/{}_{}.bin".format(prefix, fp), 'wb+') as f: common.dump_routing_tables(f, tables)
def place_and_route_wrapper(vertices_resources, vertices_applications, nets, net_keys, system_info, constraints=[], place=default_place, place_kwargs={}, allocate=default_allocate, allocate_kwargs={}, route=default_route, route_kwargs={}, minimise_tables_methods=(remove_default_entries, ordered_covering), core_resource=Cores, sdram_resource=SDRAM, sram_resource=SRAM): """Wrapper for core place-and-route tasks for the common case. This function takes a set of vertices and nets and produces placements, allocations, minimised routing tables and application loading information. .. note:: This function replaces the deprecated :py:func:`.wrapper` function and makes use of the additional information provided by the :py:class:`~rig.machine_control.machine_controller.SystemInfo` object to infer the constraints required by most applications such as reserving non-idle cores such as the monitor processor. Parameters ---------- vertices_resources : {vertex: {resource: quantity, ...}, ...} A dictionary from vertex to the required resources for that vertex. This dictionary must include an entry for every vertex in the application. Resource requirements are specified by a dictionary `{resource: quantity, ...}` where `resource` is some resource identifier and `quantity` is a non-negative integer representing the quantity of that resource required. vertices_applications : {vertex: application, ...} A dictionary from vertices to the application binary to load onto cores associated with that vertex. Applications are given as a string containing the file name of the binary to load. nets : [:py:class:`~rig.netlist.Net`, ...] A list (in no particular order) defining the nets connecting vertices. net_keys : {:py:class:`~rig.netlist.Net`: (key, mask), ...} A dictionary from nets to (key, mask) tuples to be used in SpiNNaker routing tables for routes implementing this net. The key and mask should be given as 32-bit integers. system_info : \ :py:class:`~rig.machine_control.machine_controller.SystemInfo` A data structure which defines the resources available in the target SpiNNaker machine, typically returned by :py:meth:`rig.machine_control.MachineController.get_system_info`. This information will be used internally to build a :py:class:`~rig.place_and_route.Machine` and set of :py:mod:`rig.place_and_route.constraints` which describe the SpiNNaker machine used and ensure placement, allocation and routing only use working and unused chips, cores, memory and links. If greater control over these datastructures is required this wrapper may not be appropriate. constraints : [constraint, ...] **Optional.** A list of additional constraints on placement, allocation and routing. Available constraints are provided in the :py:mod:`rig.place_and_route.constraints` module. These constraints will be added to those derrived from the ``system_info`` argument which restrict placement and allocation to only idle cores. place : function (Default: :py:func:`rig.place_and_route.place`) **Optional.** Placement algorithm to use. place_kwargs : dict (Default: {}) **Optional.** Algorithm-specific arguments for the placer. allocate : function (Default: :py:func:`rig.place_and_route.allocate`) **Optional.** Allocation algorithm to use. allocate_kwargs : dict (Default: {}) **Optional.** Algorithm-specific arguments for the allocator. route : function (Default: :py:func:`rig.place_and_route.route`) **Optional.** Routing algorithm to use. route_kwargs : dict (Default: {}) **Optional.** Algorithm-specific arguments for the router. minimise_tables_methods : [:py:func:`rig.routing_table.minimise`, ...] **Optional.** An iterable of routing table minimisation algorithms to use when routing tables outgrow the space available. Each method is tried in the order presented and the first to meet the required target length for a given chip is used. Consequently less computationally costly algorithms should be nearer the start of the list. The default methods will try to remove default routes (:py:meth:`rig.routing_table.remove_default_routes.minimise`) and then fall back on the ordered covering algorithm (:py:meth:`rig.routing_table.ordered_covering.minimise`). core_resource : resource (Default: :py:data:`~rig.place_and_route.Cores`) **Optional.** The resource identifier used for cores. sdram_resource : resource (Default: :py:data:`~rig.place_and_route.SDRAM`) **Optional.** The resource identifier used for SDRAM. sram_resource : resource (Default: :py:data:`~rig.place_and_route.SRAM`) **Optional.** The resource identifier used for SRAM (System RAM). Returns ------- placements : {vertex: (x, y), ...} A dictionary from vertices to the chip coordinate produced by placement. allocations : {vertex: {resource: slice, ...}, ...} A dictionary from vertices to the resources allocated to it. Resource allocations are dictionaries from resources to a :py:class:`slice` defining the range of the given resource type allocated to the vertex. These :py:class:`slice` objects have `start` <= `end` and `step` set to None. application_map : {application: {(x, y): set([core_num, ...]), ...}, ...} A dictionary from application to the set of cores it should be loaded onto. The set of cores is given as a dictionary from chip to sets of core numbers. routing_tables : {(x, y): \ [:py:class:`~rig.routing_table.RoutingTableEntry`, \ ...], ...} The generated routing tables. Provided as a dictionary from chip to a list of routing table entries. """ # Infer place-and-route data-structures from SystemInfo machine = build_machine(system_info, core_resource=core_resource, sdram_resource=sdram_resource, sram_resource=sram_resource) base_constraints = build_core_constraints(system_info, core_resource) constraints = base_constraints + constraints # Place/Allocate/Route placements = place(vertices_resources, nets, machine, constraints, **place_kwargs) allocations = allocate(vertices_resources, nets, machine, constraints, placements, **allocate_kwargs) routes = route(vertices_resources, nets, machine, constraints, placements, allocations, core_resource, **route_kwargs) # Build data-structures ready to feed to the machine loading functions application_map = build_application_map(vertices_applications, placements, allocations, core_resource) # Build routing tables from the generated routes routing_tables = routing_tree_to_tables(routes, net_keys) # Minimise the routing tables, if required target_lengths = build_routing_table_target_lengths(system_info) routing_tables = minimise_tables(routing_tables, target_lengths, minimise_tables_methods) return placements, allocations, application_map, routing_tables
# Build the network logger.info("Building netlist...") rng = np.random.RandomState(seed=2804) centroid_routes, local_routes = get_network(machine, rng) # Find the necessary number of random bits rnd_bits = int(np.ceil(np.log2(machine.width * machine.height * 17))) # Construct the keys and routing tables algs = (common.assign_xyp_keys, common.assign_xyzp_keys, common.assign_hilbert_keys, common.assign_random_keys, common.assign_random_keys) all_args = (tuple(), tuple(), (machine, ), (machine, 2804, 21), (machine, 2804, rnd_bits)) fps = ("xyp", "xyzp", "hilbert", "rnd21", "rnd{:d}".format(rnd_bits)) for routes, prefix in ((centroid_routes, "centroid"), (local_routes, "locally_connected")): for alg, args, fp in zip(algs, all_args, fps): logger.info("Generating keys...") keys = alg(iterkeys(routes), *args) # Generate the routing tables logger.info("Building routing tables...") tables = routing_tree_to_tables(routes, keys) # Dump to file logger.info("Writing to file...") with open("benchmarks/{}_{}.bin".format(prefix, fp), 'wb+') as f: common.dump_routing_tables(f, tables)