def _execute(txrx, machine, app_id, x, y, p, data_spec_path): # pylint: disable=too-many-arguments, too-many-locals # build specification reader reader = FileDataReader(data_spec_path) # maximum available memory # however system updates the memory available # independently, so the check on the space available actually # happens when memory is allocated # generate data spec executor executor = DataSpecificationExecutor( reader, machine.get_chip_at(x, y).sdram.size) # run data spec executor try: # bytes_used_by_spec, bytes_written_by_spec = \ executor.execute() except DataSpecificationException: logger.error("Error executing data specification for {}, {}, {}", x, y, p) raise bytes_used_by_spec = executor.get_constructed_data_size() # allocate memory where the app data is going to be written; this # raises an exception in case there is not enough SDRAM to allocate start_address = txrx.malloc_sdram(x, y, bytes_used_by_spec, app_id) # Write the header and pointer table and load it header = executor.get_header() pointer_table = executor.get_pointer_table(start_address) data_to_write = numpy.concatenate((header, pointer_table)).tostring() txrx.write_memory(x, y, start_address, data_to_write) bytes_written_by_spec = len(data_to_write) # Write each region for region_id in _MEM_REGIONS: region = executor.get_region(region_id) if region is not None: max_pointer = region.max_write_pointer if not region.unfilled and max_pointer > 0: # Get the data up to what has been written data = region.region_data[:max_pointer] # Write the data to the position txrx.write_memory(x, y, pointer_table[region_id], data) bytes_written_by_spec += len(data) # set user 0 register appropriately to the application data write_address_to_user0(txrx, x, y, p, start_address) return { 'start_address': start_address, 'memory_used': bytes_used_by_spec, 'memory_written': bytes_written_by_spec }
def __execute(self, core, reader, writer_func): x, y, p = core # Maximum available memory. # However, system updates the memory available independently, so the # space available check actually happens when memory is allocated. memory_available = self._machine.get_chip_at(x, y).sdram.size # generate data spec executor executor = DataSpecificationExecutor(reader, memory_available) # run data spec executor try: executor.execute() except DataSpecificationException: logger.error("Error executing data specification for {}, {}, {}", x, y, p) raise bytes_allocated = executor.get_constructed_data_size() # allocate memory where the app data is going to be written; this # raises an exception in case there is not enough SDRAM to allocate start_address = self._txrx.malloc_sdram(x, y, bytes_allocated, self._app_id) # Do the actual writing ------------------------------------ # Write the header and pointer table header = executor.get_header() pointer_table = executor.get_pointer_table(start_address) data_to_write = numpy.concatenate((header, pointer_table)).tostring() # NB: DSE meta-block is always small (i.e., one SDP write) self._txrx.write_memory(x, y, start_address, data_to_write) bytes_written = len(data_to_write) # Write each region for region_id in _MEM_REGIONS: region = executor.get_region(region_id) if region is None: continue max_pointer = region.max_write_pointer if region.unfilled or max_pointer == 0: continue # Get the data up to what has been written data = region.region_data[:max_pointer] # Write the data to the position writer_func(x, y, pointer_table[region_id], data) bytes_written += len(data) # set user 0 register appropriately to the application data write_address_to_user0(self._txrx, x, y, p, start_address) return DataWritten(start_address, bytes_allocated, bytes_written)
def __call__(self, transceiver, machine, app_id, dsg_targets): """ :param machine: the python representation of the spinnaker machine :param transceiver: the spinnman instance :param app_id: the application ID of the simulation :param dsg_targets: map of placement to file path :return: map of placement and dsg data, and loaded data flag. """ processor_to_app_data_base_address = dict() # create a progress bar for end users progress = ProgressBar( dsg_targets, "Executing data specifications and loading data") for ((x, y, p), data_spec_file_path) in progress.over(dsg_targets.iteritems()): # build specification reader data_spec_file_path = dsg_targets[x, y, p] data_spec_reader = FileDataReader(data_spec_file_path) # maximum available memory # however system updates the memory available # independently, so the check on the space available actually # happens when memory is allocated chip = machine.get_chip_at(x, y) memory_available = chip.sdram.size # generate data spec executor executor = DataSpecificationExecutor(data_spec_reader, memory_available) # run data spec executor try: # bytes_used_by_spec, bytes_written_by_spec = \ executor.execute() except DataSpecificationException as e: logger.error( "Error executing data specification for {}, {}, {}".format( x, y, p)) raise e bytes_used_by_spec = executor.get_constructed_data_size() # allocate memory where the app data is going to be written # this raises an exception in case there is not enough # SDRAM to allocate start_address = transceiver.malloc_sdram(x, y, bytes_used_by_spec, app_id) # Write the header and pointer table and load it header = executor.get_header() pointer_table = executor.get_pointer_table(start_address) data_to_write = numpy.concatenate( (header, pointer_table)).tostring() transceiver.write_memory(x, y, start_address, data_to_write) bytes_written_by_spec = len(data_to_write) # Write each region for region_id in range(constants.MAX_MEM_REGIONS): region = executor.get_region(region_id) if region is not None: max_pointer = region.max_write_pointer if not region.unfilled and max_pointer > 0: # Get the data up to what has been written data = region.region_data[:max_pointer] # Write the data to the position position = pointer_table[region_id] transceiver.write_memory(x, y, position, data) bytes_written_by_spec += len(data) # set user 0 register appropriately to the application data user_0_address = \ transceiver.get_user_0_register_address_from_core(x, y, p) start_address_encoded = \ buffer(struct.pack("<I", start_address)) transceiver.write_memory(x, y, user_0_address, start_address_encoded) # write information for the memory map report processor_to_app_data_base_address[x, y, p] = { 'start_address': start_address, 'memory_used': bytes_used_by_spec, 'memory_written': bytes_written_by_spec } return processor_to_app_data_base_address, True
def test_simple_spec(self): # Create a sdram just to set max chip size SDRAM(1000) # Write a data spec to execute temp_spec = mktemp() spec_writer = io.FileIO(temp_spec, "w") spec = DataSpecificationGenerator(spec_writer) spec.reserve_memory_region(0, 100) spec.reserve_memory_region(1, 200, empty=True) spec.reserve_memory_region(2, 4) spec.reserve_memory_region(3, 12, reference=1) spec.reference_memory_region(4, 2) spec.switch_write_focus(0) spec.write_array([0, 1, 2]) spec.set_write_pointer(20) spec.write_value(4) spec.switch_write_focus(2) spec.write_value(3) spec.set_write_pointer(0) spec.write_value(10) spec.end_specification() # Execute the spec spec_reader = io.FileIO(temp_spec, "r") executor = DataSpecificationExecutor(spec_reader, 400) executor.execute() # Test the size header_and_table_size = (constants.MAX_MEM_REGIONS + 2) * 4 self.assertEqual(executor.get_constructed_data_size(), header_and_table_size + 100 + 200 + 4 + 12) # Test the unused regions for region in range(5, constants.MAX_MEM_REGIONS): self.assertIsNone(executor.get_region(region)) # Test region 0 region_0 = executor.get_region(0) self.assertEqual(region_0.allocated_size, 100) self.assertEqual(region_0.max_write_pointer, 24) self.assertFalse(region_0.unfilled) self.assertIsNone(region_0.reference) self.assertEqual(region_0.region_data[:region_0.max_write_pointer], struct.pack("<IIIIII", 0, 1, 2, 0, 0, 4)) # Test region 1 region_1 = executor.get_region(1) self.assertIsInstance(region_1, MemoryRegionReal) self.assertEqual(region_1.allocated_size, 200) self.assertTrue(region_1.unfilled) self.assertIsNone(region_1.reference) # Test region 2 region_2 = executor.get_region(2) self.assertIsInstance(region_2, MemoryRegionReal) self.assertEqual(region_2.allocated_size, 4) self.assertIsNone(region_2.reference) self.assertEqual(region_2.region_data, struct.pack("<I", 10)) # Test region 3 region_3 = executor.get_region(3) self.assertIsInstance(region_3, MemoryRegionReal) self.assertEqual(region_3.allocated_size, 12) self.assertEqual(region_3.reference, 1) self.assertEqual(executor.referenceable_regions, [3]) # Test region 4 region_4 = executor.get_region(4) self.assertIsInstance(region_4, MemoryRegionReference) self.assertEqual(region_4.ref, 2) self.assertEqual(executor.references_to_fill, [4]) # Test the pointer table table = executor.get_pointer_table(0) self.assertEqual(len(table), constants.MAX_MEM_REGIONS) self.assertEqual(table[0], header_and_table_size) self.assertEqual(table[1], header_and_table_size + 100) self.assertEqual(table[2], header_and_table_size + 300) self.assertEqual(table[3], header_and_table_size + 304) # 4 is also 0 because it is a reference for region in range(4, constants.MAX_MEM_REGIONS): self.assertEqual(table[region], 0) # Test the header header = executor.get_header() self.assertEqual(len(header), 2) self.assertEqual(header[0], constants.APPDATA_MAGIC_NUM) self.assertEqual(header[1], constants.DSE_VERSION)