def _read_in_master_pop_table(self, p, controller, master_pop_table_region,
                                  MASTER_POPULATION_TABLE_SIZE):
        '''
        reads in the master pop table from a given processor on the machine
        '''
        # Get the App Data base address for the core
        # (location where this cores memory starts in
        # sdram and region table)
        app_data_base_address_offset = getAppDataBaseAddressOffset(p)
        app_data_base_address = \
            self._read_and_convert(app_data_base_address_offset,
                                   scamp.TYPE_WORD, 4, "<I", controller)

        # Get the memory address of the master pop table region
        master_pop_region = master_pop_table_region

        master_region_base_address_address = \
            getRegionBaseAddressOffset(app_data_base_address,
                                       master_pop_region)

        master_region_base_address_offset = \
            self._read_and_convert(master_region_base_address_address,
                                   scamp.TYPE_WORD, 4, "<I", controller)

        master_region_base_address =\
            master_region_base_address_offset + app_data_base_address

        #read in the master pop table and store in ram for future use
        logger.debug("Reading {} ({}) bytes starting at {} + "
                     "4".format(MASTER_POPULATION_TABLE_SIZE,
                                hex(MASTER_POPULATION_TABLE_SIZE),
                                hex(master_region_base_address)))

        return master_region_base_address, app_data_base_address
    def _read_in_master_pop_table(self, p, controller, master_pop_table_region,
                                  MASTER_POPULATION_TABLE_SIZE):
        '''
        reads in the master pop table from a given processor on the machine
        '''
        # Get the App Data base address for the core
        # (location where this cores memory starts in
        # sdram and region table)
        app_data_base_address_offset = getAppDataBaseAddressOffset(p)
        app_data_base_address = \
            self._read_and_convert(app_data_base_address_offset,
                                   scamp.TYPE_WORD, 4, "<I", controller)

        # Get the memory address of the master pop table region
        master_pop_region = master_pop_table_region

        master_region_base_address_address = \
            getRegionBaseAddressOffset(app_data_base_address,
                                       master_pop_region)

        master_region_base_address_offset = \
            self._read_and_convert(master_region_base_address_address,
                                   scamp.TYPE_WORD, 4, "<I", controller)

        master_region_base_address =\
            master_region_base_address_offset + app_data_base_address

        #read in the master pop table and store in ram for future use
        logger.debug("Reading {} ({}) bytes starting at {} + "
                     "4".format(MASTER_POPULATION_TABLE_SIZE,
                                hex(MASTER_POPULATION_TABLE_SIZE),
                                hex(master_region_base_address)))

        return master_region_base_address, app_data_base_address
