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