docs: 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)