Source code for data_specification.data_specification_generator

import logging
import struct
import decimal

from data_specification import constants, exceptions
from data_specification.enums import \
    DataType, RandomNumberGenerator, Commands, Condition, LogicOperation, \
    ArithmeticOperation
from spinn_machine import sdram
import numpy

logger = logging.getLogger(__name__)


[docs]class DataSpecificationGenerator(object): """ Used to generate a data specification language file that can be\ executed to produce a memory image """ __slots__ = [ # The object to write the specification to "spec_writer", # the writer for the human readable report "report_writer", # ???????? "txt_indent", # how many instructions has been executed ????? "instruction_counter", # ??????? "mem_slot", # ??????? "function", # ??????? "struct_slot", # ???????? "rng", # ???????? "random_distribution", # ??????? "conditionals", # the current dsg region we're writing to "current_region", # ????????? "ongoing_function_definition", # ???????? "ongoing_loop" ] MAGIC_NUMBER = 0xAD130AD6 VERSION = 1 def __init__(self, spec_writer, report_writer=None): """ :param spec_writer: The object to write the specification to :type spec_writer: Implementation of\ :py:class:`data_specification.abstract_data_writer.AbstractDataWriter` :param report_writer: Determines if a text version of the\ specification is to be written :type report_writer: Implementation of\ :py:class:`data_specification.abstract_data_writer.AbstractDataWriter` :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails """ self.spec_writer = spec_writer self.report_writer = report_writer self.txt_indent = 0 self.instruction_counter = 0 self.mem_slot = [0] * constants.MAX_MEM_REGIONS self.function = [0] * constants.MAX_CONSTRUCTORS self.struct_slot = [0] * constants.MAX_STRUCT_SLOTS self.rng = [0] * constants.MAX_RNGS self.random_distribution = [0] * constants.MAX_RANDOM_DISTS self.conditionals = [] self.current_region = None self.ongoing_function_definition = False self.ongoing_loop = False
[docs] def comment(self, comment): """ Write a comment to the text version of the specification.\ Note that this is ignored by the binary file :param comment: The comment to write :type comment: str :return: Nothing is returned :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails """ self.write_command_to_files( bytearray(), comment, no_instruction_number=True)
[docs] def define_break(self): """ Insert command to stop execution with an exception (for debugging) :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails """ cmd_word = ( (constants.LEN1 << 28) | (Commands.BREAK.value << 20)) # @UndefinedVariable encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = encoded_cmd_word cmd_string = "BREAK" self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def no_operation(self): """ Insert command to execute nothing :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails """ cmd_word = ( (constants.LEN1 << 28) | (Commands.NOP.value << 20)) # @UndefinedVariable encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = encoded_cmd_word cmd_string = "NOP" self.write_command_to_files(cmd_word_list, cmd_string) return
[docs] def reserve_memory_region( self, region, size, label=None, empty=False, shrink=True): """ Insert command to reserve a memory region :param region: The number of the region to reserve, from 0 to 15 :type region: int :param size: The size to reserve for the region in bytes :type size: int :param label: An optional label for the region :type label: str :param empty: Specifies if the region will be left empty :type empty: bool :param shrink: Specifies if the region will be compressed :type shrink: bool :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationRegionInUseException: If the region was already \ reserved :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException: If the region requested was out of the allowed range, or that the size was too \ big to fit in SDRAM """ if (region < 0) or (region >= constants.MAX_MEM_REGIONS): logger.error( "Error: Memory region requested ({0:d}) is out of range 0 " "to {1:d}.\n".format(region, constants.MAX_MEM_REGIONS - 1)) raise exceptions.DataSpecificationParameterOutOfBoundsException( "memory region identifier", region, 0, (constants.MAX_MEM_REGIONS - 1), Commands.RESERVE.name) # @UndefinedVariable if self.mem_slot[region] != 0: error_string = "Error: Requested memory region ({0:d}) ".format( region) error_string += "is already allocated.\n" logger.error(error_string) raise exceptions.DataSpecificationRegionInUseException(region) if size > sdram.SDRAM.DEFAULT_SDRAM_BYTES: raise exceptions.DataSpecificationParameterOutOfBoundsException( "memory size", size, 1, sdram.SDRAM.DEFAULT_SDRAM_BYTES, Commands.RESERVE.name) # @UndefinedVariable self.mem_slot[region] = [size, label, empty] cmd_word = ((constants.LEN2 << 28) | (Commands.RESERVE.value << 20) | # @UndefinedVariable (constants.NO_REGS << 16) | (int(bool(empty)) << 7) | (int(bool(shrink)) << 6) | region) encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) encoded_size = bytearray(struct.pack("<I", size)) cmd_word_list = encoded_cmd_word + encoded_size if empty: unfilled_string = "UNFILLED" else: unfilled_string = "" if label is None: cmd_string = "RESERVE memRegion={0:d} size={1:d} {2:s}".format( region, size, unfilled_string) else: cmd_string = ( "RESERVE memRegion={0:d} size={1:d} label='{2:s}' {3:s}" .format(region, size, label, unfilled_string)) self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def free_memory_region(self, region): """ Insert command to free a previously reserved memory region :param region: The number of the region to free, from 0 to 15 :type region: int :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationNotAllocatedException: If the region was not\ reserved :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException: If the region \ requested was out of the allowed range """ if (region < 0) or (region >= constants.MAX_MEM_REGIONS): raise exceptions.DataSpecificationParameterOutOfBoundsException( "memory region identifier", region, 0, (constants.MAX_MEM_REGIONS - 1), Commands.RESERVE.name) # @UndefinedVariable if self.mem_slot[region] == 0: raise exceptions.DataSpecificationNotAllocatedException( "region", region, Commands.FREE.name) # @UndefinedVariable self.mem_slot[region] = 0 cmd_word = ( (constants.LEN1 << 28) | (Commands.FREE.value << 20) | # @UndefinedVariable (constants.NO_REGS << 16) | region) cmd_string = "FREE memRegion={0:d}".format(region) encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) self.write_command_to_files(encoded_cmd_word, cmd_string)
[docs] def declare_random_number_generator(self, rng_id, rng_type, seed): """ Insert command to declare a random number generator :param rng_id: The id of the random number generator :type rng_id: int :param rng_type: The type of the random number generator :type rng_type: :py:class:`RandomNumberGenerator` :param seed: The seed of the random number generator >= 0 :type seed: int :return: The id of the created random number generator,\ between 0 and 15 :rtype: int :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.DataSpecification:\ If there is no more space for a new generator :raise data_specification.exceptions.\ DataSpecificationUnknownTypeException: If the rng_type is not one \ of the allowed values :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException: * If the seed is too big or too small * If the rng_id is not in the allowed range :raise data_specification.exceptions\ .DataSpecificationRNGInUseException: If the random number generator with the given id has already been\ defined """ if rng_id < 0 or rng_id >= constants.MAX_RNGS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "random number generator id", rng_id, 0, (constants.MAX_RNGS - 1), Commands.DECLARE_RNG.name) # @UndefinedVariable if rng_type not in RandomNumberGenerator: raise exceptions.DataSpecificationUnknownTypeException( rng_type.value, Commands.DECLARE_RNG.name) # @UndefinedVariable if self.rng[rng_id] is not 0: raise exceptions.DataSpecificationRNGInUseException(rng_id) if (seed > DataType.UINT32.max or # @UndefinedVariable seed < DataType.UINT32.min): # @UndefinedVariable raise exceptions.DataSpecificationParameterOutOfBoundsException( "seed", seed, DataType.UINT32.min, # @UndefinedVariable DataType.UINT32.max, # @UndefinedVariable Commands.DECLARE_RNG.name) # @UndefinedVariable self.rng[rng_id] = [rng_type, seed] cmd_word = ( (constants.LEN2 << 28) | (Commands.DECLARE_RNG.value << 20) | # @UndefinedVariable (rng_id << 12) | (rng_type.value << 8)) encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) encoded_seed = bytearray(struct.pack("<i", seed)) cmd_word_list = encoded_cmd_word + encoded_seed cmd_string = "DECLARE_RNG id={0:d}, source={1:d}, seed={2:d}".format( rng_id, rng_type.value, seed) self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def declare_uniform_random_distribution( self, distribution_id, structure_id, rng_id, min_value, max_value): """ Insert commands to declare a uniform random distribution :param distribution_id: id of the distribution being set up :param distribution_id: int :param structure_id: id of an empty structure slot to fill with the uniform random distribution data :type structure_id: int :param rng_id: The id of the random number generator, between 0 and 15 :type rng_id: int :param min_value: The minimum value that should be returned from the\ distribution between -32768.0 and max_value :type min_value: float :param max_value: The maximum value that should be returned from the\ distribution between min_value and 32767.9999847 :type max_value: float :return: The id of the created uniform random distribution to be used\ in future calls of the distribution between 0 and 63 :rtype: int :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.DataSpecificationNoMoreException:\ If there is no more space for a new random distribution :raise data_specification.exceptions.\ DataSpecificationNotAllocatedException: If the requested rng_id \ has not been allocated :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException: If rng_id, \ structure_id, min_value or max_value is out of range :raise data_specification.exceptions.\ DataSpecificationStructureInUseException: If structure \ structure_id is already defined """ if (distribution_id < 0 or distribution_id >= constants.MAX_RANDOM_DISTS): raise exceptions.DataSpecificationParameterOutOfBoundsException( "distribution id", distribution_id, 0, constants.MAX_RANDOM_DISTS - 1, Commands.DECLARE_RANDOM_DIST.name) # @UndefinedVariable if rng_id < 0 or rng_id >= constants.MAX_RNGS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "rng", rng_id, 0, constants.MAX_RNGS - 1, Commands.DECLARE_RANDOM_DIST.name) # @UndefinedVariable if self.rng[rng_id] is 0: raise exceptions.DataSpecificationNotAllocatedException( "RNG", rng_id, Commands.DECLARE_RANDOM_DIST.name) # @UndefinedVariable if min_value < DataType.S1615.min: # @UndefinedVariable raise exceptions.DataSpecificationParameterOutOfBoundsException( "min_value", min_value, DataType.S1615.min, # @UndefinedVariable DataType.S1615.max, # @UndefinedVariable Commands.DECLARE_RANDOM_DIST.name) # @UndefinedVariable if max_value > DataType.S1615.max: # @UndefinedVariable raise exceptions.DataSpecificationParameterOutOfBoundsException( "max_value", max_value, DataType.S1615.min, # @UndefinedVariable DataType.S1615.max, # @UndefinedVariable Commands.DECLARE_RANDOM_DIST.name) # @UndefinedVariable if structure_id < 0 or structure_id >= constants.MAX_STRUCT_SLOTS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "structure id", structure_id, 0, constants.MAX_STRUCT_SLOTS - 1, Commands.DECLARE_RANDOM_DIST.name) # @UndefinedVariable if self.random_distribution[distribution_id] is not 0: raise exceptions.\ DataSpecificationRandomNumberDistributionInUseException( distribution_id) parameters = [("distType", DataType.UINT32, 0), ("rngID", DataType.UINT32, rng_id), ("param1", DataType.S1615, min_value), ("param2", DataType.S1615, max_value)] self.random_distribution[distribution_id] = parameters self.define_structure(structure_id, parameters) cmd_word = ( (constants.LEN1 << 28) | (Commands.DECLARE_RANDOM_DIST.value << 20) | # @UndefinedVariable (distribution_id << 8) | structure_id) cmd_string = "DECLARE_RANDOM_DIST distribution_id={0:d} " \ "structure_id={1:d}".format(distribution_id, structure_id) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def call_random_distribution(self, distribution_id, register_id): """ Insert command to get the next random number from a random\ distribution, placing the result in a register to be used in a\ future call :param distribution_id: The id of the random distribution to call\ between 0 and 63 :type distribution_id: int :param register_id: The id of the register to store the result in\ between 0 and 15 :type register_id: int :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationNotAllocatedException: If the random distribution\ id was not previously declared :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException: If the \ distribution_id or register_id specified was out of range """ if register_id < 0 or register_id >= constants.MAX_REGISTERS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "register_id", register_id, 0, constants.MAX_REGISTERS - 1, Commands.GET_RANDOM_NUMBER.name) # @UndefinedVariable if (distribution_id < 0 or distribution_id >= constants.MAX_RANDOM_DISTS): raise exceptions.DataSpecificationParameterOutOfBoundsException( "distribution_id", distribution_id, 0, constants.MAX_RANDOM_DISTS - 1, Commands.GET_RANDOM_NUMBER.name) # @UndefinedVariable if self.random_distribution[distribution_id] is 0: raise exceptions.DataSpecificationNotAllocatedException( "random number distribution", distribution_id, Commands.GET_RANDOM_NUMBER.name) # @UndefinedVariable bit_field = 0x4 cmd_string = "GET_RANDOM_NUMBER distribution={0:d} " \ "dest=reg[{1:d}]".format(distribution_id, register_id) cmd_word = ( (constants.LEN1 << 28) | (Commands.GET_RANDOM_NUMBER.value << 20) | # @UndefinedVariable (bit_field << 16) | (register_id << 12) | distribution_id) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def define_structure(self, structure_id, parameters): """ Insert commands to define a data structure :param structure_id: the id of the structure to create,\ between 0 and 15 :type structure_id: int :param parameters: A list of between 1 and 255 tuples of (label,\ data_type, value) where: * label is the label of the element (for debugging) * data_type is the data type of the element * value is the value of the element, or None if no value is to\ be assigned :type parameters: list of (str, :py:class:`DataType`, float) :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.DataSpecificationNoMoreException:\ If there are no more spaces for new structures :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If there are an incorrect number of parameters * If the size of one of the tuples is incorrect * If one of the values to be assigned has an integer\ data_type but has a fractional part * If one of the values to be assigned would overflow its\ data_type :raise data_specification.exceptions.\ DataSpecificationUnknownTypeException: If one of the data types in\ the structure is unknown """ # start of struct if structure_id < 0 or structure_id >= constants.MAX_STRUCT_SLOTS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "structure id", structure_id, 0, constants.MAX_STRUCT_SLOTS - 1, Commands.START_STRUCT.name) # @UndefinedVariable if len(parameters) == 0 or \ len(parameters) > constants.MAX_STRUCT_ELEMENTS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "structure elements", len(parameters), 0, constants.MAX_STRUCT_ELEMENTS, Commands.WRITE_PARAM.name) # @UndefinedVariable if self.struct_slot[structure_id] != 0: raise exceptions.DataSpecificationStructureInUseException( structure_id) self.struct_slot[structure_id] = parameters cmd_word = ( (constants.LEN1 << 28) | (Commands.START_STRUCT.value << 20) | # @UndefinedVariable structure_id) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded cmd_string = "START_STRUCT id={0:d}".format(structure_id) self.write_command_to_files(cmd_word_list, cmd_string) # elements of the struct elem_index = 0 for i in parameters: label = i[0] data_type = i[1] value = i[2] if data_type not in DataType: raise exceptions.DataSpecificationUnknownTypeException( data_type.value, Commands.WRITE_PARAM.name) # @UndefinedVariable if value is not None: if value < data_type.min or value > data_type.max: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "value", value, data_type.min, data_type.max, Commands.WRITE_PARAM.name) # @UndefinedVariable if data_type.size <= 4: cmd_word = ( (constants.LEN2 << 28) | (Commands.STRUCT_ELEM.value << # @UndefinedVariable 20) | data_type.value) elif data_type.size == 8: cmd_word = ( (constants.LEN3 << 28) | (Commands.STRUCT_ELEM.value << # @UndefinedVariable 20) | data_type.value) else: raise exceptions.DataSpecificationInvalidSizeException( data_type.name, data_type.size, Commands.STRUCT_ELEM.name) # @UndefinedVariable cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) data_format = "<{}".format(data_type.struct_encoding) text_value = "{}".format(value) data_value = decimal.Decimal(text_value) * data_type.scale value_encoded = bytearray(struct.pack(data_format, data_value)) if data_type.size == 1: padding = bytearray(3) elif data_type.size == 2: padding = bytearray(2) else: padding = bytearray() cmd_word_list = cmd_word_encoded + value_encoded + padding if len(label) == 0: cmd_string = "STRUCT_ELEM element_id={0:d}, element_type="\ "{1:s}, value = {2:d}".format( elem_index, data_type.name, value) else: cmd_string = "STRUCT_ELEM element_id={0:d}, element_type="\ "{1:s}, value = {2:f}, label = {3:s}" cmd_string = cmd_string.format( elem_index, data_type.name, value, label) self.write_command_to_files(cmd_word_list, cmd_string) else: label = i[0] data_type = i[1] cmd_word = ( (constants.LEN1 << 28) | (Commands.STRUCT_ELEM.value << 20) | # @UndefinedVariable data_type.value) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded if len(label) == 0: cmd_string = "STRUCT_ELEM element_id={0:d}, element_type="\ "{1:s}".format(elem_index, data_type.name) else: cmd_string = "STRUCT_ELEM element_id={0:d}, element_type="\ "{1:s}, label = {2:s}".format(elem_index, data_type.name, label) self.write_command_to_files(cmd_word_list, cmd_string) elem_index += 1 # end of struct cmd_word = ( (constants.LEN1 << 28) | (Commands.END_STRUCT.value << 20)) # @UndefinedVariable cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded cmd_string = "END_STRUCT id={0:d}".format(structure_id) self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def get_structure_value( self, destination_id, structure_id, parameter_index, parameter_index_is_register=False): """ Insert command to get a value from a structure.\ The value is copied in a register. :param destination_id: The id of the destination register :type destination_id: int :param structure_id: The id of the source structure :type structure_id: int :param parameter_index: The id of the parameter/element to copy :type parameter_index: int :param parameter_index_is_register: True if the index of the structure\ is contained in a register :type parameter_index_is_register: bool :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If structure_id is not in the allowed range * If parameter_index is larger than the number of parameters\ declared in the original structure * If destination_id is not the id of a valid register * If parameter_index_is_register is True and parameter_index is\ not a valid register id :raise data_specification.exceptions.\ DataSpecificationNotAllocatedException: If the structure requested\ has not been declared """ if structure_id < 0 or structure_id >= constants.MAX_STRUCT_SLOTS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "structure_id", structure_id, 0, constants.MAX_STRUCT_SLOTS - 1, Commands.READ_PARAM.name) # @UndefinedVariable if destination_id < 0 or destination_id >= constants.MAX_REGISTERS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "destination_id", destination_id, 0, constants.MAX_REGISTERS - 1, Commands.READ_PARAM.name) # @UndefinedVariable if self.struct_slot[structure_id] is 0: raise exceptions.DataSpecificationNotAllocatedException( "structure", structure_id, Commands.READ_PARAM) if parameter_index_is_register is True: if (parameter_index < 0 or parameter_index >= constants.MAX_REGISTERS): raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "parameter_index", parameter_index, 0, constants.MAX_REGISTERS - 1, Commands.READ_PARAM.name) # @UndefinedVariable cmd_word = ( (constants.LEN1 << 28) | (Commands.READ_PARAM.value << 20) | # @UndefinedVariable (constants.DEST_AND_SRC1 << 16) | (destination_id << 12) | (parameter_index << 8) | structure_id) cmd_string = "READ_PARAM structure_id={0:d}, " \ "element_id_from_register={1:d}, " \ "destination_register={2:d}".format(structure_id, parameter_index, destination_id) else: if (parameter_index < 0 or parameter_index >= constants.MAX_STRUCT_ELEMENTS): raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "parameter_index", parameter_index, 0, constants.MAX_STRUCT_ELEMENTS - 1, Commands.READ_PARAM.name) # @UndefinedVariable if len(self.struct_slot[structure_id]) <= parameter_index: raise exceptions.DataSpecificationNotAllocatedException( "structure %d parameter" % structure_id, parameter_index, Commands.READ_PARAM) cmd_word = ( (constants.LEN1 << 28) | (Commands.READ_PARAM.value << 20) | # @UndefinedVariable (constants.DEST_ONLY << 16) | (destination_id << 12) | (parameter_index << 4) | structure_id) cmd_string = "READ_PARAM structure_id={0:d}, element_id={1:d}, " \ "destination_register={2:d}".\ format(structure_id, parameter_index, destination_id) encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) self.write_command_to_files(encoded_cmd_word, cmd_string)
[docs] def set_structure_value(self, structure_id, parameter_index, value, data_type, value_is_register=False): """ Insert command to set a value in a structure :param structure_id: * If called outside of a function, the id of the structure\ between 0 and 15 * If called within a function, the id of the structure argument, between 0 and 4 :type structure_id: int :param parameter_index: The index of the value to assign in the\ structure, between 0 and the number of parameters declared in the\ structure :type parameter_index: int :param value: * If value_is_register is False, the value to assign at the\ selected position as a float * If value_is_register is True, the id of the register containing\ the value to assign to the position, between 0 and 15 :type value: float :param data_type: type of the data to be stored in the structure.\ If parameter value_is_register is set to true, this variable is\ disregarded :type data_type: :py:class:`DataType` :param value_is_register: Identifies if value identifies a register :type value_is_register: bool :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If structure_id is not in the allowed range * If parameter_index is larger than the number of parameters\ declared in the original structure * If value_is_register is False, and the data type of the\ structure value is an integer, and the value has a fractional\ part * If value_is_register is False, and value would overflow the\ position in the structure * If value_is_register is True, and value is not a valid register\ id :raise data_specification.exceptions.\ DataSpecificationNotAllocatedException: If the structure requested\ has not been declared """ if structure_id < 0 or structure_id >= constants.MAX_STRUCT_SLOTS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "structure_id", structure_id, 0, constants.MAX_STRUCT_SLOTS - 1, Commands.WRITE_PARAM.name) # @UndefinedVariable if (parameter_index < 0 or parameter_index >= constants.MAX_STRUCT_ELEMENTS): raise exceptions.DataSpecificationParameterOutOfBoundsException( "parameter_index", parameter_index, 0, constants.MAX_STRUCT_ELEMENTS - 1, Commands.WRITE_PARAM.name) # @UndefinedVariable if self.struct_slot[structure_id] is 0: raise exceptions.DataSpecificationNotAllocatedException( "structure", structure_id, Commands.WRITE_PARAM) if len(self.struct_slot[structure_id]) <= parameter_index: raise exceptions.DataSpecificationNotAllocatedException( "structure %d parameter" % structure_id, parameter_index, Commands.WRITE_PARAM.name) # @UndefinedVariable if self.struct_slot[structure_id][parameter_index][1] is not data_type: raise exceptions.DataSpecificationTypeMismatchException( Commands.WRITE_PARAM.name) # @UndefinedVariable if value_is_register: if value < 0 or value >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "value", value, 0, constants.MAX_REGISTERS - 1, Commands.WRITE_PARAM.name) # @UndefinedVariable cmd_word = ( (constants.LEN1 << 28) | (Commands.WRITE_PARAM.value << 20) | # @UndefinedVariable (constants.SRC1_ONLY << 16) | (structure_id << 12) | (value << 8) | parameter_index) value_encoded = bytearray() cmd_string = "WRITE_PARAM structure_id={0:d}, element_id={1:d}, " \ "value=reg[{2:d}]".format(structure_id, parameter_index, value) else: if value < data_type.min or value > data_type.max: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "value", value, data_type.min, data_type.max, Commands.WRITE_PARAM.name) # @UndefinedVariable if data_type.size > 4 and data_type.size != 8: raise exceptions.DataSpecificationInvalidSizeException( data_type.name, data_type.size, Commands.WRITE_PARAM.name) # @UndefinedVariable cmd_len = constants.LEN2 if data_type.size <= 4 else constants.LEN3 cmd_word = ( (cmd_len << 28) | (Commands.WRITE_PARAM.value << 20) | # @UndefinedVariable (constants.NO_REGS << 16) | (structure_id << 12) | parameter_index) encoding_string = "<{0:s}".format(data_type.struct_encoding) value_encoded = bytearray(struct.pack(encoding_string, value)) if data_type.size == 1: padding = bytearray(3) elif data_type.size == 2: padding = bytearray(2) else: padding = bytearray() value_encoded += padding cmd_string = "WRITE_PARAM structure_id={0:d}, element_id={1:d}, " \ "value={2:d}".format(structure_id, parameter_index, value) encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = encoded_cmd_word + value_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def write_structure( self, structure_id, repeats=1, repeats_is_register=False): """ Insert command to write a structure to the current write pointer,\ causing the current write pointer to move on by the number of\ bytes needed to represent the structure :param structure_id: * If called within a function, the id of the structure to write,\ between 0 and 15 * If called outside of a function, the id of the structure\ argument, between 0 and 5 :type structure_id: int :param repeats: * If repeats_is_register is True, the id of the register\ containing the number of repeats, between 0 and 15 * If repeats_is_register is False, the number of repeats to write,\ between 0 and 255 :type repeats: int :param repeats_is_register: Identifies if repeats identifies a register :type repeats_is_register: bool :return: No value returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If repeats_is_register is False and structure_id is not\ a valid id * If repeats_is_register is True and structure_id * If the number of repeats is out of range :raise data_specification.exceptions.\ DataSpecificationNoRegionSelectedException: If no region has been \ selected to write to :raise data_specification.exceptions.\ DataSpecificationRegionExhaustedException: If the selected region \ has no more space """ if structure_id < 0 or structure_id >= constants.MAX_STRUCT_SLOTS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "structure_id", structure_id, 0, constants.MAX_STRUCT_SLOTS - 1, Commands.WRITE_STRUCT.name) # @UndefinedVariable if self.struct_slot[structure_id] is 0: raise exceptions.DataSpecificationNotAllocatedException( "structure", structure_id, Commands.WRITE_STRUCT.name) # @UndefinedVariable if repeats_is_register: if repeats < 0 or repeats >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "repeats", repeats, 0, constants.MAX_REGISTERS - 1, Commands.WRITE_STRUCT.name) # @UndefinedVariable cmd_word = ( (constants.LEN1 << 28) | (Commands.WRITE_STRUCT.value << 20) | # @UndefinedVariable (constants.SRC1_ONLY << 16) | (repeats << 8) | structure_id) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_string = "WRITE_STRUCT structure_id={0:d}, " \ "repeats=reg[{1:d}]".format(structure_id, repeats) cmd_word_list = cmd_word_encoded self.write_command_to_files(cmd_word_list, cmd_string) else: if repeats < 0 or repeats >= 16: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "repeats", repeats, 0, 15, Commands.WRITE_STRUCT.name) # @UndefinedVariable cmd_word = ( (constants.LEN1 << 28) | (Commands.WRITE_STRUCT.value << 20) | # @UndefinedVariable (repeats << 8) | structure_id) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_string = "WRITE_STRUCT structure_id={0:d}, " \ "repeats={1:d}".format(structure_id, repeats) cmd_word_list = cmd_word_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def start_function(self, function_id, argument_by_value): """ Insert command to start a function definition, with up to 5\ arguments, which are the ids of structures to be used within the\ function, each of which can be passed by reference or by value.\ In the commands following this command up to the end_function\ command, structures can only be referenced using the numbers 1 to\ 5 which address the arguments, rather than the original structure\ ids :param function_id: The id of the function currently defined. :type function_id: int :param argument_by_value: A list of up to 5 booleans indicating if the\ structure to be passed as an argument is to be passed by\ reference (i.e. changes made within the function are\ persisted) or by value (i.e. changes made within the\ function are lost when the function exits. The number of\ arguments is determined by the length of this list. :type argument_by_value: list of bool :return: The id of the function, between 0 and 31 :rtype: int :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException: If there are too \ many items in the list of arguments :raise data_specification.exceptions.\ DataSpecificationInvalidCommandException: If there is already a \ function being defined at this point :raise data_specification.exceptions.\ DataSpecificationFunctionInUse: If the function is already defined """ if self.ongoing_function_definition: raise exceptions.DataSpecificationInvalidCommandException( Commands.START_CONSTRUCTOR.name) # @UndefinedVariable if len(argument_by_value) > 5: raise exceptions.DataSpecificationParameterOutOfBoundsException( "number of arguments", len(argument_by_value), 0, 5, Commands.START_CONSTRUCTOR.name) # @UndefinedVariable if function_id < 0 or function_id >= constants.MAX_CONSTRUCTORS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "function_id", function_id, 0, constants.MAX_CONSTRUCTORS, "START_CONSTRUCTOR") if self.function[function_id] != 0: raise exceptions.DataSpecificationFunctionInUse(function_id) self.function[function_id] = argument_by_value cmd_string = "START_CONSTRUCTOR id={0:d} number_of_args={1:d}".format( function_id, len(argument_by_value)) self.ongoing_function_definition = True read_only_flags = 0 for i in xrange(len(argument_by_value)): cmd_string = "{0:s} arg[{1:d}]=".format(cmd_string, i + 1) if argument_by_value[i]: read_only_flags |= 2 ** i cmd_string = "{0:s}read-only".format(cmd_string) else: cmd_string = "{0:s}read-write".format(cmd_string) cmd_word = ( (constants.LEN1 << 28) | (Commands.START_CONSTRUCTOR.value << 20) | # @UndefinedVariable (function_id << 11) | (len(argument_by_value) << 8) | read_only_flags) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded self.write_command_to_files(cmd_word_list, cmd_string, indent=True)
[docs] def end_function(self): """ Insert command to mark the end of a function definition :return: Nothing is returned :rtype: None :raise data_specification.exceptions.\ DataSpecificationInvalidCommandException: If there is no function \ being defined at this point """ if not self.ongoing_function_definition: raise exceptions.DataSpecificationInvalidCommandException( Commands.END_CONSTRUCTOR.name) # @UndefinedVariable self.ongoing_function_definition = False cmd_word = ( (constants.LEN1 << 28) | (Commands.END_CONSTRUCTOR.value << 20)) # @UndefinedVariable cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded cmd_string = "END_CONSTRUCT" self.write_command_to_files(cmd_word_list, cmd_string, outdent=True)
[docs] def call_function(self, function_id, structure_ids): """ Insert command to call a function :param function_id: The id of a previously defined function, between 0\ and 31 :type function_id: int :param structure_ids: A list of structure_ids that will be passed into\ the function, each between 0 and 15 :type structure_ids: list of int :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If the function id is not valid * If any of the structure ids are not valid :raise data_specification.exceptions.\ DataSpecificationNotAllocatedException:\ * If a function has not been defined with the given id * If no structure has been defined with one of the ids in\ structure_ids :raise data_specification.exceptions.\ DataSpecificationWrongParameterNumberException:\ If a function is called with a wrong number of parameters :raise data_specification.exceptions.\ DataSpecificationDuplicateParameterException:\ If a function is called with duplicate parameters """ if function_id < 0 or function_id >= constants.MAX_CONSTRUCTORS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "function_id", function_id, 0, constants.MAX_CONSTRUCTORS - 1, Commands.CONSTRUCT.name) # @UndefinedVariable if self.function[function_id] == 0: raise exceptions.DataSpecificationNotAllocatedException( "function", function_id, Commands.CONSTRUCT.name) # @UndefinedVariable if len(structure_ids) != len(self.function[function_id]): raise exceptions.DataSpecificationWrongParameterNumberException( function_id, len(self.function[function_id]), structure_ids) if len(structure_ids) != len(set(structure_ids)): raise exceptions.DataSpecificationDuplicateParameterException( "CONSTRUCT %d" % function_id, structure_ids) cmd_string = "CONSTRUCT function_id={0:d}".format(function_id) param_word = None if len(structure_ids) > 0: param_word = 0 for i in xrange(len(structure_ids)): if structure_ids[i] < 0 \ or structure_ids[i] >= constants.MAX_STRUCT_SLOTS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "structure argument {0:d}".format(i), structure_ids[i], 0, constants.MAX_STRUCT_SLOTS - 1, Commands.CONSTRUCT.name) # @UndefinedVariable if self.struct_slot[structure_ids[i]] == 0: raise exceptions.DataSpecificationNotAllocatedException( "structure argument {0:d}".format(i), structure_ids[i], Commands.CONSTRUCT.name) # @UndefinedVariable param_word |= structure_ids[i] << (6 * i) cmd_string = "{0:s} arg[{1:d}]=struct[{2:d}]".format( cmd_string, i, structure_ids[i]) param_word_encoded = bytearray() if param_word is None: cmd_word_length = constants.LEN1 else: cmd_word_length = constants.LEN2 param_word_encoded = bytearray(struct.pack("<I", param_word)) cmd_word = ( (cmd_word_length << 28) | (Commands.CONSTRUCT.value << 20) | # @UndefinedVariable (function_id << 8)) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded + param_word_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def read_value(self, dest_id, data_type): """ Insert command to read a value from the current write pointer,\ causing the write pointer to move by the number of bytes read.\ The data is stored in a register passed as argument. :param dest_id: The id of the destination register. :type dest_id: int :param data_type: The type of the data to be read. :type data_type: :py:class:`DataType` :return: Nothing is returned :rtype: None """ cmd_len = constants.LEN1 cmd_code = Commands.READ.value # @UndefinedVariable cmd_field_usage = constants.DEST_ONLY if data_type not in DataType: raise exceptions.DataSpecificationUnknownTypeException( data_type.value, Commands.WRITE.name) # @UndefinedVariable if dest_id < 0 or dest_id >= constants.MAX_REGISTERS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "register", dest_id, 0, constants.MAX_REGISTERS - 1, Commands.READ.name) # @UndefinedVariable cmd_word = ( (cmd_len << 28) | (cmd_code << 20) | (cmd_field_usage << 16) | (dest_id << 12) | data_type.size) encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) cmd_string = "READ {0:d} bytes in register {0:d}" \ .format(data_type.size, dest_id) self.write_command_to_files(encoded_cmd_word, cmd_string)
[docs] def write_value( self, data, repeats=1, repeats_is_register=False, data_type=DataType.UINT32): """ Insert command to write a value one or more times to the current\ write pointer, causing the write pointer to move on by the number\ of bytes required to represent the data type. The data is passed\ as a parameter to this function :param data: the data to write as a float. :type data: float :param repeats: * If repeats_is_register is False, this parameter identifies the\ number of times to repeat the data, between 1 and 255\ (default 1) * If repeats_is_register is True, this parameter identifies the\ register that contains the number of repeats. :type repeats: int :param repeats_is_register: Indicates if the parameter repeats\ identifies the register containing the\ number of repeats of the value to write :type repeats_is_register: bool :param data_type: the type to convert data to :type data_type: :py:class:`DataType` :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If repeats_register is None, and repeats is out of range * If repeats_register is not a valid register id * If data_type is an integer type, and data has a fractional part * If data would overflow the data type :raise data_specification.exceptions.\ DataSpecificationUnknownTypeException: If the data type is not\ known :raise data_specification.exceptions.\ DataSpecificationInvalidSizeException: If the data size is invalid :raise data_specification.exceptions.\ DataSpecificationNoRegionSelectedException: If no region has been \ selected to write to """ if self.current_region is None: raise exceptions.DataSpecificationNoRegionSelectedException( "WRITE") if data_type not in DataType: raise exceptions.DataSpecificationUnknownTypeException( data_type.value, Commands.WRITE.name) # @UndefinedVariable data_size = data_type.size if data_size == 1: cmd_data_len = constants.LEN2 data_len = 0 elif data_size == 2: cmd_data_len = constants.LEN2 data_len = 1 elif data_size == 4: cmd_data_len = constants.LEN2 data_len = 2 elif data_size == 8: cmd_data_len = constants.LEN3 data_len = 3 else: raise exceptions.DataSpecificationInvalidSizeException( data_type.name, data_size, Commands.WRITE.name) # @UndefinedVariable if repeats_is_register is False: if (repeats <= 0) or (repeats > 255): raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "repeats", repeats, 0, 255, Commands.WRITE.name) # @UndefinedVariable else: if (repeats < 0) or (repeats >= constants.MAX_REGISTERS): raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "repeats_is_register", repeats_is_register, 0, (constants.MAX_REGISTERS - 1), Commands.WRITE.name) # @UndefinedVariable if (data_type.min > data) or (data_type.max < data): raise exceptions.DataSpecificationParameterOutOfBoundsException( "data", data, data_type.min, data_type.max, Commands.WRITE.name) # @UndefinedVariable parameters = 0 cmd_string = None if self.report_writer is not None: cmd_string = "WRITE data=0x%8.8X" % data if repeats_is_register is not False: repeat_reg_usage = 1 parameters |= (repeats << 4) if self.report_writer is not None: cmd_string = "{0:s}, repeats=reg[{1:d}]".format( cmd_string, repeats) else: repeat_reg_usage = constants.NO_REGS parameters |= repeats if self.report_writer is not None: cmd_string = "{0:s}, repeats={1:d}".format(cmd_string, repeats) cmd_word = ( (cmd_data_len << 28) | (Commands.WRITE.value << 20) | # @UndefinedVariable (repeat_reg_usage << 16) | (data_len << 12) | parameters) data_value = decimal.Decimal("{}".format(data)) * data_type.scale padding = 4 - data_type.size if data_type.size < 4 else 0 cmd_word_list = struct.pack( "<I{}{}x".format(data_type.struct_encoding, padding), cmd_word, data_value) if self.report_writer is not None: cmd_string = "{0:s}, dataType={1:s}".format( cmd_string, data_type.name) self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def write_value_from_register( self, data_register, repeats=1, repeats_is_register=False, data_type=DataType.UINT32): """ Insert command to write a value one or more times at the write\ pointer of the current memory region, causing it to move.\ The data is contained in a register whose id is passed to the\ function :param data_register: Identifies the register in which the data is\ stored. :type data_register: int :param repeats: * If repeats_register is None, this parameter identifies the\ number of times to repeat the data, between 1 and 255\ (default 1) * If repeats_register is not None (i.e. has an integer value), the\ content of this parameter is disregarded :type repeats: int :param repeats_is_register: Identifies the register containing the\ number of repeats of the value to write :type repeats_is_register: None or int :param data_type: the type of the data held in the register :type data_type: :py:class:`DataType` :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If repeats_register is None, and repeats is out of range * If repeats_register is not a valid register id * If data_register is not a valid register id :raise data_specification.exceptions.\ DataSpecificationUnknownTypeException: If the data type is not\ known :raise data_specification.exceptions.\ DataSpecificationNoRegionSelectedException: If no region has been \ selected to write to :raise data_specification.exceptions.\ DataSpecificationRegionExhaustedException: If the selected region \ has no more space """ if data_type not in DataType: raise exceptions.DataSpecificationUnknownTypeException( data_type.value, Commands.WRITE.name) # @UndefinedVariable if self.current_region is None: raise exceptions.DataSpecificationNoRegionSelectedException( Commands.WRITE.name) # @UndefinedVariable data_size = data_type.size if data_size == 1: cmd_data_len = 0 elif data_size == 2: cmd_data_len = 1 elif data_size == 4: cmd_data_len = 2 elif data_size == 8: cmd_data_len = 3 else: raise exceptions.DataSpecificationInvalidSizeException( data_type.name, data_size, Commands.WRITE.name) # @UndefinedVariable if repeats_is_register is False: if repeats <= 0 or repeats > 255: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "repeats", repeats, 0, 255, Commands.WRITE.name) # @UndefinedVariable else: if repeats < 0 or repeats >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "repeats", repeats, 0, (constants.MAX_REGISTERS - 1), Commands.WRITE.name) # @UndefinedVariable if (data_register < 0) or (data_register >= constants.MAX_REGISTERS): raise exceptions.DataSpecificationParameterOutOfBoundsException( "data_register", data_register, 0, (constants.MAX_REGISTERS - 1), Commands.WRITE.name) # @UndefinedVariable parameters = 0 cmd_string = "WRITE data=reg[{0:d}]".format(data_register) if repeats_is_register: reg_usage = constants.SRC1_AND_SRC2 parameters |= repeats << 4 cmd_string = "{0:s}, repeats=reg[{1:d}]".format(cmd_string, repeats) else: reg_usage = constants.SRC1_ONLY parameters |= repeats cmd_string = "{0:s}, repeats={1:d}".format(cmd_string, repeats) cmd_word = ( (constants.LEN1 << 28) | (Commands.WRITE.value << 20) | # @UndefinedVariable (reg_usage << 16) | (cmd_data_len << 12) | (data_register << 8) | parameters) encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = encoded_cmd_word cmd_string = "{0:s}, dataType={1:s}".format(cmd_string, data_type.name) self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def write_array(self, array_values, data_type=DataType.UINT32): """ Insert command to write an array, causing the write pointer\ to move on by (data type size * the array size), in bytes. :param array_values: An array of words to be written :type array_values: list of unsigned int :param data_type: Type of data contained in the array :type data_type: data_specification.enums.DataType :return: The position of the write pointer within the current region,\ in bytes from the start of the region :rtype: int :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationNoRegionSelectedException: If no region has been previously selected """ cmd_len = constants.LEN2 if self.current_region is None: raise exceptions.DataSpecificationNoRegionSelectedException( Commands.WRITE_ARRAY.name) # @UndefinedVariable cmd_word = ( (cmd_len << 28) | (Commands.WRITE_ARRAY.value << 20) | # @UndefinedVariable data_type.size) data = numpy.array(array_values, dtype='uint32') cmd_string = "WRITE_ARRAY, %d elements\n" % (data.size) cmd_word_list = bytearray(struct.pack("<II", cmd_word, data.size)) self.write_command_to_files(cmd_word_list, cmd_string) self.spec_writer.write(data.tostring())
[docs] def switch_write_focus(self, region): """ Insert command to switch the region being written to :param region: The id of the region to switch to, between 0 and 15 :type region: int :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException: If the region \ identifier is not valid :raise data_specification.exceptions.\ DataSpecificationNotAllocatedException: If the region has not been\ allocated :raise data_specification.exceptions.\ DataSpecificationRegionUnfilledException: If the selected region \ should not be filled """ if region < 0 or region >= constants.MAX_MEM_REGIONS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "region", region, 0, (constants.MAX_MEM_REGIONS - 1), Commands.SWITCH_FOCUS.name) # @UndefinedVariable if self.mem_slot[region] == 0: raise exceptions.DataSpecificationNotAllocatedException( "region", region, Commands.SWITCH_FOCUS.name) # @UndefinedVariable if self.mem_slot[region][2]: raise exceptions.DataSpecificationRegionUnfilledException( region, Commands.SWITCH_FOCUS.name) # @UndefinedVariable self.current_region = region reg_usage = 0x0 parameters = region & 0xF cmd_string = "SWITCH_FOCUS memRegion = {0:d}".format(region) # Write command to switch focus: cmd_word = ( (constants.LEN1 << 28) | (Commands.SWITCH_FOCUS.value << 20) | # @UndefinedVariable (reg_usage << 16) | (parameters << 8)) encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) cmd_word_string = encoded_cmd_word self.write_command_to_files(cmd_word_string, cmd_string)
[docs] def start_loop(self, counter_register_id, start, end, increment=1, start_is_register=False, end_is_register=False, increment_is_register=False): """ Insert command to start a loop :param counter_register_id: The id of the register to use as the loop\ counter, between 0 and 15 :type counter_register_id: int :param start: * If start_is_register is False, the number at which to\ start the loop counter, >= 0 * If start_is_register is True, the id of the register\ containing the number at which to start the loop counter,\ between 0 and 15 :type start: int :param end: * If end_is_register is False, the number which the loop\ counter must reach to stop the loop i.e. the loop will\ run while the contents of counter_register < end, >= 0 * If end_is_register is True, the id of the register\ containing the number at which to stop the loop,\ between 0 and 15 :type end: int :param increment: * If increment_is_register is False, the amount by which to\ increment the loop counter on each run of the loop, >= 0 * If increment_is_register is True, the id of the register\ containing the amount by which to increment the loop\ counter on each run of the loop, between 0 and 15 :type increment: int :param start_is_register: Indicates if start is a register id :type start_is_register: bool :param end_is_register: Indicates if end is a register id :type end_is_register: bool :param increment_is_register: Indicates if increment is a register id :type increment_is_register: bool :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If counter_register_id is not a valid register id * If start_is_register is True and increment is not a valid\ register_id * If end_is_register is True and increment is not a valid\ register_id * If increment_is_register is True, and increment is not a valid register_id * If start_is_register is False and start is not in the\ allowed range * If end_is_register is False and end is not in the\ allowed range * If increment_is_register is False and increment is not\ in the allowed range """ bit_field = 0 length = constants.LEN1 encoded_values = bytearray() cmd_word = (Commands.LOOP.value << 20) # @UndefinedVariable cmd_string = "LOOP" if counter_register_id < 0 \ or counter_register_id >= constants.MAX_REGISTERS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "counter_register_id", counter_register_id, 0, constants.MAX_REGISTERS - 1, Commands.LOOP.name) # @UndefinedVariable cmd_word |= counter_register_id cmd_string = "{0:s} counter_register_id=reg[{1:d}],".format( cmd_string, counter_register_id) if start_is_register: if start < 0 or start >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "start", start, 0, constants.MAX_REGISTERS - 1, Commands.LOOP.name) # @UndefinedVariable bit_field |= 0x4 cmd_word |= (start << 12) cmd_string = "{0:s} start=reg[{1:d}],".format(cmd_string, start) else: if (start < DataType.INT32.min or # @UndefinedVariable start > DataType.INT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "start", start, DataType.INT32.min, # @UndefinedVariable DataType.INT32.max, # @UndefinedVariable Commands.LOOP.name) # @UndefinedVariable length += 1 encoded_start = bytearray(struct.pack("<i", start)) encoded_values += encoded_start cmd_string = "{0:s} start={1:d},".format(cmd_string, start) if end_is_register: if end < 0 or end >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "end", end, 0, constants.MAX_REGISTERS - 1, Commands.LOOP.name) # @UndefinedVariable bit_field |= 0x2 cmd_word |= (end << 8) cmd_string = "{0:s} end=reg[{1:d}],".format(cmd_string, end) else: if (end < DataType.INT32.min or # @UndefinedVariable end > DataType.INT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "end", end, DataType.INT32.min, # @UndefinedVariable DataType.INT32.max, # @UndefinedVariable Commands.LOOP.name) # @UndefinedVariable length += 1 encoded_end = bytearray(struct.pack("<i", end)) encoded_values += encoded_end cmd_string = "{0:s} end={1:d},".format(cmd_string, end) if increment_is_register: if increment < 0 or increment >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "increment", increment, 0, constants.MAX_REGISTERS - 1, Commands.LOOP.name) # @UndefinedVariable bit_field |= 0x1 cmd_word |= (increment << 4) cmd_string = "{0:s} increment=reg[{1:d}],".format( cmd_string, increment) else: if (increment < DataType.INT32.min or # @UndefinedVariable increment > DataType.INT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "increment", increment, DataType.INT32.min, # @UndefinedVariable DataType.INT32.max, # @UndefinedVariable Commands.LOOP.name) # @UndefinedVariable length += 1 encoded_increment = bytearray(struct.pack("<i", increment)) encoded_values += encoded_increment cmd_string = "{0:s} increment={1:d},".format(cmd_string, increment) self.ongoing_loop = True cmd_word |= (length << 28) cmd_word |= (bit_field << 16) encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = encoded_cmd_word + encoded_values self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def break_loop(self): """ Insert command to break out of a loop before it has completed :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationInvalidCommandException: If there is no loop in \ operation at this point """ if self.ongoing_loop is not True: raise exceptions.DataSpecificationInvalidCommandException( "END_LOOP") cmd_word = ( (constants.LEN1 << 28) | (Commands.BREAK_LOOP.value << 20)) # @UndefinedVariable cmd_string = "BREAK_LOOP" cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def end_loop(self): """ Insert command to indicate that this is the end of the loop.\ Commands between the start of the loop and this command will be\ repeated. :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationInvalidCommandException: If there is no loop in \ operation at this point """ cmd_word = ( (constants.LEN1 << 28) | (Commands.END_LOOP.value << 20)) # @UndefinedVariable cmd_string = "END_LOOP" cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def start_conditional(self, register_id, condition, value, value_is_register=False): """ Insert command to start a conditional if...then...else construct.\ If the condition evaluates to true, the statement is executed up\ to the next else statement, or the end of the conditional,\ whichever comes first. :param register_id: The id of a register to compare the value of :type register_id: int :param condition: The condition which must be true to execute the\ following commands :type condition: :py:class:`Condition` :param value: * If value_is_register is False, the value to compare to\ the value in the register * If value_is_register is True, the id of the register\ containing the value to compare, between 0 and 15 :type value: int :param value_is_register: Indicates if value is a register id :type value_is_register: bool :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If the register_id is not a valid register id * if value_is_register is True and value is not a valid\ register id :raise data_specification.exceptions.\ DataSpecificationUnknownTypeException: If the condition is not a \ valid condition """ data_encoded = bytearray() cmd_word = 0 cmd_string = "" if register_id < 0 or register_id >= constants.MAX_REGISTERS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "register_id", register_id, 0, constants.MAX_REGISTERS - 1, Commands.IF.name) # @UndefinedVariable if value_is_register: if value < 0 or value >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "value", value, 0, constants.MAX_REGISTERS - 1, Commands.IF.name) # @UndefinedVariable else: if (value < DataType.INT32.min or # @UndefinedVariable value > DataType.INT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "value", value, DataType.INT32.min, # @UndefinedVariable DataType.INT32.max, # @UndefinedVariable Commands.IF.name) # @UndefinedVariable if condition not in Condition: raise exceptions.DataSpecificationUnknownConditionException( condition, Commands.IF.name) # @UndefinedVariable if value_is_register: bit_field = 0x3 cmd_word = ( (constants.LEN1 << 28) | (Commands.IF.value << 20) | # @UndefinedVariable (bit_field << 16) | (register_id << 8) | (value << 4) | condition.value) cmd_string = "IF reg[{0:d}] {1:s} reg[{2:d}]".format( register_id, condition.operator, value) elif not value_is_register: bit_field = 0x2 cmd_word = ( (constants.LEN2 << 28) | (Commands.IF.value << 20) | # @UndefinedVariable (bit_field << 16) | (register_id << 8) | condition.value) data_encoded = bytearray(struct.pack("<i", value)) cmd_string = "IF reg[{0:d}] {1:s} {2:d}".format( register_id, condition.operator, value) self.conditionals.append(False) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded + data_encoded self.write_command_to_files(cmd_word_list, cmd_string, indent=True)
[docs] def else_conditional(self): """ Insert command for the else of an if...then...else construct.\ If the condition of the conditional evaluates to false, the\ statements up between the conditional and the insertion of this\ "else" are skipped, and the statements from this point until the\ end of the conditional are executed. :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationInvalidCommandException: If there is no \ conditional in operation at this point """ if len(self.conditionals) == 0 or \ self.conditionals[len(self.conditionals) - 1] is True: raise exceptions.DataSpecificationInvalidCommandException("ELSE") self.conditionals[len(self.conditionals) - 1] = True cmd_word = ( (constants.LEN1 << 28) | (Commands.ELSE.value << 20)) # @UndefinedVariable cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded cmd_string = "ELSE" self.write_command_to_files( cmd_word_list, cmd_string, indent=True, outdent=True)
[docs] def end_conditional(self): """ Insert command to mark the end of an if...then...else construct :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationInvalidCommandException: If there is no \ conditional in operation at this point """ if len(self.conditionals) == 0: raise exceptions.DataSpecificationInvalidCommandException("END_IF") self.conditionals.pop() cmd_word = ( (constants.LEN1 << 28) | (Commands.END_IF.value << 20)) # @UndefinedVariable cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded cmd_string = "END_IF" self.write_command_to_files(cmd_word_list, cmd_string, outdent=True)
[docs] def set_register_value(self, register_id, data, data_is_register=False, data_type=DataType.UINT32): """ Insert command to set the value of a register :param register_id: The id of the register to assign, between 0 and 15 :type register_id: int :param data: * If data_is_register is True, the register id containing\ the data to set, between 0 and 15 * If data_is_register is False, the data as a float :type data: float :param data_is_register: Indicates if data is a register id :type data_is_register: bool :param data_type: The type of the data to be assigned :type data_type: :py:class:`DataType` :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If register_id is not a valid register_id * If data_is_register is True, and data is not a valid\ register id * If data_is_register is False, data_type is an integer\ type and data has a fractional part * If data_is_register if False, and data would overflow the\ data type :raise data_specification.exceptions.\ DataSpecificationUnknownTypeException: If the data type is not\ known """ if register_id < 0 or register_id >= constants.MAX_REGISTERS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "register_id", register_id, 0, constants.MAX_REGISTERS - 1, Commands.MV.name) # @UndefinedVariable if data_is_register: # Build command to move between registers: if data < 0 or data >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "data", data, 0, constants.MAX_REGISTERS - 1, Commands.MV.name) # @UndefinedVariable if data == register_id: raise exceptions.DataSpecificationDuplicateParameterException( Commands.MV.name, # @UndefinedVariable [register_id, data]) dest_reg = register_id src_reg = data cmd_word = ( (constants.LEN1 << 28) | (Commands.MV.value << 20) | # @UndefinedVariable (constants.DEST_AND_SRC1 << 16) | (dest_reg << 12) | (src_reg << 8)) encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = encoded_cmd_word cmd_string = "reg[{0:d}] = reg[{1:d}]".format(dest_reg, src_reg) else: # Build command to assign from an immediate: # command has a second word (the immediate) if data_type.min > data or data_type.max < data: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "data", data, data_type.min, data_type.max, Commands.MV.name) # @UndefinedVariable if data_type.size > 4: length = constants.LEN3 else: length = constants.LEN2 dest_reg = register_id cmd_word = ( (length << 28) | (Commands.MV.value << 20) | # @UndefinedVariable (constants.DEST_ONLY << 16) | (dest_reg << 12)) scaled_data = int(data * data_type.scale) encoding_string = "<{0:s}".format(data_type.struct_encoding) encoded_data = bytearray(struct.pack(encoding_string, scaled_data)) while len(encoded_data) % 4: encoded_data += bytearray(struct.pack("<b", 0)) encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = encoded_cmd_word + encoded_data cmd_string = "reg[{0:d}] = {1:d} (0x{2:X})".format( dest_reg, data, data) self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def save_write_pointer(self, register_id): """ Insert command to save the write pointer to a register :param register_id: The id of the register to assign, between 0 and 15 :type register_id: int :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException: If the register_id\ is not a valid register id :raise data_specification.exceptions.\ DataSpecificationNoRegionSelectedException: If no region has been \ selected """ if register_id < 0 or register_id >= constants.MAX_REGISTERS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "register_id", register_id, 0, constants.MAX_REGISTERS - 1, Commands.GET_WR_PTR.name) # @UndefinedVariable if self.current_region is None: raise exceptions.DataSpecificationNoRegionSelectedException( "GET_WR_PTR") bit_field = 0x4 cmd_word = ( (constants.LEN1 << 28) | (Commands.GET_WR_PTR.value << 20) | # @UndefinedVariable (bit_field << 16) | (register_id << 12)) cmd_string = "GET_WR_PTR reg[{0:d}]".format(register_id) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def set_write_pointer(self, address, address_is_register=False, relative_to_current=False): """ Insert command to set the position of the write pointer within the\ current region :param address: * If address_is_register is True, the id of the register\ containing the address to move to * If address_is_register is False, the address to move the\ write pointer to :type address: int :param address_is_register: Indicates if the the address is a\ register id :type address_is_register: bool :param relative_to_current: Indicates if the address is to be added to\ the current address, or used as an absolute address from\ the start of the current region :type relative_to_current: bool :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException: If the \ address_is_register is True and address is not a valid register id :raise data_specification.exceptions.\ DataSpecificationNoRegionSelectedException: If no region has been \ selected """ if self.current_region is None: raise exceptions.DataSpecificationNoRegionSelectedException( Commands.SET_WR_PTR.name) # @UndefinedVariable if relative_to_current: relative = 1 relative_string = "RELATIVE" else: relative = 0 relative_string = "ABSOLUTE" data_encoded = bytearray() if address_is_register: if address < 0 or address >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "address", address, 0, constants.MAX_REGISTERS - 1, Commands.SET_WR_PTR.name) # @UndefinedVariable cmd_word = ( (constants.LEN1 << 28) | (Commands.SET_WR_PTR.value << 20) | # @UndefinedVariable (constants.SRC1_ONLY << 16) | (address << 8) | relative) cmd_string = "SET_WR_PTR reg[{0:d}] {1:s}".format( address, relative_string) else: if not relative_to_current: if (address < 0 or address > DataType.UINT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "address", address, 0, DataType.UINT32.max, # @UndefinedVariable Commands.SET_WR_PTR.name) # @UndefinedVariable else: data_encoded = bytearray(struct.pack("<I", address)) else: if (address < DataType.INT32.min or # @UndefinedVariable address > DataType.INT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "address", address, DataType.INT32.min, # @UndefinedVariable DataType.INT32.max, # @UndefinedVariable Commands.SET_WR_PTR.name) # @UndefinedVariable else: data_encoded = bytearray(struct.pack("<i", address)) cmd_word = ( (constants.LEN2 << 28) | (Commands.SET_WR_PTR.value << 20) | # @UndefinedVariable (constants.NO_REGS << 16) | relative) cmd_string = "SET_WR_PTR {0:d} {1:s}".format( address, relative_string) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded + data_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def align_write_pointer(self, log_block_size, log_block_size_is_register=False, return_register_id=None): """ Insert command to align the write pointer against a power-of-2\ block size in bytes. Zeros are inserted in the intervening space :param log_block_size: * If log_block_size_is_register is False, log to base 2 of\ the block size (e.g. The write pointer will be moved so\ that it is a multiple of 2^(log_block_size)),\ between 0 and 32 * If log_block_size_is_register is True, the id of the\ register containing log to the base 2 of the block size,\ between 0 and 15 :type log_block_size: int :param log_block_size_is_register: Indicates if log_block_size is a\ register id :type log_block_size_is_register: bool :param return_register_id: The id of a register where the write\ pointer will be written to once it has been updated, between\ 0 and 15or None if no such writing is to be done :type return_register_id: int :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If log_block_size_is_register is False, and\ log_block_size is not within the allowed range * If log_block_size_is_register is True and log_block_size\ is not a valid register id :raise data_specification.exceptions.\ DataSpecificationRegionOutOfBoundsException:\ If the move of the pointer would put it outside of the\ current region :raise data_specification.exceptions.\ DataSpecificationNoRegionSelectedException: If no region has been \ selected """ bit_field = 0 imm_value = 0 return_register_value = 0 block_size_reg = 0 cmd_string = "ALIGN_WR_PTR" if self.current_region is None: raise exceptions.DataSpecificationNoRegionSelectedException( Commands.ALIGN_WR_PTR.name) # @UndefinedVariable if return_register_id is not None: if return_register_id < 0 \ or return_register_id >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "return_register_id", return_register_id, 0, constants.MAX_REGISTERS - 1, Commands.ALIGN_WR_PTR.name) # @UndefinedVariable bit_field |= 0x4 return_register_value = return_register_id cmd_string = "{0:s} reg[{1:d}] =".format( cmd_string, return_register_value) if log_block_size_is_register: if log_block_size < 0 or log_block_size >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "log_block_size", log_block_size, 0, constants.MAX_REGISTERS - 1, Commands.ALIGN_WR_PTR.name) # @UndefinedVariable bit_field |= 0x2 block_size_reg = log_block_size cmd_string = "{0:s} align(reg[{1:d}])".format( cmd_string, block_size_reg) else: if log_block_size < 0 or log_block_size > 31: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "log_block_size", log_block_size, 0, 31, Commands.ALIGN_WR_PTR.name) # @UndefinedVariable imm_value = log_block_size cmd_string = "{0:s} align({1:d})".format( cmd_string, imm_value) cmd_word = ( (constants.LEN1 << 28) | (Commands.ALIGN_WR_PTR.value << 20) | # @UndefinedVariable (bit_field << 16) | (return_register_value << 12) | (block_size_reg << 8) | imm_value) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def call_arithmetic_operation(self, register_id, operand_1, operation, operand_2, signed, operand_1_is_register=False, operand_2_is_register=False): """ Insert command to perform an arithmetic operation on two signed or\ unsigned values and store the result in a register :param register_id: The id of the register to store the result in :type register_id: int :param operand_1: * If operand_1_is_register is True, the id of a register\ where the first operand can be found, between 0 and 15 * If operand_1_is_register is False, a 32-bit value :type operand_1: int :param operation: The operation to perform :type operation: :py:class:`ArithmeticOperation` :param operand_2: * If operand_2_is_register is True, the id of a register\ where the second operand can be found, between 0 and 15 * If operand_2_is_register is False, a 32-bit value :type operand_2: int :param signed: Indicates if the values should be considered signed :type signed: bool :param operand_1_is_register: Indicates if operand_1 is a register id :type operand_1_is_register: bool :param operand_2_is_register: Indicates if operand_2 is a register id :type operand_2_is_register: bool :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been\ initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If operand_1_is_register is True and operand_1 is not a\ valid register id * If operand_2_is_register is True and operand_2 is not a\ valid register id :raise data_specification.exceptions.\ DataSpecificationUnknownTypeException: If operation is not a known\ operation """ cmd_length = 0 bit_field = 0x4 register_op_1 = 0 register_op_2 = 0 operand_1_encoded = bytearray() operand_2_encoded = bytearray() cmd_string = "ARTIH_OP" signed_value = 0 if signed: signed_value = 1 cmd_string = "{0:s} SIGNED".format(cmd_string) else: cmd_string = "{0:s} UNSIGNED".format(cmd_string) if register_id < 0 or register_id >= constants.MAX_REGISTERS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "register_id", register_id, 0, constants.MAX_REGISTERS - 1, Commands.ARITH_OP.name) # @UndefinedVariable cmd_string = "{0:s} reg[{1:d}] =".format(cmd_string, register_id) if operand_1_is_register: if operand_1 < 0 or operand_1 >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "operand_1", operand_1, 0, constants.MAX_REGISTERS - 1, Commands.ARITH_OP.name) # @UndefinedVariable bit_field |= 2 register_op_1 = operand_1 cmd_string = "{0:s} reg[{1:d}]".format(cmd_string, register_op_1) else: cmd_length += 1 if signed: if (operand_1 < DataType.INT32.min or # @UndefinedVariable operand_1 > DataType.INT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "operand_1", operand_1, DataType.INT32.min, # @UndefinedVariable DataType.INT32.max, # @UndefinedVariable Commands.ARITH_OP.name) # @UndefinedVariable operand_1_encoded = bytearray(struct.pack("<i", operand_1)) cmd_string = "{0:s} {1:d}".format(cmd_string, operand_1) else: if (operand_1 < DataType.UINT32.min or # @UndefinedVariable operand_1 > DataType.UINT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "operand_1", operand_1, DataType.UINT32.min, # @UndefinedVariable DataType.UINT32.max, # @UndefinedVariable Commands.ARITH_OP.name) # @UndefinedVariable operand_1_encoded = bytearray(struct.pack("<I", operand_1)) cmd_string = "{0:s} {1:d}".format(cmd_string, operand_1) if operation not in ArithmeticOperation: raise exceptions.DataSpecificationInvalidOperationException( "arithmetic", operation.value, Commands.ARITH_OP.name) # @UndefinedVariable cmd_string = "{0:s} {1:s}".format(cmd_string, operation.operator) if operand_2_is_register: if operand_2 < 0 or operand_2 >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "operand_2", operand_2, 0, constants.MAX_REGISTERS - 1, Commands.ARITH_OP.name) # @UndefinedVariable bit_field |= 1 register_op_2 = operand_2 cmd_string = "{0:s} reg[{1:d}]".format(cmd_string, register_op_2) else: cmd_length += 1 if signed: if (operand_2 < DataType.INT32.min or # @UndefinedVariable operand_2 > DataType.INT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "operand_2", operand_2, DataType.INT32.min, # @UndefinedVariable DataType.INT32.max, # @UndefinedVariable Commands.ARITH_OP.name) # @UndefinedVariable operand_2_encoded = bytearray(struct.pack("<i", operand_2)) cmd_string = "{0:s} {1:d}".format(cmd_string, operand_2) else: if (operand_2 < DataType.UINT32.min or # @UndefinedVariable operand_2 > DataType.UINT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "operand_2", operand_2, DataType.UINT32.min, # @UndefinedVariable DataType.UINT32.max, # @UndefinedVariable Commands.ARITH_OP.name) # @UndefinedVariable operand_2_encoded = bytearray(struct.pack("<I", operand_2)) cmd_string = "{0:s} {1:d}".format(cmd_string, operand_2) cmd_word = ( (cmd_length << 28) | (Commands.ARITH_OP.value << 20) | # @UndefinedVariable (signed_value << 19) | (bit_field << 16) | (register_id << 12) | (register_op_1 << 8) | (register_op_2 << 4) | operation.value) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = ( cmd_word_encoded + operand_1_encoded + operand_2_encoded) self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def logical_and(self, register_id, operand_1, operand_2, operand_1_is_register=False, operand_2_is_register=False): """ Insert command to perform a logical AND operation, using the\ _call_logic_operation. :param register_id: The id of the register to store the result in :type register_id: int :param operand_1: * If operand_1_is_register is True, the id of a register\ where the first operand can be found, between 0 and 15 * If operand_1_is_register is False, a 32-bit value :type operand_1: int :param operand_2: * If operand_2_is_register is True, the id of a register\ where the second operand can be found. between 0 and 15 * If operand_2_is_register is False, a 32-bit value :type operand_2: int :param operand_1_is_register: Indicates if operand_1 is a register id :type operand_1_is_register: bool :param operand_2_is_register: Indicates if operand_2 is a register id :type operand_2_is_register: bool :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If operand_1_is_register is True and operand_1 is not a\ valid register id * If operand_2_is_register is True and operand_2 is not a\ valid register id """ self._call_logic_operation(register_id, operand_1, LogicOperation.AND, operand_2, operand_1_is_register, operand_2_is_register)
[docs] def logical_or(self, register_id, operand_1, operand_2, operand_1_is_register=False, operand_2_is_register=False): """ Insert command to perform a logical OR operation, using the\ _call_logic_operation. :param register_id: The id of the register to store the result in :type register_id: int :param operand_1: * If operand_1_is_register is True, the id of a register\ where the first operand can be found, between 0 and 15 * If operand_1_is_register is False, a 32-bit value :type operand_1: int :param operand_2: * If operand_2_is_register is True, the id of a register\ where the second operand can be found. between 0 and 15 * If operand_2_is_register is False, a 32-bit value :type operand_2: int :param operand_1_is_register: Indicates if operand_1 is a register id :type operand_1_is_register: bool :param operand_2_is_register: Indicates if operand_2 is a register id :type operand_2_is_register: bool :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If operand_1_is_register is True and operand_1 is not a\ valid register id * If operand_2_is_register is True and operand_2 is not a\ valid register id """ self._call_logic_operation(register_id, operand_1, LogicOperation.OR, operand_2, operand_1_is_register, operand_2_is_register)
[docs] def logical_left_shift(self, register_id, operand_1, operand_2, operand_1_is_register=False, operand_2_is_register=False): """ Insert command to perform a logical left shift operation, using\ the _call_logic_operation. :param register_id: The id of the register to store the result in :type register_id: int :param operand_1: * If operand_1_is_register is True, the id of a register\ where the first operand can be found, between 0 and 15 * If operand_1_is_register is False, a 32-bit value :type operand_1: int :param operand_2: * If operand_2_is_register is True, the id of a register\ where the second operand can be found. between 0 and 15 * If operand_2_is_register is False, a 32-bit value :type operand_2: int :param operand_1_is_register: Indicates if operand_1 is a register id :type operand_1_is_register: bool :param operand_2_is_register: Indicates if operand_2 is a register id :type operand_2_is_register: bool :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If operand_1_is_register is True and operand_1 is not a\ valid register id * If operand_2_is_register is True and operand_2 is not a\ valid register id """ self._call_logic_operation(register_id, operand_1, LogicOperation.LEFT_SHIFT, operand_2, operand_1_is_register, operand_2_is_register)
[docs] def logical_right_shift(self, register_id, operand_1, operand_2, operand_1_is_register=False, operand_2_is_register=False): """ Insert command to perform a logical right shift operation, using\ the _call_logic_operation. :param register_id: The id of the register to store the result in :type register_id: int :param operand_1: * If operand_1_is_register is True, the id of a register\ where the first operand can be found, between 0 and 15 * If operand_1_is_register is False, a 32-bit value :type operand_1: int :param operand_2: * If operand_2_is_register is True, the id of a register\ where the second operand can be found. between 0 and 15 * If operand_2_is_register is False, a 32-bit value :type operand_2: int :param operand_1_is_register: Indicates if operand_1 is a register id :type operand_1_is_register: bool :param operand_2_is_register: Indicates if operand_2 is a register id :type operand_2_is_register: bool :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If operand_1_is_register is True and operand_1 is not a\ valid register id * If operand_2_is_register is True and operand_2 is not a\ valid register id """ self._call_logic_operation(register_id, operand_1, LogicOperation.RIGHT_SHIFT, operand_2, operand_1_is_register, operand_2_is_register)
[docs] def logical_xor(self, register_id, operand_1, operand_2, operand_1_is_register=False, operand_2_is_register=False): """ Insert command to perform a logical xor operation, using the _call_logic_operation. :param register_id: The id of the register to store the result in :type register_id: int :param operand_1: * If operand_1_is_register is True, the id of a register\ where the first operand can be found, between 0 and 15 * If operand_1_is_register is False, a 32-bit value :type operand_1: int :param operand_2: * If operand_2_is_register is True, the id of a register\ where the second operand can be found. between 0 and 15 * If operand_2_is_register is False, a 32-bit value :type operand_2: int :param operand_1_is_register: Indicates if operand_1 is a register id :type operand_1_is_register: bool :param operand_2_is_register: Indicates if operand_2 is a register id :type operand_2_is_register: bool :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If operand_1_is_register is True and operand_1 is not a\ valid register id * If operand_2_is_register is True and operand_2 is not a\ valid register id """ self._call_logic_operation(register_id, operand_1, LogicOperation.XOR, operand_2, operand_1_is_register, operand_2_is_register)
[docs] def logical_not(self, register_id, operand, operand_is_register=False): """ Insert command to perform a logical xor operation, using the _call_logic_operation. :param register_id: The id of the register to store the result in :type register_id: int :param operand: * If operand_is_register is True, the id of a register\ where the first operand can be found, between 0 and 15 * If operand_is_register is False, a 32-bit value :type operand: int :param operand_is_register: Indicates if operand_1 is a register id :type operand_is_register: bool :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If operand_is_register is True and operand_1 is not a\ valid register id """ self._call_logic_operation(register_id, operand, LogicOperation.NOT, 0, operand_is_register, False)
def _call_logic_operation(self, register_id, operand_1, operation, operand_2, operand_1_is_register=False, operand_2_is_register=False): """ Insert command to perform a logic operation on two signed or\ unsigned values and store the result in a register :param register_id: The id of the register to store the result in :type register_id: int :param operand_1: * If operand_1_is_register is True, the id of a register\ where the first operand can be found, between 0 and 15 * If operand_1_is_register is False, a 32-bit value :type operand_1: int :param operation: The operation to perform :type operation: :py:class:`LogicOperation` :param operand_2: * If operand_2_is_register is True, the id of a register\ where the second operand can be found. between 0 and 15 * If operand_2_is_register is False, a 32-bit value :type operand_2: int :param operand_1_is_register: Indicates if operand_1 is a register id :type operand_1_is_register: bool :param operand_2_is_register: Indicates if operand_2 is a register id :type operand_2_is_register: bool :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If operand_1_is_register is True and operand_1 is not a\ valid register id * If operand_2_is_register is True and operand_2 is not a\ valid register id :raise data_specification.exceptions.\ DataSpecificationInvalidOperationException: If operation is not a\ known operation """ cmd_length = 0 bit_field = 0x4 register_op_1 = 0 register_op_2 = 0 operand_1_encoded = bytearray() operand_2_encoded = bytearray() cmd_string = "LOGIC_OP" if register_id < 0 or register_id >= constants.MAX_REGISTERS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "register_id", register_id, 0, constants.MAX_REGISTERS - 1, Commands.LOGIC_OP.name) # @UndefinedVariable cmd_string = "{0:s} reg[{1:d}] =".format(cmd_string, register_id) if operation not in LogicOperation: raise exceptions.DataSpecificationInvalidOperationException( "logic", operation.value, Commands.LOGIC_OP.name) # @UndefinedVariable if operation.value == LogicOperation.NOT.value: # @UndefinedVariable cmd_string = "{0:s} {1:s}".format(cmd_string, operation.operator) if operand_1_is_register: if operand_1 < 0 or operand_1 >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "operand_1", operand_1, 0, constants.MAX_REGISTERS - 1, Commands.LOGIC_OP.name) # @UndefinedVariable bit_field |= 2 register_op_1 = operand_1 cmd_string = "{0:s} reg[{1:d}]".format(cmd_string, register_op_1) else: cmd_length += 1 if (operand_1 < DataType.UINT32.min or # @UndefinedVariable operand_1 > DataType.UINT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "operand_1", operand_1, DataType.UINT32.min, # @UndefinedVariable DataType.UINT32.max, # @UndefinedVariable Commands.LOGIC_OP.name) # @UndefinedVariable operand_1_encoded = bytearray(struct.pack("<I", operand_1)) cmd_string = "{0:s} {1:d}".format(cmd_string, operand_1) if operation.value != LogicOperation.NOT.value: # @UndefinedVariable cmd_string = "{0:s} {1:s}".format(cmd_string, operation.operator) if operand_2_is_register: if operand_2 < 0 or operand_2 >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "operand_2", operand_2, 0, constants.MAX_REGISTERS - 1, Commands.LOGIC_OP.name) # @UndefinedVariable bit_field |= 1 register_op_2 = operand_2 cmd_string = "{0:s} reg[{1:d}]".format( cmd_string, register_op_2) else: cmd_length += 1 if (operand_2 < DataType.UINT32.min or # @UndefinedVariable operand_2 > DataType.UINT32.max): # @UndefinedVariable raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "operand_2", operand_2, DataType.UINT32.min, # @UndefinedVariable DataType.UINT32.max, # @UndefinedVariable Commands.LOGIC_OP.name) # @UndefinedVariable operand_2_encoded = bytearray(struct.pack("<I", operand_2)) cmd_string = "{0:s} {1:d}".format(cmd_string, operand_2) cmd_word = ( (cmd_length << 28) | (Commands.LOGIC_OP.value << 20) | # @UndefinedVariable (bit_field << 16) | (register_id << 12) | (register_op_1 << 8) | (register_op_2 << 4) | operation.value) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = ( cmd_word_encoded + operand_1_encoded + operand_2_encoded) self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def copy_structure(self, source_structure_id, destination_structure_id, source_id_is_register=False, destination_id_is_register=False): """ Insert command to copy a structure, possibly overwriting another\ structure :param source_structure_id: * If source_id_is_register is True, the id of the register holding the source structure id, between 0 and 15 * Otherwise, the id of the source structure, between\ 0 and 15 :type source_structure_id: int :param destination_structure_id: * If destination_id_is_register is True, the id of the\ register holding the destination structure id, between\ 0 and 15 * If destination_id_is_register is False, the id of the\ destination structure, between 0 and 15 :type destination_structure_id: int :param source_id_is_register: Indicates if source_structure_id is a\ register id :type source_id_is_register: bool :param destination_id_is_register: Indicates if\ destination_structure_id is a register id :type destination_id_is_register: bool :return: The id of the copied structure, between 0 and 15 :rtype: int :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If source_id_is_register is True and source_structure_id\ is not a valid register id * If destination_id_is_register is True and\ destination_structure_id is not a valid register id * If source_id_is_register is False and source_structure_id\ is not a valid structure id * If destination_id_is_register is False and\ destination_structure_id is not a valid structure id :raise data_specification.exceptions.\ DataSpecificationNotAllocatedException:\ * If no structure with id source_structure_id has been\ allocated """ bit_field = 0 cmd_string = "COPY_STRUCT" if source_structure_id == destination_structure_id and \ destination_id_is_register == source_id_is_register: raise exceptions.DataSpecificationDuplicateParameterException( "COPY_STRUCT", [source_structure_id, destination_structure_id]) if source_id_is_register: if source_structure_id < 0 \ or source_structure_id >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "source_structure_id", source_structure_id, 0, constants.MAX_REGISTERS - 1, Commands.COPY_STRUCT.name) # @UndefinedVariable bit_field |= constants.SRC1_ONLY cmd_string = "{0:s} source_struct = reg[{1:d}]".format( cmd_string, source_structure_id) else: if source_structure_id < 0 \ or source_structure_id >= constants.MAX_STRUCT_SLOTS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "source_structure_id", source_structure_id, 0, constants.MAX_STRUCT_SLOTS - 1, Commands.COPY_STRUCT.name) # @UndefinedVariable if self.struct_slot[source_structure_id] == 0: raise exceptions.DataSpecificationNotAllocatedException( "struct", source_structure_id, "COPY_STRUCT") cmd_string = "{0:s} source_struct = {1:d}".format( cmd_string, source_structure_id) if destination_id_is_register: if destination_structure_id < 0 \ or destination_structure_id >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "destination_structure_id", destination_structure_id, 0, constants.MAX_REGISTERS - 1, Commands.COPY_STRUCT.name) # @UndefinedVariable bit_field |= constants.DEST_ONLY cmd_string = "{0:s} destination_struct = reg[{1:d}]".format( cmd_string, destination_structure_id) else: if destination_structure_id < 0 \ or destination_structure_id >= constants.MAX_STRUCT_SLOTS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "destination_structure_id", destination_structure_id, 0, constants.MAX_STRUCT_SLOTS - 1, Commands.COPY_STRUCT.name) # @UndefinedVariable cmd_string = "{0:s} destination_struct = {1:d}".format( cmd_string, destination_structure_id) cmd_word = ( (constants.LEN1 << 28) | (Commands.COPY_STRUCT.value << 20) | # @UndefinedVariable (bit_field << 16) | (destination_structure_id << 12) | (source_structure_id << 8)) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def copy_structure_parameter(self, source_structure_id, source_parameter_index, destination_id, destination_parameter_index=None, destination_is_register=False): """ Insert command to copy the value of a parameter from one structure to another :param source_structure_id: The id of the source structure,\ between 0 and 15 :type source_structure_id: int :param source_parameter_index: The index of the parameter in the\ source structure :type source_parameter_index: int :param destination_id: The id of the destination structure, or the id of the destination register, between 0 and 15 :type destination_id: int :param destination_parameter_index: The index of the parameter in the\ destination structure. Ignored when writing to a register. :type destination_parameter_index: int :return: Nothing is returned :param destination_is_register: Indicates whether the destination is a structure or a register. :type destination_is_register: boolean :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If source_structure_id is not a valid structure id * If destination_id is not a valid structure id * If source_parameter_index is not a valid parameter index\ in the source structure * If destination_parameter_index is not a valid parameter\ index in the destination structure :raise data_specification.exceptions.\ DataSpecificationNotAllocatedException:\ * If no structure with id destination_id has been\ allocated * If no structure with id source_structure_id has been allocated """ if source_structure_id < 0 \ or source_structure_id >= constants.MAX_STRUCT_SLOTS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "source_structure_id", source_structure_id, 0, constants.MAX_STRUCT_SLOTS - 1, Commands.COPY_PARAM.name) # @UndefinedVariable if source_parameter_index < 0 \ or source_parameter_index >= constants.MAX_STRUCT_ELEMENTS: raise exceptions.DataSpecificationParameterOutOfBoundsException( "source_parameter_index", source_parameter_index, 0, constants.MAX_STRUCT_ELEMENTS - 1, Commands.COPY_PARAM.name) # @UndefinedVariable if self.struct_slot[source_structure_id] == 0: raise exceptions.DataSpecificationNotAllocatedException( "structure", source_structure_id, "COPY_PARAM") if (len(self.struct_slot[source_structure_id]) <= source_parameter_index): raise exceptions.DataSpecificationNotAllocatedException( "parameter", source_parameter_index, "COPY_PARAM") if not destination_is_register: if (destination_parameter_index < 0 or destination_parameter_index >= constants.MAX_STRUCT_ELEMENTS): raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "destination_parameter_index", destination_parameter_index, 0, constants.MAX_STRUCT_ELEMENTS - 1, Commands.COPY_PARAM.name) # @UndefinedVariable if destination_id < 0 \ or destination_id >= constants.MAX_STRUCT_SLOTS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "destination_structure_id", destination_id, 0, constants.MAX_STRUCT_SLOTS - 1, Commands.COPY_PARAM.name) # @UndefinedVariable if self.struct_slot[destination_id] == 0: raise exceptions.DataSpecificationNotAllocatedException( "structure", destination_id, "COPY_PARAM") if (len(self.struct_slot[source_structure_id]) <= source_parameter_index): raise exceptions.DataSpecificationNotAllocatedException( "parameter", destination_parameter_index, "COPY_PARAM") if (len(self.struct_slot[destination_id]) <= destination_parameter_index): raise exceptions.DataSpecificationNotAllocatedException( "parameter", destination_parameter_index, "COPY_PARAM") if (self.struct_slot[source_structure_id] [source_parameter_index][1] != self.struct_slot[destination_id] [destination_parameter_index][1]): raise exceptions.DataSpecificationTypeMismatchException( "COPY_PARAM") if (source_structure_id == destination_id and destination_parameter_index == source_parameter_index): raise exceptions.DataSpecificationDuplicateParameterException( "COPY_PARAM", [source_structure_id, source_parameter_index, destination_id, destination_parameter_index]) cmd_word_1 = ( (constants.LEN2 << 28) | (Commands.COPY_PARAM.value << 20) | # @UndefinedVariable (constants.NO_REGS << 16) | (destination_id << 12) | (source_structure_id << 8)) cmd_word_2 = ((destination_parameter_index << 8) | source_parameter_index) cmd_string = ( "COPY_PARAM source_structure_id = {0:d}, " "source_parameter_id = {1:d}, " "destination_structure_id = {2:d}, " "destination_parameter_id = {3:d}".format( source_structure_id, source_parameter_index, destination_id, destination_parameter_index)) else: if destination_id < 0 \ or destination_id >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "destination_register_id", destination_id, 0, constants.MAX_REGISTERS - 1, Commands.COPY_PARAM.name) # @UndefinedVariable cmd_word_1 = ( (constants.LEN2 << 28) | (Commands.COPY_PARAM.value << 20) | # @UndefinedVariable (constants.DEST_ONLY << 16) | (destination_id << 12) | (source_structure_id << 8)) cmd_word_2 = source_parameter_index cmd_string = "WRITE_PARAM source_structure_id = {0:d}, " \ "source_parameter_id = {1:d}, " \ "destination_register_id = {2:d}"\ .format(source_structure_id, source_parameter_index, destination_id) cmd_word_1_encoded = bytearray(struct.pack("<I", cmd_word_1)) cmd_word_2_encoded = bytearray(struct.pack("<I", cmd_word_2)) cmd_word_list = cmd_word_1_encoded + cmd_word_2_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def print_value(self, value, value_is_register=False, data_type=DataType.UINT32): """ Insert command to print out a value (for debugging) :param value: * If value_is_register is True, the id of the register\ containing the value to print * If value_is_register is False, the value to print as a\ float :type value: float :param value_is_register: Indicates if the value is a register :type value_is_register: bool :param data_type: The type of the data to be printed :type data_type: :py:class:`DataType` :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If value_is_register is True and value is not a valid\ register id * If value_is_register is False, the data_type is an integer type and value has a fractional part * If value_is_register is False and the value would overflow the data type :raise data_specification.exceptions.\ DataSpecificationUnknownTypeException:\ * If data_type is not a valid data type """ cmd_word_length = constants.LEN1 source_register_id = 0 bit_field = 0 data_encoded = bytearray() if value_is_register: if value < 0 or value >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "value", value, 0, constants.MAX_REGISTERS - 1, Commands.PRINT_VAL.name) # @UndefinedVariable bit_field |= 2 source_register_id = value cmd_string = "PRINT_VAL reg[{0:d}]".format(source_register_id) else: if value < data_type.min or value > data_type.max: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "value", value, data_type.min, data_type.max, Commands.PRINT_VAL.name) # @UndefinedVariable if data_type.size <= 4: cmd_word_length = constants.LEN2 else: cmd_word_length = constants.LEN3 data_encoding_string = "<{0:s}".format(data_type.struct_encoding) data_encoded = bytearray(struct.pack(data_encoding_string, value)) while len(data_encoded) % 4: data_encoded += bytearray(struct.pack("<b", 0)) cmd_string = "PRINT_VAL {0:d}".format(value) cmd_word = ( (cmd_word_length << 28) | (Commands.PRINT_VAL.value << 20) | # @UndefinedVariable (bit_field << 16) | (source_register_id << 8) | data_type.value) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded + data_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def print_text(self, text): """ Insert command to print some text (for debugging) :param text: The text to write (max 12 characters) :type text: str :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails """ text_len = len(text) if text_len > 12: raise exceptions.DataSpecificationParameterOutOfBoundsException( "len(text)", text_len, 1, 12, Commands.PRINT_TXT.name) # @UndefinedVariable if text_len <= 4: cmd_word_len = constants.LEN2 elif text_len <= 8: cmd_word_len = constants.LEN3 else: cmd_word_len = constants.LEN4 text_encoded = bytearray(text) # add final padding to the encoded text if text_len % 4 is not 0: text_encoded += bytearray(4 - (text_len % 4)) cmd_string = "PRINT_TXT \"{0:s}\"".format(text) cmd_word = ( (cmd_word_len << 28) | (Commands.PRINT_TXT.value << 20) | # @UndefinedVariable (text_len - 1)) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded + text_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def print_struct(self, structure_id, structure_id_is_register=False): """ Insert command to print out a structure (for debugging) :param structure_id: * If structure_id_is_register is True, the id of the\ register containing the id of the structure to print,\ between 0 and 15 * If structure_id_is_register is False, the id of the\ structure to print, between 0 and 15 :type structure_id: int :param structure_id_is_register: Indicates if the structure_id is a\ register :type structure_id_is_register: bool :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been\ initialised :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException:\ * If structure_id_is_register is True and structure_id is\ not a valid register id * If structure_id_is_register is False and structure_id is\ not a valid structure id :raise data_specification.exceptions.\ DataSpecificationNotAllocatedException: If \ structure_id_is_register is False and structure_id is the id of a \ structure that has not been allocated """ struct_register = 0 bit_field = 0 cmd_string = "PRINT_STRUCT" if structure_id_is_register: if structure_id < 0 or structure_id >= constants.MAX_REGISTERS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "structure_id", structure_id, 0, constants.MAX_REGISTERS - 1, Commands.PRINT_STRUCT.name) # @UndefinedVariable struct_register = structure_id structure_id = 0 bit_field = 0x2 cmd_string = "{0:s} struct(reg[{1:d}])".format( cmd_string, struct_register) else: if structure_id < 0 or structure_id >= constants.MAX_STRUCT_SLOTS: raise exceptions.\ DataSpecificationParameterOutOfBoundsException( "structure_id", structure_id, 0, constants.MAX_STRUCT_SLOTS - 1, Commands.PRINT_STRUCT.name) # @UndefinedVariable if self.struct_slot[structure_id] == 0: raise exceptions.DataSpecificationNotAllocatedException( "structure", structure_id, "PRINT_STRUCT") cmd_string = "{0:s} struct({1:d})".format( cmd_string, structure_id) cmd_word = ( (constants.LEN1 << 28) | (Commands.PRINT_STRUCT.value << 20) | # @UndefinedVariable (bit_field << 16) | (struct_register << 8) | structure_id) cmd_word_encoded = bytearray(struct.pack("<I", cmd_word)) cmd_word_list = cmd_word_encoded self.write_command_to_files(cmd_word_list, cmd_string)
[docs] def end_specification(self, close_writer=True): """ Insert a command to indicate that the specification has finished\ and finish writing :param close_writer: Indicates whether to close the underlying\ writer(s) :type close_writer: bool :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails """ self.comment("\nEnd of specification:") cmd_word = ( (constants.LEN1 << 28) | (Commands.END_SPEC.value << 20)) # @UndefinedVariable encoded_cmd_word = bytearray(struct.pack("<I", cmd_word)) parameter = -1 encoded_parameter = struct.pack("<i", parameter) cmd_word_list = encoded_cmd_word + encoded_parameter cmd_string = "END_SPEC" self.write_command_to_files(cmd_word_list, cmd_string) if close_writer: self.spec_writer.close() if self.report_writer is not None: self.report_writer.close()
[docs] def write_command_to_files(self, cmd_word_list, cmd_string, indent=False, outdent=False, no_instruction_number=False): """ Writes the binary command to the binary output file and, if the\ user has requested a text output for debug purposes, also write\ the text version to the text file.\ Setting the optional parameter 'indent' to True causes subsequent\ commands to be indented by two spaces relative to this one.\ Similarly, setting 'outdent' to True, reverses this spacing. :param cmd_word_list: list of binary words to be added to the binary\ data specification file :type cmd_word_list: bytearray :param cmd_string: string describing the command to be added to the\ report for the data specification file :type cmd_string: str :param indent: if the following lines need to be indented :type indent: bool :param outdent: if the following lines need to be out-dented :type outdent: bool :param no_instruction_number: if each report line should include also\ the address of the command in the file :param no_instruction_number: bool :return: Nothing is returned :rtype: None :raise data_specification.exceptions.DataUndefinedWriterException:\ If the binary specification file writer has not been initialised :raise spinn_storage_handlers.exceptions.DataWriteException:\ If a write to external storage fails """ if self.spec_writer is None: raise exceptions.DataUndefinedWriterException( "The spec file writer has not been initialised") elif len(cmd_word_list) > 0: self.spec_writer.write(cmd_word_list) if self.report_writer is not None: if outdent is True: self.txt_indent -= 1 if self.txt_indent < 0: self.txt_indent = 0 if no_instruction_number is True: formatted_cmd_string = "{0:s}{1:s}\n".format( " " * self.txt_indent, cmd_string) else: formatted_cmd_string = "%8.8X. %s%s\n" % ( self.instruction_counter, " " * self.txt_indent, cmd_string) self.instruction_counter += len(cmd_word_list) self.report_writer.write(formatted_cmd_string) if indent is True: self.txt_indent += 1 return
@property def region_sizes(self): """ A list of sizes of each region that has been reserved. Note that\ the list will include 0s for each non-reserved region. """ return [ self.mem_slot[i] if self.mem_slot[i] == 0 else self.mem_slot[i][0] for i in range(len(self.mem_slot)) ]