aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2021-05-25 13:13:58 +0000
committers-ol <s+removethis@s-ol.nu>2021-05-25 13:13:58 +0000
commit9de28da73ba6a50f773804fd3a4c0beb342ffc3d (patch)
tree5c91df552aa5f5ae4f79d7d166a98043652409d3
parentimplement LabelRef (diff)
downloadsubv-9de28da73ba6a50f773804fd3a4c0beb342ffc3d.tar.gz
subv-9de28da73ba6a50f773804fd3a4c0beb342ffc3d.zip
use new bits in format.py
-rwxr-xr-xformat.py209
-rw-r--r--subv.py4
2 files changed, 107 insertions, 106 deletions
diff --git a/format.py b/format.py
index 58b7708..385c632 100755
--- a/format.py
+++ b/format.py
@@ -35,39 +35,40 @@ instruction.
... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12
... 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12
... # jump back up to the top
-... 6f/jal 0/rd/x0 main/off20
+... 6f/jal 0/rd/x0 main/off21
... '''[1:-1]))))
== code 0x80000000
main:
# load 0x10010000 (UART0) into t0
37/7 05/5 10010/20
# store 0x48 (H) in UART0+0
-13/7 06/5 00/3 00/5 48/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/7 06/5 0/3 00/5 048/12
+23/7 00/5 2/3 05/5 06/5 00/7
# store 0x65 (e) in UART0+0
-13/7 06/5 00/3 00/5 65/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/7 06/5 0/3 00/5 065/12
+23/7 00/5 2/3 05/5 06/5 00/7
# store 0x6c (l) in UART0+0
-13/7 06/5 00/3 00/5 6c/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/7 06/5 0/3 00/5 06c/12
+23/7 00/5 2/3 05/5 06/5 00/7
# store 0x6c (l) in UART0+0
-13/7 06/5 00/3 00/5 6c/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/7 06/5 0/3 00/5 06c/12
+23/7 00/5 2/3 05/5 06/5 00/7
# store 0x6f (o) in UART0+0
-13/7 06/5 00/3 00/5 6f/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/7 06/5 0/3 00/5 06f/12
+23/7 00/5 2/3 05/5 06/5 00/7
# store 0x0a (\\n) in UART0+0
-13/7 06/5 00/3 00/5 0a/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/7 06/5 0/3 00/5 00a/12
+23/7 00/5 2/3 05/5 06/5 00/7
# jump back up to the top
-6f/7 00/5 main[19:12]/off8 main[11:11]/off1 main[10:1]/off10 main[20:20]/off1
+6f/7 00/5 main/off21/[19:12] main/off21/[11:11] main/off21/[10:1] main/off21/[20:20]
"""
-from operator import __and__
-from functools import reduce
import subv
import bits
+def _test_format(words):
+ return ' '.join(map(str, words))
+
def ref_slice(ref, hi, lo):
if hi < lo:
raise ValueError("cant slice reverse range")
@@ -81,87 +82,86 @@ def ref_slice(ref, hi, lo):
'size': hi - lo + 1,
}
+def sign_trunc(val, size):
+ """ truncate and sign-shrink a number literal.
+
+ >>> sign_trunc(bits.i(4, 32), 8)
+ Bitfield(0x4, 8)
+ >>> sign_trunc(bits.i(-4, 32), 8)
+ Bitfield(0xfc, 8)
+ >>> sign_trunc(bits.i(0x11ff, 32), 8)
+ Bitfield(0x7f, 8)
+ >>> sign_trunc(bits.i(-0x11ff, 32), 8)
+ Bitfield(0x81, 8)
+ """
+ sign = val[val.size-1]
+ rest = val[size-2:0]
+ return sign & rest
+
+global_slice = slice
def default_slice(val, hi, lo):
""" add a default slice spec to labels if missing.
>>> default_slice(('label', 'imm12'), 12, 1)
- ('label[12:1]', 'imm12')
+ LabelRef('label', 0, ('imm', 12), 12:1)
>>> default_slice(('label-4', 'imm12'), 12, 1)
- ('label-4[12:1]', 'imm12')
- >>> default_slice(('label[14:3]', 'imm12'), 12, 1)
- ('label[14:3]', 'imm12')
- >>> default_slice(('label+4[14:3]', 'imm12'), 12, 1)
- ('label+4[14:3]', 'imm12')
- >>> default_slice(('label[14:3]', 'imm12', 'extra'), 12, 1)
- ('label[14:3]', 'imm12', 'extra')
- >>> default_slice(('label[31:0]', 'imm12'), 11, 0)
+ LabelRef('label', -4, ('imm', 12), 12:1)
+ >>> default_slice(('label', 'imm12', '[14:3]'), 12, 1)
+ LabelRef('label', 0, ('imm', 12), 14:3)
+ >>> default_slice(('label+4', 'imm12', '[14:3]'), 12, 1)
+ LabelRef('label', 4, ('imm', 12), 14:3)
+ >>> default_slice(('label', 'imm12', '[14:3]'), 12, 1)
+ LabelRef('label', 0, ('imm', 12), 14:3)
+ >>> default_slice(('label', 'imm12', '[31:0]'), 11, 0)
Traceback (most recent call last):
...
- AssertionError: expected 12 bit slice, got label[31:0] (32 bit)
+ AssertionError: expected 12 bit slice, got label/imm12/[31:0]
"""
- parsed = subv.parse_reference(val)
- if 'hi' not in parsed:
- parsed['hi'] = hi
- parsed['lo'] = lo
- ref = subv.format_reference(parsed)
+ if len(val) == 3:
+ label_offset, mode, slice = val
+ elif len(val) == 2:
+ label_offset, mode = val
+ slice = global_slice(hi, lo)
+ else:
+ raise ValueError("expected label reference")
- p_size = parsed['hi'] - parsed['lo'] + 1
- assert parsed['size'] == p_size, "expected {} bit slice, got {} ({} bit)".format(parsed['size'], ref[0], p_size)
+ import re
- return ref
+ ref_re = re.compile(r'^([^\[+-]+)(?:([+-]\d+))?$')
+ slice_re = re.compile(r'^\[(\d+):(\d+)]$')
-def slice_bit_or_ref(val, hi, lo):
- """ bit.slice but for bitfields and label references.
+ match = ref_re.match(label_offset)
+ assert match, ValueError("invalid label reference")
+ label, offset = match.group(1), int(match.group(2) or 0)
- >>> slice_bit_or_ref(('label[31:0]', 'imm32'), 12, 1)
- ('label[12:1]', 'imm12')
- >>> slice_bit_or_ref(('label[31:0]', 'off32'), 11, 0)
- ('label[11:0]', 'off12')
- >>> slice_bit_or_ref(('label[31:0]', 'off32'), 31, 12)
- ('label[31:12]', 'off20')
- >>> slice_bit_or_ref(('label[11:0]', 'imm12', 'extra'), 15, 4)
- Traceback (most recent call last):
- ...
- AssertionError: cant slice outside of bounds
- >>> slice_bit_or_ref(('label', 'imm12'), 12, 1)
- Traceback (most recent call last):
- ...
- AssertionError: cant slice label w/o bounds
- """
- if isinstance(val, bits.Bitfield):
- return val[hi:lo]
+ if isinstance(slice, str):
+ match = slice_re.match(slice)
+ assert match, ValueError("invalid slice syntax")
+ a, b = match.groups()
+ slice = global_slice(int(a), int(b))
- ref = subv.parse_reference(val)
- assert 'hi' in ref, "cant slice label w/o bounds"
+ ref = bits.LabelRef(label, offset, mode, slice)
- sz = hi - lo
- lo = ref['lo'] + lo
- hi = lo + sz
- assert hi <= ref['hi'], "cant slice outside of bounds"
-
- ref['hi'] = hi
- ref['lo'] = lo
- ref['size'] = sz + 1
- main = '{label}[{hi}:{lo}]'.format(**ref)
- field = '{mode}{size}'.format(**ref)
- return (main, field, *val[2:])
+ expected = hi - lo + 1
+ assert expected == ref.size, ValueError("expected {} bit slice, got {}".format(expected, ref))
+ return ref
def pack_u(instr):
""" verify & pack U-type instructions.
- >>> pack_u([(0x37, 'lui'), (5, 'rd', 't0'), (0x10010, 'imm20')])
- [Bitfield(0x37, 7), Bitfield(0x5, 5), Bitfield(0x10010, 20)]
+ >>> _test_format(pack_u([(0x37, 'lui'), (5, 'rd', 't0'), (0x10010, 'imm20')]))
+ '37/7 05/5 10010/20'
- >>> pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos', 'imm20')])
- [Bitfield(0x37, 7), Bitfield(0x5, 5), ('pos[31:12]', 'imm20')]
+ >>> _test_format(pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos', 'imm20')]))
+ '37/7 05/5 pos/imm20/[31:12]'
- >>> pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos[19:0]', 'imm20')])
- [Bitfield(0x37, 7), Bitfield(0x5, 5), ('pos[19:0]', 'imm20')]
+ >>> _test_format(pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos', 'imm20', '[19:0]')]))
+ '37/7 05/5 pos/imm20/[19:0]'
- >>> pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos[31:0]', 'imm20')])
+ >>> _test_format(pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos', 'imm20', '[31:0]')]))
Traceback (most recent call last):
...
- AssertionError: expected 20 bit slice, got pos[31:0] (32 bit)
+ AssertionError: expected 20 bit slice, got pos/imm20/[31:0]
"""
(op, rd, imm) = instr
op = bits.u(subv.untag(op), 7)
@@ -176,11 +176,11 @@ def pack_u(instr):
def pack_i(instr):
""" verify & pack I-type instructions.
- >>> reduce(__and__, pack_i([(0x13, 'opi'), (0, 'subop', 'add'), (6, 'rd', 't1'), (0, 'rs', 'x0'), (101, 'imm12')]))
- Bitfield(0x26600065, 32)
+ >>> _test_format(pack_i([(0x13, 'opi'), (0, 'subop', 'add'), (6, 'rd', 't1'), (0, 'rs', 'x0'), (0x65, 'imm12')]))
+ '13/7 06/5 0/3 00/5 065/12'
- >>> pack_i([(0x13, 'opi'), (0, 'subop', 'add'), (6, 'rd', 't1'), (0, 'rs', 'x0'), ('label', 'imm12')])
- [Bitfield(0x13, 7), Bitfield(0x6, 5), Bitfield(0x0, 3), Bitfield(0x0, 5), ('label[11:0]', 'imm12')]
+ >>> _test_format(pack_i([(0x13, 'opi'), (0, 'subop', 'add'), (6, 'rd', 't1'), (0, 'rs', 'x0'), ('label', 'imm12')]))
+ '13/7 06/5 0/3 00/5 label/imm12/[11:0]'
"""
(op, sub, rd, rs, imm) = instr
op = bits.u(subv.untag(op), 7)
@@ -197,11 +197,11 @@ def pack_i(instr):
def pack_s(instr):
""" verify & pack S-type instructions.
- >>> reduce(__and__, pack_s([(0x23, 'store'), (2, 'subop', 'word'), (5, 'rs', 't0'), (6, 'rs', 't1'), (0, 'off12')]))
- Bitfield(0x46045300, 32)
+ >>> _test_format(pack_s([(0x23, 'store'), (2, 'subop', 'word'), (5, 'rs', 't0'), (6, 'rs', 't1'), (0, 'off12')]))
+ '23/7 00/5 2/3 05/5 06/5 00/7'
- >>> pack_s([(0x23, 'store'), (2, 'subop', 'word'), (5, 'rs', 't0'), (6, 'rs', 't1'), ('home', 'off12')])
- [Bitfield(0x23, 7), ('home[4:0]', 'off5'), Bitfield(0x2, 3), Bitfield(0x5, 5), Bitfield(0x6, 5), ('home[11:5]', 'off7')]
+ >>> _test_format(pack_s([(0x23, 'store'), (2, 'subop', 'word'), (5, 'rs', 't0'), (6, 'rs', 't1'), ('home', 'off12')]))
+ '23/7 home/off12/[4:0] 2/3 05/5 06/5 home/off12/[11:5]'
"""
(op, sub, rs1, rs2, imm) = instr
op = bits.u(subv.untag(op), 7)
@@ -214,21 +214,21 @@ def pack_s(instr):
else:
imm = bits.i(subv.untag(imm, 'off12'), 12)
- imm_lo = slice_bit_or_ref(imm, 4, 0) # + ('off[4:0]',)
- imm_hi = slice_bit_or_ref(imm, 11, 5) # + ('off[11:5]',)
+ imm_lo = imm[4:0]
+ imm_hi = imm[11:5]
return [op, imm_lo, sub, rs1, rs2, imm_hi]
def pack_j(instr):
""" verify & pack J-type instructions.
- >>> reduce(__and__, pack_j([(0x6f, 'jal'), (0, 'rd', 'x0'), (0, 'off20')]))
- Bitfield(0xde000000, 32)
+ >>> _test_format(pack_j([(0x6f, 'jal'), (0, 'rd', 'x0'), (0, 'off20')]))
+ '6f/7 00/5 00/8 0/1 000/10 0/1'
- >>> reduce(__and__, pack_j([(0x6f, 'jal'), (0, 'rd', 'x0'), (-2, 'off20')]))
- Bitfield(0xde0ffffd, 32)
+ >>> _test_format(pack_j([(0x6f, 'jal'), (0, 'rd', 'x0'), (-2, 'off20')]))
+ '6f/7 00/5 ff/8 1/1 3fe/10 1/1'
- >>> pack_j([(0x6f, 'jal'), (2, 'rd', 'x2'), ('home', 'off20')])
- [Bitfield(0x6f, 7), Bitfield(0x2, 5), ('home[19:12]', 'off8'), ('home[11:11]', 'off1'), ('home[10:1]', 'off10'), ('home[20:20]', 'off1')]
+ >>> _test_format(pack_j([(0x6f, 'jal'), (2, 'rd', 'x2'), ('home', 'off20')]))
+ '6f/7 02/5 home/off20/[19:12] home/off20/[11:11] home/off20/[10:1] home/off20/[20:20]'
"""
(op, rd, imm) = instr
op = bits.u(subv.untag(op), 7)
@@ -239,24 +239,24 @@ def pack_j(instr):
else:
imm = bits.i(subv.untag(imm, 'off20'), 20)
- imm_lo = slice_bit_or_ref(imm, 9, 0) # + ('off[10:1]',)
- imm_11 = slice_bit_or_ref(imm, 10, 10) # + ('off[11]',)
- imm_hi = slice_bit_or_ref(imm, 18, 11) # + ('off[19:12]',)
- imm_20 = slice_bit_or_ref(imm, 19, 19) # + ('off[20]',)
+ imm_lo = imm[9:0]
+ imm_11 = imm[10]
+ imm_hi = imm[18:11]
+ imm_20 = imm[19]
return [op, rd, imm_hi, imm_11, imm_lo, imm_20]
def pack_b(instr):
""" verify & pack B-type instructions.
- >>> reduce(__and__, pack_b([(0x63, 'branch'), (0, 'subop', '=='), (6, 'rs'), (0, 'rs'), (0, 'off12')]))
- Bitfield(0xc6006000, 32)
+ >>> _test_format(pack_b([(0x63, 'branch'), (0, 'subop', '=='), (6, 'rs'), (0, 'rs'), (0, 'off12')]))
+ '63/7 0/1 0/4 0/3 06/5 00/5 00/6 0/1'
- >>> reduce(__and__, pack_b([(0x63, 'branch'), (0, 'subop', '=='), (6, 'rs'), (0, 'rs'), (-2, 'off12')]))
- Bitfield(0xc7e0607f, 32)
+ >>> _test_format(pack_b([(0x63, 'branch'), (0, 'subop', '=='), (6, 'rs'), (0, 'rs'), (-2, 'off12')]))
+ '63/7 1/1 e/4 0/3 06/5 00/5 3f/6 1/1'
- >>> pack_b([(0x63, 'branch'), (0, 'subop', '=='), (6, 'rs'), (0, 'rs'), ('home', 'off12')])
- [Bitfield(0x63, 7), ('home[11:11]', 'off1'), ('home[4:1]', 'off4'), Bitfield(0x0, 3), Bitfield(0x6, 5), Bitfield(0x0, 5), ('home[10:5]', 'off6'), ('home[12:12]', 'off1')]
+ >>> _test_format(pack_b([(0x63, 'branch'), (0, 'subop', '=='), (6, 'rs'), (0, 'rs'), ('home', 'off12')]))
+ '63/7 home/off12/[11:11] home/off12/[4:1] 0/3 06/5 00/5 home/off12/[10:5] home/off12/[12:12]'
"""
(op, sub, rs1, rs2, imm) = instr
op = bits.u(subv.untag(op), 7)
@@ -269,10 +269,11 @@ def pack_b(instr):
else:
imm = bits.i(subv.untag(imm, 'off12'), 12)
- imm_lo = slice_bit_or_ref(imm, 3, 0) # + ('off[4:1]',)
- imm_md = slice_bit_or_ref(imm, 9, 4) # + ('off[10:5]',)
- imm_11 = slice_bit_or_ref(imm, 10, 10) # + ('off[11]',)
- imm_12 = slice_bit_or_ref(imm, 11, 11) # + ('off[12]',)
+ imm_lo = imm[3:0]
+ imm_md = imm[9:4]
+ imm_11 = imm[10]
+ imm_12 = imm[11]
+
return [op, imm_11, imm_lo, sub, rs1, rs2, imm_md, imm_12]
instr_map = {
diff --git a/subv.py b/subv.py
index dd45b16..ed30308 100644
--- a/subv.py
+++ b/subv.py
@@ -299,8 +299,8 @@ def format_part(part):
>>> format_part(('$label:suff', 'tag'))
'$label:suff/tag'
"""
- if isinstance(part, bits.Bitfield):
- part = ('{:02x}'.format(part.val), part.size)
+ if isinstance(part, bits.WordBase):
+ return str(part)
elif not is_reference(part):
first = '{:02x}'.format(part[0])
part = (first, *part[1:])