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 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 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))
]