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 _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): """ :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)