diff options
Diffstat (limited to 'fpga/usrp3/lib/io_port2/create-lvbitx.py')
-rw-r--r-- | fpga/usrp3/lib/io_port2/create-lvbitx.py | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/io_port2/create-lvbitx.py b/fpga/usrp3/lib/io_port2/create-lvbitx.py new file mode 100644 index 000000000..ea8231292 --- /dev/null +++ b/fpga/usrp3/lib/io_port2/create-lvbitx.py @@ -0,0 +1,153 @@ +#!/usr/bin/python +""" +Generate lvbitx from template and bitfile +""" + +from __future__ import print_function +from xml.etree import ElementTree +import optparse +import base64 +import os +from hashlib import md5 + +def to_native_str(str_or_bstr): + """ + Returns a native string, regardless of the input string type (binary or + UTF-8), and the Python version (2 or 3). + Note that the native string type is actually not the same in Python 2 and + 3: In the former, it's a binary string, in the latter, it's Unicode. + >>> to_native_str(b'foo') + 'foo' + >>> to_native_str(u'foo') + 'foo' + """ + if isinstance(str_or_bstr, str): + return str_or_bstr + try: + # This will either fail because we're running Python 2 (which doesn't) + # have the encoding argument) or because we're not passing in a bytes- + # like object (e.g., an integer) + return str(str_or_bstr, encoding='ascii') + except TypeError: + return str(str_or_bstr) + +def get_parser(): + """Parse args.""" + parser = optparse.OptionParser() + parser.add_option( + "--device", + type="string", + dest="device_type", + help="Device Type. (Has to match the LVFPGA target plugin)", + default=None + ) + parser.add_option( + "--input-bin", + type="string", + dest="input_bin", + help="Path to bin file that needs to be merged with the LVBITX before exporting", + default=None + ) + parser.add_option( + "--output-bin", + type="string", + dest="output_bin", + help="Create a binary configuration bitstream", + default=None + ) + parser.add_option( + "--output-lvbitx", + type="string", + dest="output_lvbitx_path", + help="Output path for autogenerated LVBITX file", + default=None + ) + parser.add_option( + "--output-src-path", + type="string", + dest="output_src_path", + help="Output path for autogenerated src file", + default=None + ) + return parser + +def main(): + """Go, go, go!""" + parser = get_parser() + options, args = parser.parse_args() + # Args + if len(args) < 1: + print('ERROR: Please specify the input LVBITX file name') + parser.print_help() + exit(1) + + lvbitx_filename = args[0] + input_filename = os.path.abspath(lvbitx_filename) + + if not os.path.isfile(input_filename): + print("ERROR: LVBITX File `{}' could not be accessed or is not a file." + .format(input_filename)) + parser.print_help() + exit(1) + + if options.input_bin is not None and \ + not os.path.isfile(os.path.abspath(options.input_bin)): + print("ERROR: FPGA Bin File `{}' could not be accessed or is not a file." + .format(options.input_bin)) + parser.print_help() + exit(1) + + if options.output_lvbitx_path is not None and \ + input_filename == options.output_lvbitx_path: + print('ERROR: Input and output LVBITX files were the same. ' + 'Choose a difference input or output file.') + parser.print_help() + exit(1) + + # Get XML Tree Node + tree = ElementTree.parse(input_filename) + root = tree.getroot() + + # Update device type + if options.device_type is not None: + root.find('Project').find('TargetClass').text += '; ' + options.device_type + + # Merge bitstream into LVBITX + if options.input_bin is not None: + with open(os.path.abspath(options.input_bin), 'rb') as bin_file: + bitstream = bin_file.read() + bitstream_md5 = md5(bitstream).hexdigest() + bitstream_b64 = base64.b64encode(bitstream) + bitstream_b64_lb = b'\n'.join([ + bitstream_b64[i:i+76] + for i in range(0, len(bitstream_b64), 76) + ]) + b'\n' + root.find('Bitstream').text = to_native_str(bitstream_b64_lb) + root.find('BitstreamMD5').text = bitstream_md5 + + # Write BIN file + bitstream = base64.b64decode(root.find('Bitstream').text) + if options.output_lvbitx_path is not None \ + and md5(bitstream).hexdigest() != root.find('BitstreamMD5').text: + print('ERROR: The MD5 sum for the output LVBITX was incorrect. ' + 'Make sure that the bitstream in the input LVBITX or BIN file is valid.') + exit(1) + + if options.output_bin is not None: + fpga_bin_file = open(options.output_bin, 'wb') + fpga_bin_file.write(bitstream) + fpga_bin_file.close() + + # Save LVBITX + if options.output_lvbitx_path is not None: + with open(options.output_lvbitx_path, 'wb') as lvbitx_file: + tree.write( + lvbitx_file, + encoding="utf-8", + xml_declaration=True, + default_namespace=None, + method="xml" + ) + +if __name__ == "__main__": + main() |