Source code for data_specification.data_specification_executor_functions

from data_specification import constants, exceptions, memory_region_collection
import struct
from data_specification.memory_region import MemoryRegion


[docs]class DataSpecificationExecutorFunctions(object): """ This class includes the function related to each of the commands\ of the data specification file. """ __slots__ = [ # ???????????? "spec_reader", # ???????????? "mem_writer", # ???????????? "memory_space", # ???????????? "space_allocated", # ???????????? "current_region", # ???????????? "registers", # ???????????? "mem_regions", # ???????????? "struct_slots", # ???????????? "_cmd_size", # ???????????? "opcode", # ???????????? "use_dest_reg", # ???????????? "use_src1_reg", # ???????????? "use_src2_reg", # ???????????? "dest_reg", # ???????????? "src1_reg", # ???????????? "src2_reg", # ???????????? "data_len" ] def __init__(self, spec_reader, memory_space): """ :param spec_reader: The object to read the specification language file\ from :type spec_reader:\ :py:class:`data_specification.abstract_data_reader.\ AbstractDataReader` :param memory_space: Memory space available for the data to be\ generated :type memory_space: int """ self.spec_reader = spec_reader self.memory_space = memory_space self.space_allocated = 0 self.current_region = None self.registers = [0] * constants.MAX_REGISTERS self.mem_regions = memory_region_collection.MemoryRegionCollection( constants.MAX_MEM_REGIONS) self.struct_slots = [0] * constants.MAX_STRUCT_SLOTS # storage objects self._cmd_size = None self.opcode = None self.use_dest_reg = None self.use_src1_reg = None self.use_src2_reg = None self.dest_reg = None self.src1_reg = None self.src2_reg = None self.data_len = None def __unpack_cmd__(self, cmd): """ Routine to unpack the command read from the data spec file. The\ parameters of the command are stored in the class data :param cmd: The command read form the data spec file :type cmd: int :return: No value returned :rtype: None """ self._cmd_size = (cmd >> 28) & 0x3 self.opcode = (cmd >> 20) & 0xFF self.use_dest_reg = (cmd >> 18) & 0x1 == 0x1 self.use_src1_reg = (cmd >> 17) & 0x1 == 0x1 self.use_src2_reg = (cmd >> 16) & 0x1 == 0x1 self.dest_reg = (cmd >> 12) & 0xF self.src1_reg = (cmd >> 8) & 0xF self.src2_reg = (cmd >> 4) & 0xF self.data_len = (cmd >> 12) & 0x3
[docs] def execute_break(self, cmd): """ This command raises an exception to stop the execution of the data spec executor (DSE) :param cmd: the command which triggered the function call :type cmd: int :return: No value returned :rtype: None :raise data_specification.exceptions.ExecuteBreakInstruction:\ Raises the exception to break the execution of the DSE """ raise exceptions.ExecuteBreakInstruction( self.spec_reader.tell(), self.spec_reader.filename)
[docs] def execute_nop(self, cmd): """ This command executes no operation :param cmd: the command which triggered the function call :type cmd: int :return: No value returned :rtype: None """ pass
[docs] def execute_reserve(self, cmd): """ This command reserves a region and assigns some memory space to it :param cmd: the command which triggered the function call :type cmd: int :return: No value returned :rtype: None :raise data_specification.exceptions.DataSpecificationSyntaxError:\ If there is an error in the command syntax :raise data_specification.exceptions.\ DataSpecificationParameterOutOfBoundsException: If the requested \ size of the region is beyond the available memory space """ self.__unpack_cmd__(cmd) region = cmd & 0x1F # cmd[4:0] if self._cmd_size != constants.LEN2: raise exceptions.DataSpecificationSyntaxError( "Command {0:s} requires one word as argument (total 2 words), " "but the current encoding ({1:X}) is specified to be {2:d} " "words long".format( "RESERVE", cmd, self._cmd_size)) unfilled = (cmd >> 7) & 0x1 == 0x1 if not self.mem_regions.is_empty(region): raise exceptions.DataSpecificationRegionInUseException(region) size_encoded = self.spec_reader.read(4) size = struct.unpack("<I", str(size_encoded))[0] if size & 0x3 != 0: size = (size + 4) - (size & 0x3) if (size <= 0) or (size > self.memory_space): raise exceptions.DataSpecificationParameterOutOfBoundsException( "region size", size, 1, self.memory_space, "RESERVE") self.mem_regions[region] = MemoryRegion( memory_pointer=0, unfilled=unfilled, size=size) self.space_allocated += size
[docs] def execute_free(self, cmd): raise exceptions.UnimplementedDSECommand("FREE")
[docs] def execute_declare_rng(self, cmd): raise exceptions.UnimplementedDSECommand("DECLARE_RNG")
[docs] def execute_random_dist(self, cmd): raise exceptions.UnimplementedDSECommand("DECLARE_RANDOM_DIST")
[docs] def execute_get_random_rumber(self, cmd): raise exceptions.UnimplementedDSECommand("GET_RANDOM_NUMBER")
[docs] def execute_start_struct(self, cmd): raise exceptions.UnimplementedDSECommand("START_STRUCT")
[docs] def execute_struct_elem(self, cmd): raise exceptions.UnimplementedDSECommand("STRUCT_ELEM")
[docs] def execute_end_struct(self, cmd): raise exceptions.UnimplementedDSECommand("END_STRUCT")
[docs] def execute_start_constructor(self, cmd): raise exceptions.UnimplementedDSECommand("START_CONSTRUCTOR")
[docs] def execute_end_constructor(self, cmd): raise exceptions.UnimplementedDSECommand("END_CONSTRUCTOR")
[docs] def execute_construct(self, cmd): raise exceptions.UnimplementedDSECommand("CONSTRUCT")
[docs] def execute_read(self, cmd): raise exceptions.UnimplementedDSECommand("READ")
[docs] def execute_write(self, cmd): """ This command writes the given value in the specified region a number\ of times as identified by either a value in the command or a register\ value :param cmd: the command which triggered the function call :type cmd: int :return: No value returned :rtype: None :raise data_specification.exceptions.DataSpecificationSyntaxError:\ If there is an error in the command syntax """ self.__unpack_cmd__(cmd) if self.use_src2_reg: n_repeats = self.registers[self.src2_reg] else: n_repeats = cmd & 0xFF # Convert data length to bytes data_len = (1 << self.data_len) if self.use_src1_reg: value = self.registers[self.src1_reg] else: if self._cmd_size == constants.LEN2 and data_len != 8: read_data = self.spec_reader.read(4) value = struct.unpack("<I", str(read_data))[0] elif self._cmd_size == constants.LEN3 and data_len == 8: read_data = self.spec_reader.read(8) value = struct.unpack("<Q", str(read_data))[0] else: raise exceptions.DataSpecificationSyntaxError( "Command {0:s} requires a value as an argument, but the " "current encoding ({1:X}) is specified to be {2:d} words " "long and the data length command argument is specified " "to be {3:d} bytes long".format( "WRITE", cmd, self._cmd_size, data_len)) # Perform the writes self._write_to_mem( value, data_len, n_repeats, "WRITE")
[docs] def execute_write_array(self, cmd): """ This command writes an array of values in the specified region :param cmd: the command which triggered the function call :type cmd: int :return: No value returned :rtype: None """ length_encoded = self.spec_reader.read(4) length = struct.unpack("<I", str(length_encoded))[0] value_encoded = self.spec_reader.read(4 * length) self._write_bytes_to_mem(value_encoded, "WRITE_ARRAY")
[docs] def execute_write_struct(self, cmd): raise exceptions.UnimplementedDSECommand("WRITE_STRUCT")
[docs] def execute_block_copy(self, cmd): raise exceptions.UnimplementedDSECommand("BLOCK_COPY")
[docs] def execute_switch_focus(self, cmd): """ This command switches the focus to the desired, already allocated,\ memory region :param cmd: the command which triggered the function call :type cmd: int :return: No value returned :rtype: None :raise data_specification.exceptions.\ DataSpecificationRegionUnfilledException: If the focus is being \ switched to a region of memory which has been declared to be kept \ unfilled """ self.__unpack_cmd__(cmd) if not self.use_src1_reg: region = (cmd >> 8) & 0xF else: region = self.registers[self.src1_reg] if self.mem_regions.is_empty(region): raise exceptions.DataSpecificationRegionUnfilledException( region, "SWITCH_FOCUS") else: self.current_region = region
[docs] def execute_loop(self, cmd): raise exceptions.UnimplementedDSECommand("LOOP")
[docs] def execute_break_loop(self, cmd): raise exceptions.UnimplementedDSECommand("BREAK_LOOP")
[docs] def execute_end_loop(self, cmd): raise exceptions.UnimplementedDSECommand("END_LOOP")
[docs] def execute_if(self, cmd): raise exceptions.UnimplementedDSECommand("IF")
[docs] def execute_else(self, cmd): raise exceptions.UnimplementedDSECommand("ELSE")
[docs] def execute_end_if(self, cmd): raise exceptions.UnimplementedDSECommand("ENDIF")
[docs] def execute_mv(self, cmd): """ This command moves an immediate value to a register or copies the \ value of a register to another register :param cmd: the command which triggered the function call :type cmd: int :return: No value returned :rtype: None :raise data_specification.exceptions.DataSpecificationSyntaxError: \ if the destination register is not correctly specified - the \ destination must be a register and the appropriate bit needs \ to be set in the specification """ self.__unpack_cmd__(cmd) if not self.use_dest_reg: raise exceptions.DataSpecificationSyntaxError( "Destination register not correctly specified") if self.use_src1_reg: self.registers[self.dest_reg] = self.registers[self.src1_reg] else: data_encoded = self.spec_reader.read(4) data = struct.unpack("<I", str(data_encoded))[0] self.registers[self.dest_reg] = data
[docs] def execute_get_wr_ptr(self, cmd): raise exceptions.UnimplementedDSECommand("GET_WR_PTR")
[docs] def execute_set_wr_ptr(self, cmd): address = None self.__unpack_cmd__(cmd) if self.use_src1_reg == 1: # the data is a register future_address = self.registers[self.dest_reg] else: # the data is a raw address data_encoded = self.spec_reader.read(4) future_address = struct.unpack("<I", str(data_encoded))[0] # check that the address is relative or absolute if cmd & 0x1 == 1: # relative to its current write pointer if self.mem_regions[self.current_region] is None: raise exceptions.DataSpecificationNoRegionSelectedException( "the write pointer for this region is currently undefined") else: # relative to the base address of the region (obsolete) # noinspection PyTypeChecker address = ( self.mem_regions[self.current_region].write_pointer + future_address) else: address = future_address # update write pointer self.mem_regions[self.current_region].write_pointer = address
[docs] def execute_reset_wr_ptr(self, cmd): raise exceptions.UnimplementedDSECommand("RESET_RW_PTR")
[docs] def execute_align_wr_ptr(self, cmd): raise exceptions.UnimplementedDSECommand("ALIGN_WR_PTR")
[docs] def execute_arith_op(self, cmd): raise exceptions.UnimplementedDSECommand("ARITH_OP")
[docs] def execute_logic_op(self, cmd): raise exceptions.UnimplementedDSECommand("LOGIC_OP")
[docs] def execute_reformat(self, cmd): raise exceptions.UnimplementedDSECommand("REFORMAT")
[docs] def execute_copy_struct(self, cmd): raise exceptions.UnimplementedDSECommand("COPY_STRUCT")
[docs] def execute_copy_param(self, cmd): raise exceptions.UnimplementedDSECommand("COPY_PARAM")
[docs] def execute_write_param(self, cmd): raise exceptions.UnimplementedDSECommand("WRITE_PARAM")
[docs] def execute_write_param_component(self, cmd): raise exceptions.UnimplementedDSECommand("WRITE_PARAM_COMPONENT")
[docs] def execute_print_val(self, cmd): raise exceptions.UnimplementedDSECommand("PRINT_VAL")
[docs] def execute_print_txt(self, cmd): raise exceptions.UnimplementedDSECommand("PRINT_TXT")
[docs] def execute_print_struct(self, cmd): raise exceptions.UnimplementedDSECommand("PRINT_STRUCT")
[docs] def execute_read_param(self, cmd): raise exceptions.UnimplementedDSECommand("READ_PARAM")
[docs] def execute_end_spec(self, cmd): """ Return the value which terminates the data spec executor :param cmd: the command which triggered the function call :type cmd: int :return: constants.END_SPEC_EXECUTOR :rtype: int :raise data_specification.exceptions.DataSpecificationSyntaxError:\ If command END_SPEC != -1 """ read_data = self.spec_reader.read(4) value = struct.unpack("<i", str(read_data))[0] if value != -1: raise exceptions.DataSpecificationSyntaxError( "Command END_SPEC requires an argument equal to -1. The " "current argument value is {0:d}".format(value)) return constants.END_SPEC_EXECUTOR
def _write_to_mem(self, value, n_bytes, repeat, command): """ Write the specified value to data memory the specified amount of\ times. The selected memory region needs to be already allocated :param value: the value to be written in the data memory region :type value: int :param n_bytes: number of bytes that represent the value :type n_bytes: int :param repeat: the number of times the value is to be repeated :type repeat: int :param command: the command which is being executed :type command: str :return: No value returned :rtype: None :raise data_specification.exceptions.\ DataSpecificationNoRegionSelectedException: raised if there is no \ memory region selected for the write operation :raise data_specification.exceptions.\ DataSpecificationRegionNotAllocated: raised if the selected region\ has not been allocated memory space :raise data_specification.exceptions.DataSpecificationNoMoreException:\ raised if the selected region has not enough available memory to \ store the required data :raise data_specification.exceptions.\ DataSpecificationUnknownTypeLengthException: raised if the data \ type size is not 1, 2, 4, or 8 bytes """ if self.current_region is None: raise exceptions.DataSpecificationNoRegionSelectedException( command) if self.mem_regions.is_empty(self.current_region) is None: raise exceptions.DataSpecificationRegionNotAllocated( self.current_region, command) space_allocated = self.mem_regions[self.current_region].allocated_size space_used = self.mem_regions[self.current_region].write_pointer # noinspection PyTypeChecker space_available = space_allocated - space_used space_required = n_bytes * repeat if space_available < space_required: raise exceptions.DataSpecificationNoMoreException( space_available, space_required, self.current_region) if n_bytes == 1: encoded_value = struct.pack("<B", value) elif n_bytes == 2: encoded_value = struct.pack("<H", value) elif n_bytes == 4: encoded_value = struct.pack("<I", value) elif n_bytes == 8: encoded_value = struct.pack("<Q", value) else: raise exceptions.DataSpecificationUnknownTypeLengthException( n_bytes, command) encoded_array = encoded_value * repeat current_write_ptr = self.mem_regions[self.current_region].write_pointer # noinspection PyTypeChecker self.mem_regions[self.current_region].region_data[ current_write_ptr:current_write_ptr + len( encoded_array)] = encoded_array self.mem_regions[self.current_region].increment_write_pointer( len(encoded_array)) def _write_bytes_to_mem(self, data, command): """ Write raw bytes to data memory The selected memory region needs to be already allocated :param data: the value to be written in the data memory region :type data: str :param command: the command which is being executed :type command: str :return: No value returned :rtype: None :raise data_specification.exceptions.\ DataSpecificationNoRegionSelectedException: raised if there is no \ memory region selected for the write operation :raise data_specification.exceptions.\ DataSpecificationRegionNotAllocated: raised if the selected region\ has not been allocated memory space :raise data_specification.exceptions.DataSpecificationNoMoreException:\ raised if the selected region has not enough available memory to \ store the required data """ data_length = len(data) if self.current_region is None: raise exceptions.DataSpecificationNoRegionSelectedException( command) if self.mem_regions.is_empty(self.current_region) is None: raise exceptions.DataSpecificationRegionNotAllocated( self.current_region, command) space_allocated = self.mem_regions[self.current_region].allocated_size space_used = self.mem_regions[self.current_region].write_pointer # noinspection PyTypeChecker space_available = space_allocated - space_used space_required = data_length if space_available < space_required: raise exceptions.DataSpecificationNoMoreException( space_available, space_required, self.current_region) current_write_ptr = self.mem_regions[self.current_region].write_pointer # noinspection PyTypeChecker self.mem_regions[self.current_region].region_data[ current_write_ptr:current_write_ptr + data_length] = data self.mem_regions[self.current_region].increment_write_pointer( data_length)