tillitis-key/hw/production_test/pybin2nvcm.py
Matt Mets 12f6575afd
Update raw_usb interface
* Update raw_usb interface to the 0200 version
* Rename ice* commands to be less confusing
* Split production test into a runner script and test library
* Add continuous randomized test for test library
* Speed improvements for nvcm commands
2023-03-21 14:38:28 +01:00

85 lines
2.2 KiB
Python
Executable File

#!/usr/bin/env python
""" bistream to NVCM command conversion is based on majbthrd's work
in https://github.com/YosysHQ/icestorm/pull/272
"""
def pybin2nvcm(bitstream: bytes) -> list[str]:
"""Convert an ice40 bitstream into an NVCM program
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
"""
# 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):
raise ValueError('Preamble not found')
print(f'Found preamable at {origin:08x}')
# 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)
row_str = f'02{nvcm_addr:06x}{row.hex()}'
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:
data = f_in.read()
cmds = pybin2nvcm(data)
with open(args.outfile, 'w', encoding='utf-8') as f_out:
for cmd in cmds:
f_out.write(cmd)
f_out.write('\n')