aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2021-05-22 13:03:56 +0000
committers-ol <s+removethis@s-ol.nu>2021-05-22 13:03:56 +0000
commit7d9fd6018aae0b60bbff268f2d4428c34f2bd3e4 (patch)
treeb0176c467c42222c6b7b81c85e96fd15f08f42f8
parentdisable qemu bios (diff)
downloadsubv-7d9fd6018aae0b60bbff268f2d4428c34f2bd3e4.tar.gz
subv-7d9fd6018aae0b60bbff268f2d4428c34f2bd3e4.zip
more error reporting in format.py
-rwxr-xr-xformat.py67
-rw-r--r--subv.py21
2 files changed, 61 insertions, 27 deletions
diff --git a/format.py b/format.py
index e97fac2..d43f835 100755
--- a/format.py
+++ b/format.py
@@ -91,17 +91,18 @@ def default_slice(val, hi, lo):
>>> default_slice(('label[31:0]', 'imm12'), 11, 0)
Traceback (most recent call last):
...
- AssertionError: expected 12 bit slice
+ AssertionError: expected 12 bit slice, got label[31:0] (32 bit)
"""
parsed = subv.parse_reference(val)
if 'hi' not in parsed:
parsed['hi'] = hi
parsed['lo'] = lo
+ ref = '{label}[{hi}:{lo}]'.format(**parsed)
+
p_size = parsed['hi'] - parsed['lo'] + 1
- assert parsed['size'] == p_size, "expected {} bit slice".format(parsed['size'])
+ assert parsed['size'] == p_size, "expected {} bit slice, got {} ({} bit)".format(parsed['size'], ref, p_size)
- ref = '{label}[{hi}:{lo}]'.format(**parsed)
return (ref, *val[1:])
def slice_bit_or_ref(val, hi, lo):
@@ -155,7 +156,7 @@ def pack_u(instr):
>>> pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos[31:0]', 'imm20')])
Traceback (most recent call last):
...
- AssertionError: expected 20 bit slice
+ AssertionError: expected 20 bit slice, got pos[31:0] (32 bit)
"""
(op, rd, imm) = instr
op = bits.u(subv.untag(op), 7)
@@ -283,27 +284,43 @@ instr_map = {
def format(iter):
segment = None
- for line in iter:
- line = subv.parse(line)
-
- if segment == 'code' and line['type'] == 'instr':
- op = line['instr'][0]
- assert len(op) == 2, 'instruction without op label: {}'.format(op)
-
- (op, label) = op
- if label not in instr_map:
- raise ValueError("unknown instruction label: {}".format(label))
- (formatter, expected) = instr_map[label]
- if op != expected:
- raise ValueError("opcode {} doesn't match label {} (expected {})"
- .format(op, label, expected))
-
- line['instr'] = formatter(line['instr'])
- yield subv.format(line)
- else:
- if line['type'] == 'segment':
- segment = line['segment'][0]
- yield line['raw']
+ for line_no, raw_line in enumerate(iter, start=1):
+ try:
+ line = subv.parse(raw_line)
+ except AssertionError as e:
+ message = '''
+failed to format line:
+<input>:{} {}
+parsed as {}
+ '''.strip().format(line_no, raw_line.strip())
+ raise Exception(message) from e
+
+ try:
+ if segment == 'code' and line['type'] == 'instr':
+ op = line['instr'][0]
+ assert len(op) == 2, 'instruction without op label: {}'.format(op)
+
+ (op, label) = op
+ if label not in instr_map:
+ raise ValueError("unknown instruction label: {}".format(label))
+ (formatter, expected) = instr_map[label]
+ if op != expected:
+ raise ValueError("opcode {} doesn't match label {} (expected {})"
+ .format(op, label, expected))
+
+ line['instr'] = formatter(line['instr'])
+ yield subv.format(line)
+ else:
+ if line['type'] == 'segment':
+ segment = line['segment'][0]
+ yield line['raw']
+ except AssertionError as e:
+ message = '''
+failed to format line:
+<input>:{} {}
+parsed as {}
+ '''.strip().format(line_no, raw_line.strip(), subv.dump(line))
+ raise Exception(message) from e
if __name__ == '__main__':
import sys
diff --git a/subv.py b/subv.py
index 107f0e9..43bfa35 100644
--- a/subv.py
+++ b/subv.py
@@ -223,12 +223,16 @@ def untag(part, expect=None):
return part[0]
def format_part(part):
- """ oppposite of parse_part.
+ """ opposite of parse_part.
>>> format_part((0,))
'00'
>>> format_part((0x00,))
'00'
+ >>> format_part((16,))
+ '10'
+ >>> format_part((0x10,))
+ '10'
>>> format_part(('label', 'tag*'))
'label/tag*'
@@ -245,7 +249,7 @@ def format_part(part):
return '/'.join([str(p) for p in part])
def format(line):
- """ oppposite of parse.
+ """ opposite of parse.
>>> format({
... 'type': 'instr',
@@ -262,6 +266,19 @@ def format(line):
else:
raise NotImplementedError()
+def dump(line):
+ """ debug-friendly string representation of parsed lines.
+
+ >>> dump({
+ ... 'type': 'instr',
+ ... 'instr': [(255, 'op'), (0, 'subop', 'add'), (1, 'rd', 'x1'), ('label[11:0]', 'imm12')],
+ ... 'comment': "this does things."
+ ... })
+ "instr[(255, 'op'), (0, 'subop', 'add'), (1, 'rd', 'x1'), ('label[11:0]', 'imm12')]"
+ """
+
+ return '{}{}'.format(line['type'], line[line['type']])
+
def join_all(gen):
res = '\n'.join(gen)
return res