def unpack(self, data_bytes): """ :param bytes data_bytes: :rtype: XilinxBitstream """ sync_marker = self.context.format.sync_word sync_marker_index = data_bytes.find(sync_marker) assert sync_marker_index >= 0, \ "The sync marker is not present in the provided bitstream data" assert sync_marker_index + len(sync_marker) < len(data_bytes) - WORD_SIZE, \ "The configuration data is expected to contain at least one word size worth of data" return XilinxBitstream( DataObject.create_packed(self.context, data_bytes[:sync_marker_index], XilinxBitstreamHeaderInterface), DataObject.create_packed( self.context, data_bytes[sync_marker_index:sync_marker_index + len(sync_marker)], XilinxBitstreamSyncMarker, ), DataObject.create_packed( self.context, data_bytes[sync_marker_index + len(sync_marker):], XilinxPackets, ))
def _create_type1_payload(self, data_stream, header, register_format): """ Unpack the payload for a type 1 packet :param io.BytesIO data_stream: :param XilinxCtypePacketHeader header: :param XilinxRegisterFormat register_format: :rtype: Tuple[DataObject, bool] """ if header.word_count == 0: return None, False payload_data = data_stream.read(header.word_count * WORD_SIZE) if header.opcode == 0: raise ValueError( "NOOP Xilinx packets are expected to have a 0 length payload") payload = DataObject.create_packed( self.context, payload_data, XilinxType1Payload, converter_args=(register_format, ), ) if register_format.name == "Cmd": return payload, payload.unpack().get( "command").get_model().value_name == "DESYNC" return payload, False
def __init__(self, converters_by_type, analyzers_by_type, modifiers_by_type, bytes): super(XilinxContext, self).__init__(converters_by_type, analyzers_by_type, modifiers_by_type) self._bitstream = DataObject.create_packed(self, bytes, XilinxBitstream)
def unpack(self, data_bytes): """ :param bytes data_bytes: :rtype: ArrayModel """ frames = [] data_stream = io.BytesIO(data_bytes) expected_size = 0 for frame_index in range(self._major_format.frame_count): frame_data = data_stream.read(self._major_format.frame_size) expected_size += self._major_format.frame_size frame_description = None if len(self._major_format.frame_descriptions) > frame_index: frame_description = self._major_format.frame_descriptions[ frame_index] FrameInterface = type("XilinxFdriLogicFrame", (XilinxFdriLogicFrame, ), {}) FrameInterface.__doc__ = frame_description frames.append( DataObject.create_packed(self.context, frame_data, FrameInterface)) assert expected_size == len(data_bytes), \ "The number of bytes provided {} does not match the expected number of bytes {}".format( len(data_bytes), expected_size ) major_name = "".join( [p.title() for p in self._major_format.name.split("_")]) class_name = "{}".format(major_name) MajorModel = type(class_name, (XilinxFdriLogicMajor, ), {}) MajorModel.__doc__ = "The config data for a {} major".format( self._major_format.name) return MajorModel(frames)
def unpack(self, data_bytes): """ :param bytes data_bytes: :rtype: ArrayModel """ if self.context.id_code is None: raise ValueError( "The ID code for the targeted device has not been set on the bitstream context." ) rows = [] expected_size = 0 data_stream = io.BytesIO(data_bytes) fdri_format = self.context.format.get_fdri_format(self.context.id_code) for row_format in fdri_format.logic_block_format: row_size = sum([ major_format.frame_size * major_format.frame_count for major_format in row_format ]) expected_size += row_size rows.append( DataObject.create_packed( self.context, data_stream.read(row_size), XilinxFdriLogicRow, converter_args=(row_format, ), )) assert expected_size == len(data_bytes), \ "The number of bytes provided {} does not match the expected number of bytes {}".format( len(data_bytes), expected_size ) return XilinxFdriLogicBlock(rows)
def unpack(self, data_bytes): """ :param bytes data_bytes: :rtype: CustomXilinxHeaderModel """ assert len(data_bytes) == 16, \ "The header data is expected to contain 16 bytes" return CustomXilinxHeaderModel( DataObject.create_packed(self.context, data_bytes[:4], CustomXilinxHeaderPart1Interface), DataObject.create_packed( self.context, data_bytes[4:16], CustomXilinxHeaderPart2Interface, ), )
def _create_attribute_object( self, attribute_format, class_name, value, value_name, value_description, ): AttributeModel = type(str(class_name), (XilinxType1PayloadAttribute, ), {}) AttributeModel.__doc__ = attribute_format.description model = AttributeModel(int(value), value_name, value_description) return DataObject.create_unpacked(self.context, model, bit_size=attribute_format.bit_size)
def unpack(self, data_bytes): """ :param bytes data_bytes: :rtype: XilinxFdriPayload """ if self.context.id_code is None: raise ValueError( "The ID code for the targeted device has not been set on the bitstream context." ) fdri_format = self.context.format.get_fdri_format(self.context.id_code) expected_size = fdri_format.logic_block_size + fdri_format.bram_block_size + \ fdri_format.io_block_size + fdri_format.crc_size assert len(data_bytes) == expected_size, \ "The size of the config data ({}) does not match the expected size ({})".format( len(data_bytes), expected_size ) data_stream = io.BytesIO(data_bytes) return XilinxFdriPayload( DataObject.create_packed( self.context, data_stream.read(fdri_format.logic_block_size), XilinxFdriLogicBlock, ), DataObject.create_packed( self.context, data_stream.read(fdri_format.bram_block_size), XilinxFdriRAMBlockInterface, ), DataObject.create_packed( self.context, data_stream.read(fdri_format.io_block_size), XilinxFdriIOBlockInterface), DataObject.create_packed( self.context, data_stream.read(fdri_format.crc_size), XilinxFdriCRCInterface, ), )
def _create_type2_payload(self, data_stream, header): """ Unpack the payload for a type 2 packet :param io.BytesIO data_stream: :param XilinxCtypePacketHeader header: :rtype: Tuple[DataObject,DataObject] """ register_format = self._get_register_format(header) word_count_data = data_stream.read(4) word_count, = struct.unpack(">I", word_count_data) payload_size_object = DataObject.create_unpacked( self.context, WordCountValue(word_count), bytes=word_count_data) payload_data = data_stream.read((word_count + 2) * WORD_SIZE) # TODO: Remove this hack for the LX45T, it's got 2 FDRI packets, one is waaaaay too small. if register_format.name != "Fdri" or len(payload_data) < 500: return payload_size_object, DataObject.create_packed( self.context, payload_data, XilinxType2PayloadInterface, converter_args=(register_format, )) return payload_size_object, DataObject.create_packed( self.context, payload_data, XilinxFdriPayload)
def unpack(self, data_bytes): sync_marker = hex_to_bytes("AA995566") sync_marker_index = data_bytes.find(sync_marker) assert sync_marker_index >= 0, \ "The sync marker is not present in the provided bitstream data" assert sync_marker_index + len(sync_marker) < len(data_bytes) - 2, \ "The configuration data is expected to contain at least one word size worth of data" return XilinxBitstream( DataObject.create_packed(self.context, data_bytes[:sync_marker_index], XilinxBitstreamHeaderInterface), DataObject.create_packed( self.context, data_bytes[sync_marker_index:sync_marker_index + len(sync_marker)], XilinxBitstreamSyncMarkerInterface, ), DataObject.create_packed( self.context, data_bytes[sync_marker_index + len(sync_marker):], XilinxPacketsInterface, ))
def unpack(self, data_bytes): """ :param bytes data_bytes: :rtype: ArrayModel """ majors = [] data_stream = io.BytesIO(data_bytes) expected_size = 0 for major_format in self._row_format: major_size = major_format.frame_count * major_format.frame_size expected_size += major_size majors.append( DataObject.create_packed(self.context, data_stream.read(major_size), XilinxFdriLogicMajor, converter_args=(major_format, ))) assert expected_size == len(data_bytes), \ "The number of bytes provided {} does not match the expected number of bytes {}".format( len(data_bytes), expected_size ) return XilinxFdriLogicRow(majors)
def unpack(self, data_bytes): """ :param bytes data_bytes: :rtype: XilinxPackets """ packets = [] data_stream = io.BytesIO(data_bytes) previous_packet_type = 0 while data_stream.tell() < len(data_bytes): header_raw_data = data_stream.read(2) header = XilinxCtypePacketHeader.from_buffer_copy( bytearray([header_raw_data[0], header_raw_data[1], 0, 0])) is_done = False register_format = self._get_register_format(header) if header.type == 0: payload_object = None payload_size_object = None elif header.type == 1: payload_object, is_done = self._create_type1_payload( data_stream, header, register_format) payload_size_object = None elif header.type == 2: if previous_packet_type != 1: raise ValueError( "Unexpected packet type 2 after a packet type {}". format(previous_packet_type)) payload_size_object, payload_object = self._create_type2_payload( data_stream, header) else: raise ValueError( "Unexpected packet type {} while parsing the Xilinx bitstream" .format(header.type)) previous_packet_type = header.type raw_packet_data = header_raw_data if payload_size_object is not None: raw_packet_data += payload_size_object.get_bytes() if payload_object is not None: raw_packet_data += payload_object.get_bytes() header_object = DataObject.create_unpacked( self.context, model=XilinxPacketHeader( DataObject.create_unpacked( self.context, TypeValue(int(header.type), self._get_type_name(header.type)), 3, ), DataObject.create_unpacked( self.context, OpCodeValue(int(header.opcode), self._get_opcode_name(header.opcode)), 2, ), DataObject.create_unpacked( self.context, RegisterAddressValue(int(header.register_address), register_format.name), 6, ), DataObject.create_unpacked( self.context, WordCountValue(int(header.word_count)), 5, ), ), bytes=header_raw_data, ) packets.append( DataObject.create_unpacked( self.context, model=XilinxPacket( header_object, payload_size_object, payload_object, ), bytes=raw_packet_data, )) if is_done is True: packets.append( DataObject.create_packed( self.context, data_stream.read(), XilinxPacketsTail, )) break return XilinxPackets(packets)