def test_get_max_row_bytes(dynamics, size, exception, max_size):
    io = SynapseIORowBased()
    population_table = MasterPopTableAsBinarySearch()
    synapse_information = SynapseInformation(None, dynamics, 0)
    in_edge = ProjectionApplicationEdge(None, None, synapse_information)
    if exception is not None:
        with pytest.raises(exception) as exc_info:
            io._get_max_row_bytes(size, dynamics, population_table, in_edge,
                                  size)
        assert exc_info.value.max_size == max_size
    else:
        actual_size = io._get_max_row_bytes(size, dynamics, population_table,
                                            in_edge, size)
        assert actual_size == max_size
Example #2
0
def test_get_allowed_row_length(dynamics_class, timing, weight, size,
                                exception, max_size):
    spynnaker8.setup()
    if timing is not None and weight is not None:
        dynamics = dynamics_class(timing(), weight())
    else:
        dynamics = dynamics_class()
    synapse_information = SynapseInformation(None, None, None, False, False,
                                             None, None, dynamics, 0, True)
    in_edge = ProjectionApplicationEdge(None, None, synapse_information)
    if exception is not None:
        with pytest.raises(exception) as exc_info:
            _get_allowed_row_length(size, dynamics, in_edge, size)
        assert exc_info.value.max_size == max_size
    else:
        actual_size = _get_allowed_row_length(size, dynamics, in_edge, size)
        assert actual_size == max_size
def test_slices():
    unittest_setup()
    app_edge = ProjectionApplicationEdge(None, None, None)
    mv0_2 = SimpleMachineVertex(None, None, None, None, Slice(0, 1))
    mv2_4 = SimpleMachineVertex(None, None, None, None, Slice(2, 3))
    mv4_6 = SimpleMachineVertex(None, None, None, None, Slice(4, 5))
    app_edge.remember_associated_machine_edge(MachineEdge(mv0_2, mv2_4))
    app_edge.remember_associated_machine_edge(MachineEdge(mv4_6, mv0_2))
    app_edge.remember_associated_machine_edge(MachineEdge(mv0_2, mv2_4))
    assert app_edge.pre_slices == [Slice(0, 1), Slice(4, 5)]
    post1 = app_edge.post_slices
    assert post1 == [Slice(0, 1), Slice(2, 3)]
    app_edge.remember_associated_machine_edge(MachineEdge(mv0_2, mv0_2))
    app_edge.remember_associated_machine_edge(MachineEdge(mv2_4, mv2_4))
    assert app_edge.pre_slices == [Slice(0, 1), Slice(2, 3), Slice(4, 5)]
    post2 = app_edge.post_slices
    assert post1 == post2
    assert id(post1) != id(post2)
