예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
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
예제 #4
0
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)
예제 #5
0
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)
예제 #6
0
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)
예제 #8
0
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
예제 #9
0
    # 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)