示例#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):
        """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: (n.keyspace.get_value(tag=self.keyspaces.routing_tag),
                        n.keyspace.get_mask(tag=self.keyspaces.routing_tag))
                    for n in self.nets}
        routing_tables = build_routing_tables(self.routes, net_keys)
        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
        )

        # Inform the vertices of where that chunk of memory is
        for vertex, memory in iteritems(self.vertices_memory):
            x, y = self.placements[vertex]
            p = self.allocations[vertex][Cores].start
            controller.write_vcpu_struct_field(
                "user0", memory.address, x, y, p)

        # 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 run(self):
        """Run the simulation."""
        # Define the resource requirements of each component in the simulation.
        vertices_resources = {
            # Every component runs on exactly one core and consumes a certain
            # amount of SDRAM to hold configuration data.
            component: {Cores: 1, SDRAM: component._get_config_size()}
            for component in self._components
        }

        # Work out what SpiNNaker application needs to be loaded for each
        # component
        vertices_applications = {component: component._get_kernel()
                                 for component in self._components}

        # Convert the Wire objects into Rig Net objects and create a lookup
        # from Net to the (key, mask) to use.
        net_keys = {Net(wire.source, wire.sinks): (wire.routing_key,
                                                   0xFFFFFFFF)
                    for wire in self._wires}
        nets = list(net_keys)

        # Boot the SpiNNaker machine and interrogate it to determine what
        # resources (e.g. cores, SDRAM etc.) are available.
        mc = MachineController(self._hostname)
        mc.boot()
        system_info = mc.get_system_info()

        # Automatically chose which chips and cores to use for each component
        # and generate routing tables.
        placements, allocations, application_map, routing_tables = \
            place_and_route_wrapper(vertices_resources,
                                    vertices_applications,
                                    nets, net_keys,
                                    system_info)

        with mc.application():
            # Allocate memory for configuration data, tagged by core number.
            memory_allocations = sdram_alloc_for_vertices(mc, placements,
                                                          allocations)

            # Load the configuration data for all components
            for component, memory in memory_allocations.items():
                component._write_config(memory)

            # Load all routing tables
            mc.load_routing_tables(routing_tables)

            # Load all SpiNNaker application kernels
            mc.load_application(application_map)

            # Wait for all six cores to reach the 'sync0' barrier
            mc.wait_for_cores_to_reach_state("sync0", len(self._components))

            # Send the 'sync0' signal to start execution and wait for the
            # simulation to finish.
            mc.send_signal("sync0")
            time.sleep(self.length * 0.001)
            mc.wait_for_cores_to_reach_state("exit", len(self._components))

            # Retrieve result data
            for component, memory in memory_allocations.items():
                component._read_results(memory)
示例#5
0
 def simulate(self, hostname, sim_length=128):
     """Simulate the current circuit for the specified number of timer
     ticks.
     """
     # We define the set of ticks for convenience when plotting
     self.ticks = list(range(sim_length))
     
     # We define our simulation within the following "with" block which
     # causes the SpiNNaker applications and their associated resources to
     # be automatically freed at the end of simulation or in the event of
     # some failure.
     mc = MachineController(hostname)
     with mc.application():
         # Step 1: Determine what resources are available in the supplied
         # SpiNNaker machine.
         system_info = mc.get_system_info()
         
         # Step 2: Describe the simulation as a graph of SpiNNaker applications
         # which Rig will place in the machine
         
         # Each device uses a single core and consumes some amount of SDRAM for
         # config and result data.
         vertices_resources = {
             d: {Cores: 1, SDRAM: d.sdram_required(sim_length)}
             for d in self._devices
         }
         vertices_applications = {d: d.app_name for d in self._devices}
         
         # We'll make a net for every signal in our circuit. Packets will have
         # their bottom 31-bits be the unique signal ID and the top bit will
         # contain the state of the signal (and is thus masked off here)
         net_keys = {Net(s.source, s.sinks): (s.id, 0x7FFFFFFF)
                     for s in self._signals}
         nets = list(net_keys)
         
         # Step 3: Place and route the application graph we just described
         placements, allocations, application_map, routing_tables = \
             place_and_route_wrapper(vertices_resources, vertices_applications,
                                     nets, net_keys, system_info)
         
         # Step 4: Allocate SDRAM for each device. We use the
         # `sdram_alloc_for_vertices` utility method to allocate SDRAM on
         # the chip each device has been placed on, tagging the allocation
         # with the core number so the application can discover the
         # allocation using `sark_tag_ptr`. The returned file-like objects
         # may then conveniently be used to read/write to this allocated
         # region of SDRAM.
         # A dictionary {Device: filelike} is returned.
         device_sdram_filelikes = sdram_alloc_for_vertices(mc, placements, allocations)
         
         # Step 5: Write the config data to SDRAM for all devices.
         for d in self._devices:
             d.write_config(device_sdram_filelikes[d], sim_length)
         
         # Step 6: Load application binaries and routing tables
         mc.load_application(application_map)
         mc.load_routing_tables(routing_tables)
         
         # Step 7: Wait for all applications to reach the initial sync0
         # barrier and then start the simulation.
         mc.wait_for_cores_to_reach_state("sync0", len(self._devices))
         mc.send_signal("sync0")
         
         # Step 8: Wait for the simulation to run and all cores to finish
         # executing and enter the EXIT state.
         time.sleep(0.001 * sim_length)
         mc.wait_for_cores_to_reach_state("exit", len(self._devices))
         
         # Step 9: Retrieve any results and we're done!
         for d in self._devices:
             d.read_results(device_sdram_filelikes[d], sim_length)