def retrieve_region_data(txrx, x, y, p, region_id, region_size):
    """Get the data from the given processor and region.

    :param txrx: transceiver to use when communicating with the board
    :param region_id: id of the region to retrieve
    :param region_size: size of the region (in words)
    :returns: a string containing data from the region
    """
    # Get the application pointer table to get the address for the region
    txrx.select(x, y)
    app_data_base_offset = memory_utils.getAppDataBaseAddressOffset(p)
    _app_data_table = txrx.memory_calls.read_mem(app_data_base_offset,
                                                 scamp.TYPE_WORD, 4)
    app_data_table = struct.unpack('<I', _app_data_table)[0]

    # Get the position of the desired region
    region_base_offset = memory_utils.getRegionBaseAddressOffset(
        app_data_table, region_id)
    _region_base = txrx.memory_calls.read_mem(region_base_offset,
                                              scamp.TYPE_WORD, 4)
    region_address = struct.unpack('<I', _region_base)[0] + app_data_table

    # Read the region
    data = txrx.memory_calls.read_mem(region_address, scamp.TYPE_WORD,
                                      region_size * 4)
    return data
    def _retrieve_synaptic_block(self, controller, pre_subvertex, pre_n_atoms,
                                 post_subvertex, master_pop_table_region,
                                 MASTER_POPULATION_TABLE_SIZE,
                                 synaptic_matrix_region):
        '''
        reads in a synaptic block from a given processor and subvertex on the
        machine.
        '''
        post_x, post_y, post_p = \
            post_subvertex.placement.processor.get_coordinates()
        controller.txrx.select(post_x, post_y)
        # either read in the master pop table or retrieve it from storage
        app_data_base_address = None
        if not post_subvertex in controller.dao.master_population_tables.keys():
            master_pop_base_mem_address,\
            app_data_base_address = \
                self._read_in_master_pop_table(post_p, controller,
                                               master_pop_table_region,
                                               MASTER_POPULATION_TABLE_SIZE)

            controller.dao.master_population_tables[post_subvertex] = list()
            controller.dao.master_population_tables[post_subvertex].append(master_pop_base_mem_address)
            controller.dao.master_population_tables[post_subvertex].append(app_data_base_address)
        else:
            master_pop_base_mem_address = \
                controller.dao.master_population_tables[post_subvertex][0]
            app_data_base_address = \
                controller.dao.master_population_tables[post_subvertex][1]


        # locate address of the synaptic block
        pre_x, pre_y, pre_p = pre_subvertex.placement.processor.get_coordinates()
        tableSlotAddr = packet_conversions.\
            get_mpt_sb_mem_addrs_from_coords(pre_x, pre_y,pre_p)
        master_table_pop_entry_address = (tableSlotAddr +
                                          master_pop_base_mem_address)
        #read in the master pop entry
        master_pop_entry = \
            self._read_and_convert(master_table_pop_entry_address,
                                   scamp.TYPE_HALF, 2, "<H", controller)


        synaptic_block_base_address = master_pop_entry >> 3 #in kilobytes
        #convert synaptic_block_base_address into bytes from kilobytes
        synaptic_block_base_address_offset = synaptic_block_base_address << 10
        max_row_length_index = master_pop_entry & 0x7
        #retrieve the max row length
        maxed_row_length =\
            SynapticManager.ROW_LEN_TABLE_ENTRIES[max_row_length_index]

        #calculate the synaptic block size in words
        synaptic_block_size = pre_n_atoms * 4 * \
            (SynapticManager.SYNAPTIC_ROW_HEADER_WORDS + maxed_row_length)

        #read in the base address of the synaptic matrix in the app region table
        synapste_region_base_address_location = \
            getRegionBaseAddressOffset(app_data_base_address,
                                       synaptic_matrix_region)

        # read in the memory address of the synaptic_region base address
        synapste_region_base_address = \
            self._read_and_convert(synapste_region_base_address_location,
                                   scamp.TYPE_WORD, 4, "<I", controller)
        # the base address of the synaptic block in absolute terms is the app
        # base, plus the synaptic matrix base plus the offset
        synaptic_block_base_address = \
            app_data_base_address + synapste_region_base_address + \
            synaptic_block_base_address_offset

        #read in and return the synaptic block
        block = controller.txrx.memory_calls.\
            read_mem(synaptic_block_base_address, scamp.TYPE_WORD,
                     synaptic_block_size), maxed_row_length
        if len(block[0]) != synaptic_block_size:
            raise exceptions.SpinnManException("Not enough data has been read (aka, something funkky)")
        return block
    def _getSpikes(self, controller, compatible_output,
                   spikeRecordingRegion, subVertexOutSpikeBytesFunction,
                   runtime):
        """
        Return a 2-column numpy array containing cell ids and spike times for 
        recorded cells.   This is read directly from the memory for the board.
        """
        
        logger.info("Getting spikes for %s" % (self.label))
        
        spikes = numpy.zeros((0, 2))
        
        # Find all the sub-vertices that this population exists on
        for subvertex in self.subvertices:
            (x, y, p) = subvertex.placement.processor.get_coordinates()
            logger.debug("Reading spikes from chip %d, %d, core %d, lo_atom %d"
                     % (x, y, p, subvertex.lo_atom))
            controller.txrx.select(x, y)
            
            # Get the App Data for the core
            appDataBaseAddressOffset = getAppDataBaseAddressOffset(p)
            appDataBaseAddressBuf = controller.txrx.memory_calls.read_mem(
                    appDataBaseAddressOffset, scamp.TYPE_WORD, 4)
            appDataBaseAddress = struct.unpack("<I", appDataBaseAddressBuf)[0]
            
            # Get the position of the spike buffer
            spikeRegionBaseAddressOffset = getRegionBaseAddressOffset(
                    appDataBaseAddress, spikeRecordingRegion)
            spikeRegionBaseAddressBuf = controller.txrx.memory_calls.read_mem(
                    spikeRegionBaseAddressOffset, scamp.TYPE_WORD, 4)
            spikeRegionBaseAddress = struct.unpack("<I", 
                    spikeRegionBaseAddressBuf)[0]
            spikeRegionBaseAddress += appDataBaseAddress
            
            # Read the spike data size
            numberOfBytesWrittenBuf = controller.txrx.memory_calls.read_mem(
                    spikeRegionBaseAddress, scamp.TYPE_WORD, 4)
            numberOfBytesWritten = struct.unpack_from("<I", 
                    numberOfBytesWrittenBuf)[0]

            #check that the number of spikes written is smaller or the same as the size of the memory
            #region we allocated for spikes
            outSpikeBytes = subVertexOutSpikeBytesFunction(subvertex)
            machine_time_step = conf.config.getint("Machine", "machineTimeStep")
            no_machine_time_steps = int((runtime * 1000.0) / machine_time_step)
            size_of_region = self.get_recording_region_size(outSpikeBytes, no_machine_time_steps)

            if numberOfBytesWritten > size_of_region:
                raise exceptions.MemReadException("the amount of memory written was "
                                                  "larger than was allocated for it")

            
            # Read the spikes
            logger.debug("Reading %d (%s) bytes starting at %s + 4" %
                    (numberOfBytesWritten, hex(numberOfBytesWritten), 
                            hex(spikeRegionBaseAddress)))
            spikeData = controller.txrx.memory_calls.read_mem(
                    spikeRegionBaseAddress + 4, scamp.TYPE_WORD, 
                    numberOfBytesWritten)
            
            # Extract number of spike bytes from subvertex
            outSpikeBytes = subVertexOutSpikeBytesFunction(subvertex)
            numberOfTimeStepsWritten = numberOfBytesWritten / (outSpikeBytes)
            
            logger.debug("Processing %d timesteps" % numberOfTimeStepsWritten)
            
            # Loop through ticks
            for tick in range(0, numberOfTimeStepsWritten):
                
                # Convert tick to ms
                time = tick * (controller.dao.machineTimeStep / 1000.0)
                
                # Get offset into file data that the bit vector representing 
                # the state at this tick begins at
                vectorOffset = (tick * outSpikeBytes)
                
                # Loop through the words that make up this vector
                for neuronWordIndex in range(0, outSpikeBytes, 4):
                    
                    # Unpack the word containing the spikingness of 32 neurons
                    spikeVectorWord = struct.unpack_from("<I", spikeData,
                                             vectorOffset + neuronWordIndex)
                    
                    if spikeVectorWord != 0:
                        # Loop through each bit in this word
                        for neuronBitIndex in range(0, 32):
                            
                            # If the bit is set
                            neuronBitMask = (1 << neuronBitIndex)
                            if (spikeVectorWord[0] & neuronBitMask) != 0:
                                
                                # Calculate neuron ID
                                neuronID = ((neuronWordIndex * 8) + neuronBitIndex
                                        + subvertex.lo_atom)
                                
                                # Add spike time and neuron ID to returned lists
                                spikes = numpy.append(spikes, [[time, neuronID]], 0)
            
        if len(spikes) > 0:
            
            logger.debug("Arranging spikes as per output spec")
            
            if compatible_output == True:
                
                # Change the order to be neuronID : time (don't know why - this
                # is how it was done in the old code, so I am doing it here too)
                spikes[:,[0,1]] = spikes[:,[1,0]]
                
                # Sort by neuron ID and not by time 
                spikeIndex = numpy.lexsort((spikes[:,1],spikes[:,0]))
                spikes = spikes[spikeIndex]
                return spikes;
            
            # If compatible output, return sorted by spike time
            spikeIndex = numpy.lexsort((spikes[:,1], spikes[:,0]))
            spikes = spikes[spikeIndex]
            return spikes
        print("No spikes recorded")
        return spikes
    def _retrieve_synaptic_block(self, controller, pre_subvertex, pre_n_atoms,
                                 post_subvertex, master_pop_table_region,
                                 MASTER_POPULATION_TABLE_SIZE,
                                 synaptic_matrix_region):
        '''
        reads in a synaptic block from a given processor and subvertex on the
        machine.
        '''
        post_x, post_y, post_p = \
            post_subvertex.placement.processor.get_coordinates()
        controller.txrx.select(post_x, post_y)
        # either read in the master pop table or retrieve it from storage
        app_data_base_address = None
        if not post_subvertex in controller.dao.master_population_tables.keys(
        ):
            master_pop_base_mem_address,\
            app_data_base_address = \
                self._read_in_master_pop_table(post_p, controller,
                                               master_pop_table_region,
                                               MASTER_POPULATION_TABLE_SIZE)

            controller.dao.master_population_tables[post_subvertex] = list()
            controller.dao.master_population_tables[post_subvertex].append(
                master_pop_base_mem_address)
            controller.dao.master_population_tables[post_subvertex].append(
                app_data_base_address)
        else:
            master_pop_base_mem_address = \
                controller.dao.master_population_tables[post_subvertex][0]
            app_data_base_address = \
                controller.dao.master_population_tables[post_subvertex][1]

        # locate address of the synaptic block
        pre_x, pre_y, pre_p = pre_subvertex.placement.processor.get_coordinates(
        )
        tableSlotAddr = packet_conversions.\
            get_mpt_sb_mem_addrs_from_coords(pre_x, pre_y,pre_p)
        master_table_pop_entry_address = (tableSlotAddr +
                                          master_pop_base_mem_address)
        #read in the master pop entry
        master_pop_entry = \
            self._read_and_convert(master_table_pop_entry_address,
                                   scamp.TYPE_HALF, 2, "<H", controller)

        synaptic_block_base_address = master_pop_entry >> 3  #in kilobytes
        #convert synaptic_block_base_address into bytes from kilobytes
        synaptic_block_base_address_offset = synaptic_block_base_address << 10
        max_row_length_index = master_pop_entry & 0x7
        #retrieve the max row length
        maxed_row_length =\
            SynapticManager.ROW_LEN_TABLE_ENTRIES[max_row_length_index]

        #calculate the synaptic block size in words
        synaptic_block_size = pre_n_atoms * 4 * \
            (SynapticManager.SYNAPTIC_ROW_HEADER_WORDS + maxed_row_length)

        #read in the base address of the synaptic matrix in the app region table
        synapste_region_base_address_location = \
            getRegionBaseAddressOffset(app_data_base_address,
                                       synaptic_matrix_region)

        # read in the memory address of the synaptic_region base address
        synapste_region_base_address = \
            self._read_and_convert(synapste_region_base_address_location,
                                   scamp.TYPE_WORD, 4, "<I", controller)
        # the base address of the synaptic block in absolute terms is the app
        # base, plus the synaptic matrix base plus the offset
        synaptic_block_base_address = \
            app_data_base_address + synapste_region_base_address + \
            synaptic_block_base_address_offset

        #read in and return the synaptic block
        block = controller.txrx.memory_calls.\
            read_mem(synaptic_block_base_address, scamp.TYPE_WORD,
                     synaptic_block_size), maxed_row_length
        if len(block[0]) != synaptic_block_size:
            raise exceptions.SpinnManException(
                "Not enough data has been read (aka, something funkky)")
        return block
    def _getSpikes(self, controller, compatible_output, spikeRecordingRegion,
                   subVertexOutSpikeBytesFunction, runtime):
        """
        Return a 2-column numpy array containing cell ids and spike times for 
        recorded cells.   This is read directly from the memory for the board.
        """

        logger.info("Getting spikes for %s" % (self.label))

        spikes = numpy.zeros((0, 2))

        # Find all the sub-vertices that this population exists on
        for subvertex in self.subvertices:
            (x, y, p) = subvertex.placement.processor.get_coordinates()
            logger.debug(
                "Reading spikes from chip %d, %d, core %d, lo_atom %d" %
                (x, y, p, subvertex.lo_atom))
            controller.txrx.select(x, y)

            # Get the App Data for the core
            appDataBaseAddressOffset = getAppDataBaseAddressOffset(p)
            appDataBaseAddressBuf = controller.txrx.memory_calls.read_mem(
                appDataBaseAddressOffset, scamp.TYPE_WORD, 4)
            appDataBaseAddress = struct.unpack("<I", appDataBaseAddressBuf)[0]

            # Get the position of the spike buffer
            spikeRegionBaseAddressOffset = getRegionBaseAddressOffset(
                appDataBaseAddress, spikeRecordingRegion)
            spikeRegionBaseAddressBuf = controller.txrx.memory_calls.read_mem(
                spikeRegionBaseAddressOffset, scamp.TYPE_WORD, 4)
            spikeRegionBaseAddress = struct.unpack(
                "<I", spikeRegionBaseAddressBuf)[0]
            spikeRegionBaseAddress += appDataBaseAddress

            # Read the spike data size
            numberOfBytesWrittenBuf = controller.txrx.memory_calls.read_mem(
                spikeRegionBaseAddress, scamp.TYPE_WORD, 4)
            numberOfBytesWritten = struct.unpack_from(
                "<I", numberOfBytesWrittenBuf)[0]

            #check that the number of spikes written is smaller or the same as the size of the memory
            #region we allocated for spikes
            outSpikeBytes = subVertexOutSpikeBytesFunction(subvertex)
            machine_time_step = conf.config.getint("Machine",
                                                   "machineTimeStep")
            no_machine_time_steps = int((runtime * 1000.0) / machine_time_step)
            size_of_region = self.get_recording_region_size(
                outSpikeBytes, no_machine_time_steps)

            if numberOfBytesWritten > size_of_region:
                raise exceptions.MemReadException(
                    "the amount of memory written was "
                    "larger than was allocated for it")

            # Read the spikes
            logger.debug("Reading %d (%s) bytes starting at %s + 4" %
                         (numberOfBytesWritten, hex(numberOfBytesWritten),
                          hex(spikeRegionBaseAddress)))
            spikeData = controller.txrx.memory_calls.read_mem(
                spikeRegionBaseAddress + 4, scamp.TYPE_WORD,
                numberOfBytesWritten)

            # Extract number of spike bytes from subvertex
            outSpikeBytes = subVertexOutSpikeBytesFunction(subvertex)
            numberOfTimeStepsWritten = numberOfBytesWritten / (outSpikeBytes)

            logger.debug("Processing %d timesteps" % numberOfTimeStepsWritten)

            # Loop through ticks
            for tick in range(0, numberOfTimeStepsWritten):

                # Convert tick to ms
                time = tick * (controller.dao.machineTimeStep / 1000.0)

                # Get offset into file data that the bit vector representing
                # the state at this tick begins at
                vectorOffset = (tick * outSpikeBytes)

                # Loop through the words that make up this vector
                for neuronWordIndex in range(0, outSpikeBytes, 4):

                    # Unpack the word containing the spikingness of 32 neurons
                    spikeVectorWord = struct.unpack_from(
                        "<I", spikeData, vectorOffset + neuronWordIndex)

                    if spikeVectorWord != 0:
                        # Loop through each bit in this word
                        for neuronBitIndex in range(0, 32):

                            # If the bit is set
                            neuronBitMask = (1 << neuronBitIndex)
                            if (spikeVectorWord[0] & neuronBitMask) != 0:

                                # Calculate neuron ID
                                neuronID = ((neuronWordIndex * 8) +
                                            neuronBitIndex + subvertex.lo_atom)

                                # Add spike time and neuron ID to returned lists
                                spikes = numpy.append(spikes,
                                                      [[time, neuronID]], 0)

        if len(spikes) > 0:

            logger.debug("Arranging spikes as per output spec")

            if compatible_output == True:

                # Change the order to be neuronID : time (don't know why - this
                # is how it was done in the old code, so I am doing it here too)
                spikes[:, [0, 1]] = spikes[:, [1, 0]]

                # Sort by neuron ID and not by time
                spikeIndex = numpy.lexsort((spikes[:, 1], spikes[:, 0]))
                spikes = spikes[spikeIndex]
                return spikes

            # If compatible output, return sorted by spike time
            spikeIndex = numpy.lexsort((spikes[:, 1], spikes[:, 0]))
            spikes = spikes[spikeIndex]
            return spikes
        print("No spikes recorded")
        return spikes
 def get_neuron_parameter(self, region, compatible_output, controller):
     if not controller.dao.has_ran:
         raise exceptions.PacmanException("The simulation has not yet ran,"
                                          "therefore gsyn cannot be "
                                          "retrieved")
     value = numpy.zeros((0, 3))
     
     # Find all the sub-vertices that this population exists on
     for subvertex in self.subvertices:
         (x, y, p) = subvertex.placement.processor.get_coordinates()
         controller.txrx.select(x, y)
         
         # Get the App Data for the core
         appDataBaseAddressOffset = getAppDataBaseAddressOffset(p)
         appDataBaseAddressBuf = controller.txrx.memory_calls.read_mem(
                 appDataBaseAddressOffset, scamp.TYPE_WORD, 4)
         appDataBaseAddress = struct.unpack("<I", appDataBaseAddressBuf)[0]
         
         # Get the position of the value buffer
         vRegionBaseAddressOffset = getRegionBaseAddressOffset(
                 appDataBaseAddress, region)
         vRegionBaseAddressBuf = controller.txrx.memory_calls.read_mem(
                 vRegionBaseAddressOffset, scamp.TYPE_WORD, 4)
         vRegionBaseAddress = struct.unpack("<I", 
                 vRegionBaseAddressBuf)[0]
         vRegionBaseAddress += appDataBaseAddress
         
         # Read the size
         numberOfBytesWrittenBuf = controller.txrx.memory_calls.read_mem(
                 vRegionBaseAddress, scamp.TYPE_WORD, 4)
         numberOfBytesWritten = struct.unpack_from("<I", 
                 numberOfBytesWrittenBuf)[0]
                 
         # Read the values
         logger.debug("Reading %d (%s) bytes starting at %s" 
                 %(numberOfBytesWritten, hex(numberOfBytesWritten), 
                         hex(vRegionBaseAddress + 4)))
         vData = controller.txrx.memory_calls.read_mem(
                 vRegionBaseAddress + 4, scamp.TYPE_WORD, 
                 numberOfBytesWritten)
         bytesPerTimeStep = subvertex.n_atoms * 4
         numberOfTimeStepsWritten = numberOfBytesWritten / bytesPerTimeStep
         msPerTimestep = controller.dao.machineTimeStep / 1000.0
         
         logger.debug("Processing %d timesteps" % numberOfTimeStepsWritten)
         
         # Standard fixed-point 'accum' type scaling
         size = len(vData) / 4
         scale = numpy.zeros(size, dtype=numpy.float)
         scale.fill(float(0x7FFF))
         
         # Add an array for time and neuron id
         time = numpy.array([int(i / subvertex.n_atoms) * msPerTimestep 
                 for i in range(size)], dtype=numpy.float)
         neuronId = numpy.array([int(i % subvertex.n_atoms) 
                 + subvertex.lo_atom for i in range(size)], 
                 dtype=numpy.uint32)
         
         # Get the values
         tempValue = numpy.frombuffer(vData, dtype="<i4")
         tempValue = numpy.divide(tempValue, scale)
         tempArray = numpy.dstack((time, neuronId, tempValue))
         tempArray = numpy.reshape(tempArray, newshape=(-1, 3))
         
         value = numpy.append(value, tempArray, axis=0)
     
     logger.debug("Arranging parameter output")
     
     if compatible_output == True:
         
         # Change the order to be neuronID : time (don't know why - this
         # is how it was done in the old code, so I am doing it here too)
         value[:,[0,1,2]] = value[:,[1,0,2]]
         
         # Sort by neuron ID and not by time 
         vIndex = numpy.lexsort((value[:,2], value[:,1], value[:,0]))
         value = value[vIndex]
         return value
     
     # If not compatible output, we will sort by time (as NEST seems to do)
     vIndex = numpy.lexsort((value[:,2], value[:,1], value[:,0]))
     value = value[vIndex]
     return value