Example #4
0
def test_get_max_row_length(dynamics_class, timing, weight, size, exception,
                            max_size):
    MockSimulator.setup()
    if timing is not None and weight is not None:
        dynamics = dynamics_class(timing(), weight())
    else:
        dynamics = dynamics_class()
    io = SynapseIORowBased()
    population_table = MasterPopTableAsBinarySearch()
    synapse_information = SynapseInformation(None, None, None, None, None,
                                             None, dynamics, 0)
    in_edge = ProjectionApplicationEdge(None, None, synapse_information)
    if exception is not None:
        with pytest.raises(exception) as exc_info:
            io._get_max_row_length(size, dynamics, population_table, in_edge,
                                   size)
        assert exc_info.value.max_size == max_size
    else:
        actual_size = io._get_max_row_length(size, dynamics, population_table,
                                             in_edge, size)
        assert actual_size == max_size
    def __init__(self, spinnaker_control, connector, synapse_dynamics_stdp,
                 target, pre_synaptic_population, post_synaptic_population,
                 rng, machine_time_step, user_max_delay, label,
                 time_scale_factor):
        # pylint: disable=too-many-arguments, too-many-locals
        self._spinnaker_control = spinnaker_control
        self._projection_edge = None
        self._host_based_synapse_list = None
        self._has_retrieved_synaptic_list_from_machine = False
        self._requires_mapping = True
        self._label = None

        if not isinstance(post_synaptic_population._get_vertex,
                          AbstractAcceptsIncomingSynapses):
            raise ConfigurationException(
                "postsynaptic population is not designed to receive"
                " synaptic projections")

        # sort out synapse type
        synapse_type = post_synaptic_population._get_vertex\
            .get_synapse_id_by_target(target)
        if synapse_type is None:
            raise ConfigurationException(
                "Synapse target {} not found in {}".format(
                    target, post_synaptic_population.label))

        # set the plasticity dynamics for the post pop (allows plastic stuff
        #  when needed)
        post_synaptic_population._get_vertex.set_synapse_dynamics(
            synapse_dynamics_stdp)

        # Set and store information for future processing
        self._synapse_information = SynapseInformation(connector,
                                                       synapse_dynamics_stdp,
                                                       synapse_type)
        connector.set_projection_information(pre_synaptic_population,
                                             post_synaptic_population, rng,
                                             machine_time_step)

        # handle max delay
        max_delay = synapse_dynamics_stdp.get_delay_maximum(connector)
        if max_delay is None:
            max_delay = user_max_delay

        # check if all delays requested can fit into the natively supported
        # delays in the models
        post_vertex_max_supported_delay_ms = \
            post_synaptic_population._get_vertex \
            .get_maximum_delay_supported_in_ms(machine_time_step)
        if max_delay > (post_vertex_max_supported_delay_ms +
                        _delay_extension_max_supported_delay):
            raise ConfigurationException(
                "The maximum delay {} for projection is not supported".format(
                    max_delay))

        if max_delay > user_max_delay / (machine_time_step / 1000.0):
            logger.warning("The end user entered a max delay"
                           " for which the projection breaks")

        # check that the projection edges label is not none, and give an
        # auto generated label if set to None
        if label is None:
            label = "projection edge {}".format(
                spinnaker_control.none_labelled_edge_count)
            spinnaker_control.increment_none_labelled_edge_count()

        # Find out if there is an existing edge between the populations
        edge_to_merge = self._find_existing_edge(
            pre_synaptic_population._get_vertex,
            post_synaptic_population._get_vertex)
        if edge_to_merge is not None:

            # If there is an existing edge, add the connector
            edge_to_merge.add_synapse_information(self._synapse_information)
            self._projection_edge = edge_to_merge
        else:

            # If there isn't an existing edge, create a new one
            self._projection_edge = ProjectionApplicationEdge(
                pre_synaptic_population._get_vertex,
                post_synaptic_population._get_vertex,
                self._synapse_information,
                label=label)

            # add edge to the graph
            spinnaker_control.add_application_edge(
                self._projection_edge, constants.SPIKE_PARTITION_ID)

        # If the delay exceeds the post vertex delay, add a delay extension
        if max_delay > post_vertex_max_supported_delay_ms:
            delay_edge = self._add_delay_extension(
                pre_synaptic_population, post_synaptic_population, max_delay,
                post_vertex_max_supported_delay_ms, machine_time_step,
                time_scale_factor)
            self._projection_edge.delay_edge = delay_edge

        # add projection to the SpiNNaker control system
        spinnaker_control.add_projection(self)

        # If there is a virtual board, we need to hold the data in case the
        # user asks for it
        self._virtual_connection_list = None
        if spinnaker_control.use_virtual_board:
            self._virtual_connection_list = list()
            pre_vertex = pre_synaptic_population._get_vertex
            post_vertex = post_synaptic_population._get_vertex
            connection_holder = ConnectionHolder(None, False,
                                                 pre_vertex.n_atoms,
                                                 post_vertex.n_atoms,
                                                 self._virtual_connection_list)

            post_vertex.add_pre_run_connection_holder(
                connection_holder, self._projection_edge,
                self._synapse_information)
