-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add intel_hex parser to ease integration in tb:
- parse intel_hex - calculate addresses - can reshape data width to fit mem width - can select a section of the program - can output to a memh file for verilog $readmemh
- Loading branch information
1 parent
9e0b9fc
commit 0be48d6
Showing
4 changed files
with
185 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
#!/usr/bin/env python3 | ||
# coding: utf-8 | ||
|
||
import os | ||
import sys | ||
import argparse | ||
|
||
sys.path.append(os.environ["REFLOW"]) | ||
|
||
import common.relog as relog | ||
|
||
|
||
def check_checksum(line: str) -> bool: | ||
""" | ||
sum modulo 256 of all pair of bytes | ||
should be 0 | ||
Args: | ||
line (str): text in hexa format | ||
Return: | ||
bool | ||
""" | ||
values = (int(c, 16) if i % 2 else int(c, 16) << 4 for i, c in enumerate(line[1:])) | ||
return sum(values) % 256 == 0 | ||
|
||
|
||
def line_split(line: str): | ||
""" | ||
generate the different fields from | ||
the line of the file | ||
Args: | ||
line (str): text in hexa format | ||
Return: | ||
- byte count | ||
- both address bytes | ||
- record type | ||
- all data bytes | ||
""" | ||
byte_count = int(line[1:3], 16) | ||
both_addr = line[3:7] | ||
record_type = line[7:9] | ||
data = line[9:-2] | ||
return (byte_count, both_addr, record_type, data) | ||
|
||
|
||
def parse(file: str): | ||
""" | ||
generate an hex/bin file from file into out | ||
""" | ||
if not os.path.exists(file): | ||
relog.error("File Not Found: %s" % file) | ||
return | ||
segment = 0 | ||
with open(file, "r+") as fp: | ||
for i, line in enumerate(fp): | ||
line = line.strip() | ||
if line[0] != ":": | ||
relog.error("missing colon at line %d" % (i+1)) | ||
if len(line) < 11: | ||
relog.error("line %d is too short" % (i+1)) | ||
if not check_checksum(line): | ||
relog.error("checksum invalid at line %d" % (i+1)) | ||
# split fields | ||
byte_count, addr, record_type, data = line_split(line) | ||
# update | ||
address = segment + int(addr, 16) | ||
# is data | ||
if record_type == "00": | ||
yield (address, data) | ||
# is eof | ||
elif record_type == "01": | ||
if byte_count != "00" and addr != "0000": | ||
relog.error("wrong EOF should be 00000001FF at line %d" % (i+1)) | ||
return | ||
# is extended address for up to 1MB | ||
elif record_type == "02": | ||
segment = int(data, 16) << 4 | ||
# is extended address for up to 4GB | ||
elif record_type == "04": | ||
segment = int(data, 16) << 16 | ||
# precise start address | ||
elif record_type == "03": | ||
pass | ||
elif record_type == "05": | ||
pass | ||
return | ||
|
||
|
||
def reshape(data: str, width: int): | ||
if width > 0: | ||
for addr, datum in data: | ||
count = len(datum) // width | ||
if count == 1: | ||
yield (addr, datum) | ||
elif count == 0: | ||
padding = ''.join(['0'] * (width - len(datum))) | ||
yield (addr, ''.join([padding, datum])) | ||
else: | ||
for i in range(count): | ||
yield (addr + i, datum[i * width:(i + 1) * width]) | ||
else: | ||
for d in data: | ||
yield d | ||
return | ||
|
||
|
||
def store(data, | ||
out: str, | ||
format: str = "hex", | ||
start: str = "0000", | ||
size: int = 2**16, | ||
width: int = 4): | ||
""" | ||
""" | ||
ZERO = ''.join(['0'] * width) | ||
db = dict(reshape(data, width)) | ||
if size < 1: | ||
size = max(db.keys()) - start + 1 | ||
print("%x +: %d" % (start, size)) | ||
if isinstance(out, str): | ||
with open(out, "w+") as fp: | ||
for addr in range(start, start + size, 1): | ||
fp.write("%s\n" % db.get(addr, ZERO)) | ||
else: | ||
for addr in range(start, start + size, 1): | ||
out.write("%X %s\n" % (addr, db.get(addr, ZERO))) | ||
|
||
|
||
def main(file: str, | ||
out: str, | ||
format: str = "hex", | ||
start: str = "0000", | ||
size: int = 2**16, | ||
width: int = 16): | ||
store( | ||
parse(file), | ||
out, | ||
format, | ||
start, | ||
size, | ||
width | ||
) | ||
|
||
|
||
def any_of(chars: str, text: str): | ||
return any((c in text for c in chars)) | ||
|
||
|
||
if __name__ == "__main__": | ||
parser = argparse.ArgumentParser( | ||
description=( | ||
"intel_hex verify the validity of an" | ||
"intel_hex file and transform it into" | ||
"a readable verilog hexa or binary file" | ||
) | ||
) | ||
parser.add_argument("-i", "--input", help="intel_hex input file") | ||
parser.add_argument("-s", "--start-address", help="memory start address", default="0", type=str) | ||
parser.add_argument("-l", "--length", help="length of the memory", default=-1, type=int) | ||
parser.add_argument("-w", "--width", help="width of memory row in byte", default=-1, type=int) | ||
parser.add_argument("-o", "--output", help="output file", default=sys.stdout) | ||
parser.add_argument( | ||
"-f", "--format", help="desired output format hex or bin", default="hex" | ||
) | ||
args = parser.parse_args() | ||
# parse start address | ||
if any_of("ABCDEFabcdefxh", args.start_address): | ||
args.start_address = args.start_address.replace('x', '') | ||
args.start_address = args.start_address.replace('h', '') | ||
args.start_address = int(args.start_address, 16) | ||
else: | ||
args.start_address = int(args.start_address, 10) | ||
main(args.input, args.output, args.format, args.start_address, args.length, args.width) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
:10C00000576F77212044696420796F7520726561CC | ||
:10C010006C6C7920676F207468726F756768206137 | ||
:10C020006C6C20746869732074726F75626C652023 | ||
:10C03000746F207265616420746869732073747210 | ||
:04C040007696E67397 | ||
:00000001FF |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
:020000022BC011 | ||
:1012340054686973207061727420697320696E2028 | ||
:0D12440061206C6F77207365676D656E74B7 | ||
:020000027F007D | ||
:1080000054686973207061727420697320696E20EE | ||
:108010007468652068696768207365676D656E744C | ||
:00000001FF |