fpga-bit-to-bin.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #!/usr/bin/python3
  2. # copied from https://github.com/topic-embedded-products/meta-topic/blob/master/recipes-bsp/fpga/fpga-bit-to-bin/fpga-bit-to-bin.py
  3. import argparse
  4. import struct
  5. def flip32(data):
  6. sl = struct.Struct("<I")
  7. sb = struct.Struct(">I")
  8. try:
  9. b = buffer(data)
  10. except NameError:
  11. # Python 3 does not have 'buffer'
  12. b = data
  13. d = bytearray(len(data))
  14. for offset in range(0, len(data), 4):
  15. sb.pack_into(d, offset, sl.unpack_from(b, offset)[0])
  16. return d
  17. parser = argparse.ArgumentParser(description="Convert FPGA bit files to raw bin format suitable for flashing")
  18. parser.add_argument("-f", "--flip", dest="flip", action="store_true", default=False, help="Flip 32-bit endianess (needed for Zynq)")
  19. parser.add_argument("bitfile", help="Input bit file name")
  20. parser.add_argument("binfile", help="Output bin file name")
  21. args = parser.parse_args()
  22. short = struct.Struct(">H")
  23. ulong = struct.Struct(">I")
  24. bitfile = open(args.bitfile, "rb")
  25. l = short.unpack(bitfile.read(2))[0]
  26. if l != 9:
  27. raise Exception("Missing <0009> header (0x%x), not a bit file" % l)
  28. bitfile.read(l)
  29. l = short.unpack(bitfile.read(2))[0]
  30. d = bitfile.read(l)
  31. if d != b"a":
  32. raise Exception("Missing <a> header, not a bit file")
  33. l = short.unpack(bitfile.read(2))[0]
  34. d = bitfile.read(l)
  35. print("Design name: %s" % d)
  36. # If bitstream is a partial bitstream, get some information from filename and header
  37. if b"PARTIAL=TRUE" in d:
  38. print("Partial bitstream")
  39. partial = True
  40. # Get node_nr from filename (last (group of) digits)
  41. for i in range(len(args.bitfile) - 1, 0, -1):
  42. if args.bitfile[i].isdigit():
  43. pos_end = i + 1
  44. for j in range(i - 1, 0, -1):
  45. if not args.bitfile[j].isdigit():
  46. pos_start = j + 1
  47. break
  48. break
  49. if pos_end != 0 and pos_end != 0:
  50. node_nr = int(args.bitfile[pos_start:pos_end])
  51. else:
  52. node_nr = 0
  53. print("NodeID: %s" % node_nr)
  54. # Get 16 least significant bits of UserID in design name
  55. pos_start = d.find(b"UserID=")
  56. if pos_start != -1:
  57. pos_end = d.find(b";", pos_start)
  58. pos_start = pos_end - 4
  59. userid = int(d[pos_start:pos_end], 16)
  60. print("UserID: 0x%x" % userid)
  61. else:
  62. print("Full bitstream")
  63. partial = False
  64. node_nr = 0
  65. KEYNAMES = {b"b": "Partname", b"c": "Date", b"d": "Time"}
  66. while 1:
  67. k = bitfile.read(1)
  68. if not k:
  69. bitfile.close()
  70. raise Exception("unexpected EOF")
  71. elif k == b"e":
  72. l = ulong.unpack(bitfile.read(4))[0]
  73. print("Found binary data: %s" % l)
  74. d = bitfile.read(l)
  75. if args.flip:
  76. print("Flipping data...")
  77. d = flip32(d)
  78. # Open bin file
  79. binfile = open(args.binfile, "wb")
  80. # Write header if it is a partial
  81. if partial:
  82. binfile.write(struct.pack("B", 0))
  83. binfile.write(struct.pack("B", node_nr))
  84. binfile.write(struct.pack(">H", userid))
  85. # Write the converted bit-2-bin data
  86. print("Writing data...")
  87. binfile.write(d)
  88. binfile.close()
  89. break
  90. elif k in KEYNAMES:
  91. l = short.unpack(bitfile.read(2))[0]
  92. d = bitfile.read(l)
  93. print(KEYNAMES[k], d)
  94. else:
  95. print("Unexpected key: %s" % k)
  96. l = short.unpack(bitfile.read(2))[0]
  97. d = bitfile.read(l)
  98. bitfile.close()