Example #6
0
    def test_write_synaptic_matrix_and_master_population_table(self):
        MockSimulator.setup()

        default_config_paths = os.path.join(
            os.path.dirname(abstract_spinnaker_common.__file__),
            AbstractSpiNNakerCommon.CONFIG_FILE_NAME)

        config = conf_loader.load_config(
            AbstractSpiNNakerCommon.CONFIG_FILE_NAME, default_config_paths)
        config.set("Simulation", "one_to_one_connection_dtcm_max_bytes", 40)

        machine_time_step = 1000.0

        pre_app_vertex = SimpleApplicationVertex(10)
        pre_vertex = SimpleMachineVertex(resources=None)
        pre_vertex_slice = Slice(0, 9)
        post_app_vertex = SimpleApplicationVertex(10)
        post_vertex = SimpleMachineVertex(resources=None)
        post_vertex_slice = Slice(0, 9)
        post_slice_index = 0
        one_to_one_connector_1 = OneToOneConnector(None)
        one_to_one_connector_1.set_projection_information(
            pre_app_vertex, post_app_vertex, None, machine_time_step)
        one_to_one_connector_1.set_weights_and_delays(1.5, 1.0)
        one_to_one_connector_2 = OneToOneConnector(None)
        one_to_one_connector_2.set_projection_information(
            pre_app_vertex, post_app_vertex, None, machine_time_step)
        one_to_one_connector_2.set_weights_and_delays(2.5, 2.0)
        all_to_all_connector = AllToAllConnector(None)
        all_to_all_connector.set_projection_information(
            pre_app_vertex, post_app_vertex, None, machine_time_step)
        all_to_all_connector.set_weights_and_delays(4.5, 4.0)
        direct_synapse_information_1 = SynapseInformation(
            one_to_one_connector_1, SynapseDynamicsStatic(), 0)
        direct_synapse_information_2 = SynapseInformation(
            one_to_one_connector_2, SynapseDynamicsStatic(), 1)
        all_to_all_synapse_information = SynapseInformation(
            all_to_all_connector, SynapseDynamicsStatic(), 0)
        app_edge = ProjectionApplicationEdge(pre_app_vertex, post_app_vertex,
                                             direct_synapse_information_1)
        app_edge.add_synapse_information(direct_synapse_information_2)
        app_edge.add_synapse_information(all_to_all_synapse_information)
        machine_edge = ProjectionMachineEdge(app_edge.synapse_information,
                                             pre_vertex, post_vertex)
        partition_name = "TestPartition"

        graph = MachineGraph("Test")
        graph.add_vertex(pre_vertex)
        graph.add_vertex(post_vertex)
        graph.add_edge(machine_edge, partition_name)

        graph_mapper = GraphMapper()
        graph_mapper.add_vertex_mapping(pre_vertex, pre_vertex_slice,
                                        pre_app_vertex)
        graph_mapper.add_vertex_mapping(post_vertex, post_vertex_slice,
                                        post_app_vertex)
        graph_mapper.add_edge_mapping(machine_edge, app_edge)

        weight_scales = [4096.0, 4096.0]

        key = 0
        routing_info = RoutingInfo()
        routing_info.add_partition_info(
            PartitionRoutingInfo(
                [BaseKeyAndMask(key, 0xFFFFFFF0)],
                graph.get_outgoing_edge_partition_starting_at_vertex(
                    pre_vertex, partition_name)))

        temp_spec = tempfile.mktemp()
        spec_writer = FileDataWriter(temp_spec)
        spec = DataSpecificationGenerator(spec_writer, None)
        master_pop_sz = 1000
        master_pop_region = 0
        all_syn_block_sz = 2000
        synapse_region = 1
        spec.reserve_memory_region(master_pop_region, master_pop_sz)
        spec.reserve_memory_region(synapse_region, all_syn_block_sz)

        synapse_type = MockSynapseType()

        synaptic_manager = SynapticManager(synapse_type=synapse_type,
                                           ring_buffer_sigma=5.0,
                                           spikes_per_second=100.0,
                                           config=config)
        synaptic_manager._write_synaptic_matrix_and_master_population_table(
            spec, [post_vertex_slice], post_slice_index, post_vertex,
            post_vertex_slice, all_syn_block_sz, weight_scales,
            master_pop_region, synapse_region, routing_info, graph_mapper,
            graph, machine_time_step)
        spec.end_specification()
        spec_writer.close()

        spec_reader = FileDataReader(temp_spec)
        executor = DataSpecificationExecutor(spec_reader,
                                             master_pop_sz + all_syn_block_sz)
        executor.execute()

        master_pop_table = executor.get_region(0)
        synaptic_matrix = executor.get_region(1)

        all_data = bytearray()
        all_data.extend(
            master_pop_table.region_data[:master_pop_table.max_write_pointer])
        all_data.extend(
            synaptic_matrix.region_data[:synaptic_matrix.max_write_pointer])
        master_pop_table_address = 0
        synaptic_matrix_address = master_pop_table.max_write_pointer
        direct_synapses_address = struct.unpack_from(
            "<I", synaptic_matrix.region_data)[0]
        direct_synapses_address += synaptic_matrix_address + 8
        indirect_synapses_address = synaptic_matrix_address + 4
        placement = Placement(None, 0, 0, 1)
        transceiver = MockTransceiverRawData(all_data)

        # Get the master population table details
        items = synaptic_manager._poptable_type\
            .extract_synaptic_matrix_data_location(
                key, master_pop_table_address, transceiver,
                placement.x, placement.y)

        # The first entry should be direct, but the rest should be indirect;
        # the second is potentially direct, but has been restricted by the
        # restriction on the size of the direct matrix
        assert len(items) == 3

        # TODO: This has been changed because direct matrices are disabled!
        assert not items[0][2]
        assert not items[1][2]
        assert not items[2][2]

        data_1, row_len_1 = synaptic_manager._retrieve_synaptic_block(
            transceiver=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=0,
            using_extra_monitor_cores=False)
        connections_1 = synaptic_manager._synapse_io.read_synapses(
            direct_synapse_information_1, pre_vertex_slice, post_vertex_slice,
            row_len_1, 0, 2, weight_scales, data_1, None,
            app_edge.n_delay_stages, machine_time_step)

        # The first matrix is a 1-1 matrix, so row length is 1
        assert row_len_1 == 1

        # Check that all the connections have the right weight and delay
        assert len(connections_1) == post_vertex_slice.n_atoms
        assert all([conn["weight"] == 1.5 for conn in connections_1])
        assert all([conn["delay"] == 1.0 for conn in connections_1])

        data_2, row_len_2 = synaptic_manager._retrieve_synaptic_block(
            transceiver=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=1,
            using_extra_monitor_cores=False)
        connections_2 = synaptic_manager._synapse_io.read_synapses(
            direct_synapse_information_2, pre_vertex_slice, post_vertex_slice,
            row_len_2, 0, 2, weight_scales, data_2, None,
            app_edge.n_delay_stages, machine_time_step)

        # The second matrix is a 1-1 matrix, so row length is 1
        assert row_len_2 == 1

        # Check that all the connections have the right weight and delay
        assert len(connections_2) == post_vertex_slice.n_atoms
        assert all([conn["weight"] == 2.5 for conn in connections_2])
        assert all([conn["delay"] == 2.0 for conn in connections_2])

        data_3, row_len_3 = synaptic_manager._retrieve_synaptic_block(
            transceiver=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=2,
            using_extra_monitor_cores=False)
        connections_3 = synaptic_manager._synapse_io.read_synapses(
            all_to_all_synapse_information, pre_vertex_slice,
            post_vertex_slice, row_len_3, 0, 2, weight_scales, data_3, None,
            app_edge.n_delay_stages, machine_time_step)

        # The third matrix is an all-to-all matrix, so length is n_atoms
        assert row_len_3 == post_vertex_slice.n_atoms

        # Check that all the connections have the right weight and delay
        assert len(connections_3) == \
            post_vertex_slice.n_atoms * pre_vertex_slice.n_atoms
        assert all([conn["weight"] == 4.5 for conn in connections_3])
        assert all([conn["delay"] == 4.0 for conn in connections_3])
