tillitis-key/hw/production_test/pybin2nvcm.py

85 lines
2.2 KiB
Python
Raw Normal View History

2023-03-02 17:43:26 -05:00
#!/usr/bin/env python
2023-03-06 06:41:21 -05:00
""" bistream to NVCM command conversion is based on majbthrd's work
in https://github.com/YosysHQ/icestorm/pull/272
"""
2023-03-02 17:43:26 -05:00
def pybin2nvcm(bitstream: bytes) -> list[str]:
2023-03-06 06:41:21 -05:00
"""Convert an ice40 bitstream into an NVCM program
2023-03-02 17:43:26 -05:00
2023-03-06 06:41:21 -05:00
The NVCM format is a set of commands that are run against the
NVCM state machine, which instruct the state machine to write
the bitstream into the NVCM. It's somewhat convoluted!
Keyword arguments:
bitstream -- Bitstream to convert into NVCM format
"""
2023-03-02 17:43:26 -05:00
# ensure that the file starts with the correct bistream preamble
for origin in range(0, len(bitstream)):
if bitstream[origin:origin + 4] == bytes.fromhex('7EAA997E'):
break
if origin == len(bitstream):
2023-03-06 06:41:21 -05:00
raise ValueError('Preamble not found')
2023-03-02 17:43:26 -05:00
2023-03-06 06:41:21 -05:00
print(f'Found preamable at {origin:08x}')
2023-03-02 17:43:26 -05:00
# there might be stuff in the header with vendor tools,
# but not usually in icepack produced output, so ignore it for now
rows = []
rows.append('06')
for pos in range(origin, len(bitstream), 8):
row = bitstream[pos:pos + 8]
# pad out to 8-bytes
row += b'\0' * (8 - len(row))
if row == bytes(8):
# skip any all-zero entries in the bistream
continue
# NVCM addressing is very weird
addr = pos - origin
nvcm_addr = int(addr / 328) * 4096 + (addr % 328)
2023-03-06 06:41:21 -05:00
row_str = f'02{nvcm_addr:06x}{row.hex()}'
2023-03-02 17:43:26 -05:00
row_str = ' '.join([row_str[i:i + 2]
for i in range(0, len(row_str), 2)]) + ' '
rows.append(row_str)
rows.append('04')
return rows
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('infile',
type=str,
help='input bin file')
parser.add_argument('outfile',
type=str,
help='output nvcm file')
args = parser.parse_args()
with open(args.infile, 'rb') as f_in:
2023-03-06 06:41:21 -05:00
data = f_in.read()
2023-03-02 17:43:26 -05:00
cmds = pybin2nvcm(data)
2023-03-02 17:43:26 -05:00
2023-03-06 06:41:21 -05:00
with open(args.outfile, 'w', encoding='utf-8') as f_out:
2023-03-02 17:43:26 -05:00
for cmd in cmds:
f_out.write(cmd)
f_out.write('\n')