diff options
author | Martin Braun <martin.braun@ettus.com> | 2021-08-23 18:05:21 +0200 |
---|---|---|
committer | Wade Fife <wade.fife@ettus.com> | 2021-08-24 09:45:36 -0500 |
commit | 6046e1a812ba2065d6ae13b4c4afdce8abc99d4f (patch) | |
tree | 94f4caa0ac5bab60e9e0eea05ef141a580baba50 /fpga/usrp3 | |
parent | 3111b4a230ce7534912600fe045114fed5c8ed6d (diff) | |
download | uhd-6046e1a812ba2065d6ae13b4c4afdce8abc99d4f.tar.gz uhd-6046e1a812ba2065d6ae13b4c4afdce8abc99d4f.tar.bz2 uhd-6046e1a812ba2065d6ae13b4c4afdce8abc99d4f.zip |
fpga: Fix Xilinx bitfile parser for Python 3
The script was previously only Python 2 compatible.
Python 2 support is now removed, so we don't maintain backwards
compatibility with Python 2.
This also fixes all linter warnings.
Diffstat (limited to 'fpga/usrp3')
-rwxr-xr-x | fpga/usrp3/tools/scripts/xil_bitfile_parser.py | 85 |
1 files changed, 54 insertions, 31 deletions
diff --git a/fpga/usrp3/tools/scripts/xil_bitfile_parser.py b/fpga/usrp3/tools/scripts/xil_bitfile_parser.py index cace9b4df..19c6b696a 100755 --- a/fpga/usrp3/tools/scripts/xil_bitfile_parser.py +++ b/fpga/usrp3/tools/scripts/xil_bitfile_parser.py @@ -1,4 +1,9 @@ #!/usr/bin/env python3 +""" +Parser for Xilinx bitfiles. + +Reads metadata from Xilinx bitfile headers. +""" import argparse import os @@ -7,7 +12,8 @@ import struct import re # Parse command line options -def get_options(): +def get_args(): + """Run argparser""" parser = argparse.ArgumentParser(description='Parser for the Xilinx FPGA Bitfile') parser.add_argument("bitfile", help="Input bitfile path") parser.add_argument("--bin_out", help="Output bin file path") @@ -20,60 +26,77 @@ def get_options(): sys.exit(1) return args -short = struct.Struct('>H') -ulong = struct.Struct('>I') -KEYNAMES = {'a':'design_name', 'b':'part_name', 'c':'date', 'd':'time'} - -# Parse bitfile def parse_bitfile(bitfile_bytes): + """ + Parse bitfile + """ + short = struct.Struct('>H') + ulong = struct.Struct('>I') + keynames = {'a': 'design_name', 'b': 'part_name', 'c': 'date', 'd': 'time'} + header = dict() ptr = 0 #Field 1 - if short.unpack(bitfile_bytes[ptr:ptr+2])[0] == 9 and ulong.unpack(bitfile_bytes[ptr+2:ptr+6])[0] == 0x0ff00ff0: + if short.unpack(bitfile_bytes[ptr:ptr+2])[0] == 9 and \ + ulong.unpack(bitfile_bytes[ptr+2:ptr+6])[0] == 0x0ff00ff0: #Headers ptr += short.unpack(bitfile_bytes[ptr:ptr+2])[0] + 2 ptr += short.unpack(bitfile_bytes[ptr:ptr+2])[0] + 1 #Fields a-d - for keynum in range(0, 4): - key = bitfile_bytes[ptr]; ptr += 1 - val_len = short.unpack(bitfile_bytes[ptr:ptr+2])[0]; ptr += 2 - val = bitfile_bytes[ptr:ptr+val_len]; ptr += val_len - header[KEYNAMES[key]] = str(val).rstrip('\0') + for _ in range(0, 4): + key = chr(bitfile_bytes[ptr]) + ptr += 1 + val_len = short.unpack(bitfile_bytes[ptr:ptr+2])[0] + ptr += 2 + val = bitfile_bytes[ptr:ptr+val_len] + ptr += val_len + header[keynames[key]] = val.decode('ascii').rstrip('\0') #Field e ptr += 1 - length = ulong.unpack(bitfile_bytes[ptr:ptr+4])[0]; ptr += 4 + length = ulong.unpack(bitfile_bytes[ptr:ptr+4])[0] + ptr += 4 header['bitstream_len'] = length header['header_len'] = ptr data = bitfile_bytes[ptr:ptr+length] return (header, data) - else: - raise Exception('Bitfile header validation failed!') + raise Exception('Bitfile header validation failed!') -# Flip 32-bit endianess def flip32(data): - sl = struct.Struct('<I') - sb = struct.Struct('>I') - b = memoryview(data) - d = bytearray(len(data)) + """ + Flip 32-bit endianness + """ + le32_struct = struct.Struct('<I') + be32_struct = struct.Struct('>I') + data_flipped = bytearray(len(data)) for offset in range(0, len(data), 4): - sb.pack_into(d, offset, sl.unpack_from(b, offset)[0]) - return d + be32_struct.pack_into( + data_flipped, + offset, + le32_struct.unpack_from(memoryview(data), offset)[0]) + return data_flipped def main(): - args = get_options(); + """GoGoGo""" + args = get_args() with open(args.bitfile, 'rb') as bit_file: # Parse bytes into a header map and data buffer (header, data) = parse_bitfile(bit_file.read()) # Print bitfile info if args.info: - m = re.search('(.+);UserID=(.+);COMPRESS=(.+);Version=(.+)', header['design_name']) - if m: - print('Design Name: ' + m.group(1)) - print('User ID: ' + m.group(2)) - print('Compression: ' + m.group(3)) - print('Vivado Version: ' + m.group(4)) - else: - print('Design Name: ' + header['design_name']) + keynames = { + 'COMPRESS': 'Compression: ', + 'UserID': 'User ID: ', + 'Version': 'Vivado Version: '} + name_fields = header['design_name'].split(';') + for field in name_fields: + mobj = re.search('(.+)=(.+)', field) + if mobj: + if mobj.group(1) in keynames: + print(keynames[mobj.group(1)] + mobj.group(2)) + else: + print(mobj.group(1) + ': ' + mobj.group(2)) + else: + print('Design Name: ' + field) print('Part Name: ' + header['part_name']) print('Datestamp: ' + header['date'] + ' ' + header['time']) print('Bitstream Size: ' + str(header['bitstream_len'])) |