Example #7
0
    def __init__(self,
                 pre_synaptic_population,
                 post_synaptic_population,
                 connector,
                 synapse_type=None,
                 source=None,
                 receptor_type=None,
                 space=None,
                 label=None):
        """
        :param ~spynnaker.pyNN.models.populations.PopulationBase \
                pre_synaptic_population:
        :param ~spynnaker.pyNN.models.populations.PopulationBase \
                post_synaptic_population:
        :param AbstractConnector connector:
        :param AbstractSynapseDynamics synapse_type:
        :param None source: Unsupported; must be None
        :param str receptor_type:
        :param ~pyNN.space.Space space:
        :param str label:
        """
        # pylint: disable=too-many-arguments, too-many-locals
        if source is not None:
            raise NotImplementedError(
                "sPyNNaker {} does not yet support multi-compartmental "
                "cells.".format(__version__))

        sim = get_simulator()
        self.__projection_edge = None
        self.__host_based_synapse_list = None
        self.__has_retrieved_synaptic_list_from_machine = False
        self.__requires_mapping = True
        self.__label = label

        pre_is_view = self.__check_population(pre_synaptic_population,
                                              connector)
        post_is_view = self.__check_population(post_synaptic_population,
                                               connector)

        # set default label
        if label is None:
            # set the projection's label to a default (maybe non-unique!)
            self.__label = ("from pre {} to post {} with connector {}".format(
                pre_synaptic_population.label, post_synaptic_population.label,
                connector))
            # give an auto generated label for the underlying edge
            label = "projection edge {}".format(sim.none_labelled_edge_count)
            sim.increment_none_labelled_edge_count()

        # Handle default synapse type
        if synapse_type is None:
            synapse_dynamics = SynapseDynamicsStatic()
        else:
            synapse_dynamics = synapse_type

        # set the space function as required
        if space is None:
            space = PyNNSpace()
        connector.set_space(space)

        pre_vertex = pre_synaptic_population._vertex
        post_vertex = post_synaptic_population._vertex

        if not isinstance(post_vertex, AbstractAcceptsIncomingSynapses):
            raise ConfigurationException(
                "postsynaptic population is not designed to receive"
                " synaptic projections")

        # sort out synapse type
        synaptic_type = post_vertex.get_synapse_id_by_target(receptor_type)
        synapse_type_from_dynamics = False
        if synaptic_type is None:
            synaptic_type = synapse_dynamics.get_synapse_id_by_target(
                receptor_type)
            synapse_type_from_dynamics = True
        if synaptic_type is None:
            raise ConfigurationException(
                "Synapse target {} not found in {}".format(
                    receptor_type, post_synaptic_population.label))

        # as a from-list connector can have plastic parameters, grab those (
        # if any) and add them to the synapse dynamics object
        if isinstance(connector, FromListConnector):
            connector._apply_parameters_to_synapse_type(synaptic_type)

        # round the delays to multiples of full timesteps
        # (otherwise SDRAM estimation calculations can go wrong)
        if ((not isinstance(synapse_dynamics.delay, RandomDistribution))
                and (not isinstance(synapse_dynamics.delay, str))):
            synapse_dynamics.set_delay(
                numpy.rint(
                    numpy.array(synapse_dynamics.delay) *
                    machine_time_step_per_ms()) * machine_time_step_ms())

        # set the plasticity dynamics for the post pop (allows plastic stuff
        #  when needed)
        post_vertex.set_synapse_dynamics(synapse_dynamics)

        # get rng if needed
        rng = connector.rng if hasattr(connector, "rng") else None
        # Set and store synapse information for future processing
        self.__synapse_information = SynapseInformation(
            connector, pre_synaptic_population, post_synaptic_population,
            pre_is_view, post_is_view, rng, synapse_dynamics, synaptic_type,
            receptor_type, sim.use_virtual_board, synapse_type_from_dynamics,
            synapse_dynamics.weight, synapse_dynamics.delay)

        # Set projection information in connector
        connector.set_projection_information(self.__synapse_information)

        # Find out if there is an existing edge between the populations
        edge_to_merge = self._find_existing_edge(pre_vertex, post_vertex)
        if edge_to_merge is not None:

            # If there is an existing edge, add the connector
            edge_to_merge.add_synapse_information(self.__synapse_information)
            self.__projection_edge = edge_to_merge
        else:

            # If there isn't an existing edge, create a new one and add it
            self.__projection_edge = ProjectionApplicationEdge(
                pre_vertex,
                post_vertex,
                self.__synapse_information,
                label=label)
            sim.add_application_edge(self.__projection_edge,
                                     SPIKE_PARTITION_ID)

        # add projection to the SpiNNaker control system
        sim.add_projection(self)

        # If there is a virtual board, we need to hold the data in case the
        # user asks for it
        self.__virtual_connection_list = None
        if sim.use_virtual_board:
            self.__virtual_connection_list = list()
            connection_holder = ConnectionHolder(
                None, False, pre_vertex.n_atoms, post_vertex.n_atoms,
                self.__virtual_connection_list)

            self.__synapse_information.add_pre_run_connection_holder(
                connection_holder)

        # If the target is a population, add to the list of incoming
        # projections
        if isinstance(post_vertex, AbstractPopulationVertex):
            post_vertex.add_incoming_projection(self)

        # If the source is a poisson, add to the list of outgoing projections
        if isinstance(pre_vertex, SpikeSourcePoissonVertex):
            pre_vertex.add_outgoing_projection(self)
Example #8
0
    def test_write_synaptic_matrix_and_master_population_table(self):
        MockSimulator.setup()
        # Add an sdram so max SDRAM is high enough
        SDRAM(10000)

        # UGLY but the mock transceiver NEED generate_on_machine to be False
        AbstractGenerateConnectorOnMachine.generate_on_machine = self.say_false
        default_config_paths = os.path.join(
            os.path.dirname(abstract_spinnaker_common.__file__),
            AbstractSpiNNakerCommon.CONFIG_FILE_NAME)

        config = conf_loader.load_config(
            AbstractSpiNNakerCommon.CONFIG_FILE_NAME, default_config_paths)
        config.set("Simulation", "one_to_one_connection_dtcm_max_bytes", 40)

        machine_time_step = 1000.0

        pre_app_vertex = SimpleApplicationVertex(10)
        pre_vertex_slice = Slice(0, 9)
        pre_vertex = pre_app_vertex.create_machine_vertex(
            pre_vertex_slice, None)
        post_app_vertex = SimpleApplicationVertex(10)
        post_vertex_slice = Slice(0, 9)
        post_vertex = post_app_vertex.create_machine_vertex(
            post_vertex_slice, None)
        post_slice_index = 0

        one_to_one_connector_1 = OneToOneConnector(None)
        direct_synapse_information_1 = SynapseInformation(
            one_to_one_connector_1, pre_app_vertex, post_app_vertex, False,
            False, None, SynapseDynamicsStatic(), 0, 1.5, 1.0)
        one_to_one_connector_1.set_projection_information(
            machine_time_step, direct_synapse_information_1)
        one_to_one_connector_2 = OneToOneConnector(None)
        direct_synapse_information_2 = SynapseInformation(
            one_to_one_connector_2, pre_app_vertex, post_app_vertex, False,
            False, None, SynapseDynamicsStatic(), 1, 2.5, 2.0)
        one_to_one_connector_2.set_projection_information(
            machine_time_step, direct_synapse_information_2)
        all_to_all_connector = AllToAllConnector(None)
        all_to_all_synapse_information = SynapseInformation(
            all_to_all_connector, pre_app_vertex, post_app_vertex, False,
            False, None, SynapseDynamicsStatic(), 0, 4.5, 4.0)
        all_to_all_connector.set_projection_information(
            machine_time_step, all_to_all_synapse_information)

        app_edge = ProjectionApplicationEdge(pre_app_vertex, post_app_vertex,
                                             direct_synapse_information_1)
        app_edge.add_synapse_information(direct_synapse_information_2)
        app_edge.add_synapse_information(all_to_all_synapse_information)
        machine_edge = app_edge.create_machine_edge(pre_vertex,
                                                    post_vertex,
                                                    label=None)
        partition_name = "TestPartition"

        graph = MachineGraph("Test")
        graph.add_vertex(pre_vertex)
        graph.add_vertex(post_vertex)
        graph.add_edge(machine_edge, partition_name)

        weight_scales = [4096.0, 4096.0]

        key = 0
        routing_info = RoutingInfo()
        routing_info.add_partition_info(
            PartitionRoutingInfo(
                [BaseKeyAndMask(key, 0xFFFFFFF0)],
                graph.get_outgoing_edge_partition_starting_at_vertex(
                    pre_vertex, partition_name)))

        temp_spec = tempfile.mktemp()
        spec_writer = FileDataWriter(temp_spec)
        spec = DataSpecificationGenerator(spec_writer, None)
        master_pop_sz = 1000
        all_syn_block_sz = 2000
        master_pop_region = 0
        synapse_region = 1
        direct_region = 2
        spec.reserve_memory_region(master_pop_region, master_pop_sz)
        spec.reserve_memory_region(synapse_region, all_syn_block_sz)

        synaptic_manager = SynapticManager(n_synapse_types=2,
                                           ring_buffer_sigma=5.0,
                                           spikes_per_second=100.0,
                                           config=config)
        # Poke in our testing region IDs
        synaptic_manager._pop_table_region = master_pop_region
        synaptic_manager._synaptic_matrix_region = synapse_region
        synaptic_manager._direct_matrix_region = direct_region

        synaptic_manager._write_synaptic_matrix_and_master_population_table(
            spec, [post_vertex_slice], post_slice_index, post_vertex,
            post_vertex_slice, all_syn_block_sz, weight_scales, routing_info,
            graph, machine_time_step)
        spec.end_specification()
        spec_writer.close()

        spec_reader = FileDataReader(temp_spec)
        executor = DataSpecificationExecutor(spec_reader,
                                             master_pop_sz + all_syn_block_sz)
        executor.execute()

        master_pop_table = executor.get_region(0)
        synaptic_matrix = executor.get_region(1)
        direct_matrix = executor.get_region(2)

        all_data = bytearray()
        all_data.extend(
            master_pop_table.region_data[:master_pop_table.max_write_pointer])
        all_data.extend(
            synaptic_matrix.region_data[:synaptic_matrix.max_write_pointer])
        all_data.extend(
            direct_matrix.region_data[:direct_matrix.max_write_pointer])
        master_pop_table_address = 0
        synaptic_matrix_address = master_pop_table.max_write_pointer
        direct_synapses_address = (synaptic_matrix_address +
                                   synaptic_matrix.max_write_pointer)
        direct_synapses_address += 4
        indirect_synapses_address = synaptic_matrix_address
        placement = Placement(None, 0, 0, 1)
        transceiver = MockTransceiverRawData(all_data)

        # Get the master population table details
        items = synaptic_manager._extract_synaptic_matrix_data_location(
            key, master_pop_table_address, transceiver, placement)

        # The first entry should be direct, but the rest should be indirect;
        # the second is potentially direct, but has been restricted by the
        # restriction on the size of the direct matrix
        assert len(items) == 3
        assert items[0][2]
        assert not items[1][2]
        assert not items[2][2]

        data_1, row_len_1 = synaptic_manager._retrieve_synaptic_block(
            txrx=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=0,
            using_monitors=False)
        connections_1 = synaptic_manager._read_synapses(
            direct_synapse_information_1, pre_vertex_slice, post_vertex_slice,
            row_len_1, 0, weight_scales, data_1, None, machine_time_step)

        # The first matrix is a 1-1 matrix, so row length is 1
        assert row_len_1 == 1

        # Check that all the connections have the right weight and delay
        assert len(connections_1) == post_vertex_slice.n_atoms
        assert all([conn["weight"] == 1.5 for conn in connections_1])
        assert all([conn["delay"] == 1.0 for conn in connections_1])

        data_2, row_len_2 = synaptic_manager._retrieve_synaptic_block(
            txrx=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=1,
            using_monitors=False)
        connections_2 = synaptic_manager._read_synapses(
            direct_synapse_information_2, pre_vertex_slice, post_vertex_slice,
            row_len_2, 0, weight_scales, data_2, None, machine_time_step)

        # The second matrix is a 1-1 matrix, so row length is 1
        assert row_len_2 == 1

        # Check that all the connections have the right weight and delay
        assert len(connections_2) == post_vertex_slice.n_atoms
        assert all([conn["weight"] == 2.5 for conn in connections_2])
        assert all([conn["delay"] == 2.0 for conn in connections_2])

        data_3, row_len_3 = synaptic_manager._retrieve_synaptic_block(
            txrx=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=2,
            using_monitors=False)
        connections_3 = synaptic_manager._read_synapses(
            all_to_all_synapse_information, pre_vertex_slice,
            post_vertex_slice, row_len_3, 0, weight_scales, data_3, None,
            machine_time_step)

        # The third matrix is an all-to-all matrix, so length is n_atoms
        assert row_len_3 == post_vertex_slice.n_atoms

        # Check that all the connections have the right weight and delay
        assert len(connections_3) == \
            post_vertex_slice.n_atoms * pre_vertex_slice.n_atoms
        assert all([conn["weight"] == 4.5 for conn in connections_3])
        assert all([conn["delay"] == 4.0 for conn in connections_3])