aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2021-07-05 12:01:38 +0000
committers-ol <s+removethis@s-ol.nu>2021-07-05 12:02:19 +0000
commitae0e0c052e7f1f613fb27d5aa21dfa83fbafcd61 (patch)
treefcc6e9a67329620b6427756b51b598d659746b45
parentupdate survey for new stage order (diff)
downloadsubv-ae0e0c052e7f1f613fb27d5aa21dfa83fbafcd61.tar.gz
subv-ae0e0c052e7f1f613fb27d5aa21dfa83fbafcd61.zip
update format for new pipeline
-rwxr-xr-xformat.py268
-rw-r--r--subv.py30
-rwxr-xr-xsurvey.py46
-rwxr-xr-xvalidate.py175
4 files changed, 226 insertions, 293 deletions
diff --git a/format.py b/format.py
index e75a188..87e3c51 100755
--- a/format.py
+++ b/format.py
@@ -1,44 +1,44 @@
#!/usr/bin/env python3
""" format.py
-Verifies instruction formats, orders and pre-bit-packs arguments.
+Bit-packs instructions and verifies value ranges according to instruction formats.
Every instruction-line in the code segment needs to start with the opcode,
-which has to be correctly tagged. Arguments have to be provided in the correct
-order currently, and their first tag is verified also.
+which has to be tagged with the instruction-format name. Arguments have to be provided
+in the correct order, and their first tag is verified also.
-Labels can be referenced in the immXX/offXX fields of most instructions. If no
-bitslice is given for the labels, the default slice is picked based on the
-instruction.
+Some immediates can be given in different sizes and will be sliced to size automatically.
+For example the "j" instruction-format can take an "imm20" pre-sliced immediate, or an
+"imm21" immediate, truncating the lowest bit (and asserting that it is zero).
>>> from io import StringIO
>>> # doctest: +REPORT_NDIFF
... print(subv.join_all(format(StringIO('''
... == code 0x80000000
-... main:
+... # main:
... # load 0x10010000 (UART0) into t0
-... 37/lui 5/rd/t0 0x10010/imm20
+... 37/u 5/rd 10010/imm20
... # store 0x48 (H) in UART0+0
-... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 48/imm12
-... 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12
+... 13/i 6/rd 0/funct3 0/rs 48/imm12
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # store 0x65 (e) in UART0+0
-... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 65/imm12
-... 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12
+... 13/i 6/rd 0/funct3 0/rs 65/imm12
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # store 0x6c (l) in UART0+0
-... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6c/imm12
-... 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12
+... 13/i 6/rd 0/funct3 0/rs 6c/imm12
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # store 0x6c (l) in UART0+0
-... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6c/imm12
-... 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12
+... 13/i 6/rd 0/funct3 0/rs 6c/imm12
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # store 0x6f (o) in UART0+0
-... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6f/imm12
-... 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12
+... 13/i 6/rd 0/funct3 0/rs 6f/imm12
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # store 0x0a (\\\\n) in UART0+0
-... 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
+... 13/i 6/rd 0/funct3 0/rs a/imm12
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # jump back up to the top
-... 6f/jal 0/rd/x0 main/off21
+... 6f/j 0/rd -34/imm21
... '''[1:-1]))))
== code 0x80000000
-main:
+# main:
# load 0x10010000 (UART0) into t0
37/7 05/5 10010/20
# store 0x48 (H) in UART0+0
@@ -60,7 +60,7 @@ main:
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/off21/[19:12] main/off21/[11:11] main/off21/[10:1] main/off21/[20:20]
+6f/7 00/5 ff/8 1/1 3e6/10 1/1
"""
import subv
@@ -71,135 +71,105 @@ def _test_format(words):
return " ".join(map(str, words))
-def ref_slice(ref, hi, lo):
- if hi < lo:
- raise ValueError("cant slice reverse range")
- elif hi >= ref["size"]:
- raise ValueError(
- "cant slice [{}:{}] from {} bit value".format(hi, lo, ref["size"])
- )
-
- return {
- **ref,
- "hi": hi,
- "lo": 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
-
+def pack_i(instr):
+ """verify & pack I-type instructions.
-def pack_u(instr):
- """verify & pack U-type instructions.
+ >>> _test_format(pack_i([(0x13, 'i'), (6, 'rd'), (0, 'funct3'), (0, 'rs'), (0x65, 'imm12')]))
+ '13/7 06/5 0/3 00/5 065/12'
+ """
+ (op, rd, funct, rs, imm) = instr
+ op_tag = op[1]
+ op = bits.u(subv.untag(op), 7)
+ rd = bits.u(subv.untag(rd, "rd"), 5)
+ funct = bits.u(subv.untag(funct, "funct3"), 3)
+ rs = bits.u(subv.untag(rs, "rs"), 5)
+ imm = bits.i(subv.untag(imm, "imm12"), 12)
- >>> _test_format(pack_u([(0x37, 'lui'), (5, 'rd', 't0'), (0x10010, 'imm20')]))
- '37/7 05/5 10010/20'
+ return [op, rd, funct, rs, imm]
- >>> _test_format(pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos', 'imm20')]))
- '37/7 05/5 pos/imm20/[31:12]'
- >>> _test_format(pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos', 'imm20', '[19:0]')]))
- '37/7 05/5 pos/imm20/[19:0]'
+def pack_s(instr):
+ """verify & pack S-type instructions.
- >>> _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/imm20/[31:0]
+ >>> _test_format(pack_s([(0x23, 's'), (5, 'rs1'), (0, 'imm12'), (2, 'funct3'), (6, 'rs2')]))
+ '23/7 00/5 2/3 05/5 06/5 00/7'
"""
- (op, rd, imm) = instr
+ (op, rs1, imm, funct, rs2) = instr
op = bits.u(subv.untag(op), 7)
- rd = bits.u(subv.untag(rd, "rd"), 5)
- if subv.is_reference(imm):
- imm = bits.ref(imm, slice(31, 12))
- else:
- imm = bits.i(subv.untag(imm, "imm20"), 20)
+ rs1 = bits.u(subv.untag(rs1, "rs1"), 5)
+ imm = bits.i(subv.untag(imm, "imm12"), 12)
+ funct = bits.u(subv.untag(funct, "funct3"), 3)
+ rs2 = bits.u(subv.untag(rs2, "rs2"), 5)
- return [op, rd, imm]
+ imm_lo = imm[4:0]
+ imm_hi = imm[11:5]
+ return [op, imm_lo, funct, rs1, rs2, imm_hi]
-def pack_i(instr):
- """verify & pack I-type instructions.
+def pack_b(instr):
+ """verify & pack B-type instructions.
- >>> _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'
+ >>> _test_format(pack_b([(0x63, 'branch'), (0, 'funct3'), (6, 'rs1'), (0, 'rs2'), (0, 'imm12')]))
+ '63/7 0/1 0/4 0/3 06/5 00/5 00/6 0/1'
- >>> _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]'
+ >>> _test_format(pack_b([(0x63, 'branch'), (0, 'funct3'), (6, 'rs1'), (0, 'rs2'), (-2, 'imm12')]))
+ '63/7 1/1 e/4 0/3 06/5 00/5 3f/6 1/1'
"""
- (op, sub, rd, rs, imm) = instr
- op_tag = op[1]
+ (op, funct, rs1, rs2, imm) = instr
op = bits.u(subv.untag(op), 7)
- sub = bits.u(subv.untag(sub, "subop"), 3)
- rd = bits.u(subv.untag(rd, "rd"), 5)
- rs = bits.u(subv.untag(rs, "rs"), 5)
- if subv.is_reference(imm):
- imm = bits.ref(imm, slice(11, 0))
+ funct = bits.u(subv.untag(funct, "funct3"), 3)
+ rs1 = bits.u(subv.untag(rs1, "rs1"), 5)
+ rs2 = bits.u(subv.untag(rs2, "rs2"), 5)
+
+ if imm[1] == "imm13":
+ imm = bits.i(subv.untag(imm, "imm13"), 13)
+ imm = imm[12:1]
else:
imm = bits.i(subv.untag(imm, "imm12"), 12)
- return [op, rd, sub, rs, imm]
+ imm_lo = imm[3:0]
+ imm_md = imm[9:4]
+ imm_11 = imm[10]
+ imm_12 = imm[11]
+ return [op, imm_11, imm_lo, funct, rs1, rs2, imm_md, imm_12]
-def pack_s(instr):
- """verify & pack S-type instructions.
- >>> _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'
+def pack_u(instr):
+ """verify & pack U-type instructions.
- >>> _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]'
+ >>> _test_format(pack_u([(0x37, 'lui'), (5, 'rd', 't0'), (0x10010, 'imm20')]))
+ '37/7 05/5 10010/20'
+
+ >>> _test_format(pack_u([(0x37, 'lui'), (5, 'rd', 't0'), (-0x1234, 'imm20')]))
+ '37/7 05/5 fedcc/20'
"""
- (op, sub, rs1, rs2, imm) = instr
+ (op, rd, imm) = instr
op = bits.u(subv.untag(op), 7)
- sub = bits.u(subv.untag(sub, "subop"), 3)
- rs1 = bits.u(subv.untag(rs1, "rs"), 5)
- rs2 = bits.u(subv.untag(rs2, "rs"), 5)
-
- if subv.is_reference(imm):
- imm = bits.ref(imm, slice(11, 0))
- else:
- imm = bits.i(subv.untag(imm, "off12"), 12)
+ rd = bits.u(subv.untag(rd, "rd"), 5)
+ imm = bits.i(subv.untag(imm, "imm20"), 20)
- imm_lo = imm[4:0]
- imm_hi = imm[11:5]
- return [op, imm_lo, sub, rs1, rs2, imm_hi]
+ return [op, rd, imm]
def pack_j(instr):
"""verify & pack J-type instructions.
- >>> _test_format(pack_j([(0x6f, 'jal'), (0, 'rd', 'x0'), (0, 'off20')]))
+ >>> _test_format(pack_j([(0x6f, 'jal'), (0, 'rd', 'x0'), (0, 'imm20')]))
'6f/7 00/5 00/8 0/1 000/10 0/1'
- >>> _test_format(pack_j([(0x6f, 'jal'), (0, 'rd', 'x0'), (-2, 'off20')]))
+ >>> _test_format(pack_j([(0x6f, 'jal'), (0, 'rd', 'x0'), (-2, 'imm20')]))
'6f/7 00/5 ff/8 1/1 3fe/10 1/1'
-
- >>> _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)
rd = bits.u(subv.untag(rd, "rd"), 5)
- if subv.is_reference(imm):
- imm = bits.ref(imm, slice(20, 1))
+ if imm[1] == "imm21":
+ imm = bits.i(subv.untag(imm, "imm21"), 21)
+ imm = imm[20:1]
else:
- imm = bits.i(subv.untag(imm, "off20"), 20)
+ imm = bits.i(subv.untag(imm, "imm20"), 20)
imm_lo = imm[9:0]
imm_11 = imm[10]
@@ -209,47 +179,13 @@ def pack_j(instr):
return [op, rd, imm_hi, imm_11, imm_lo, imm_20]
-def pack_b(instr):
- """verify & pack B-type instructions.
-
- >>> _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'
-
- >>> _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'
-
- >>> _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)
- sub = bits.u(subv.untag(sub, "subop"), 3)
- rs1 = bits.u(subv.untag(rs1, "rs"), 5)
- rs2 = bits.u(subv.untag(rs2, "rs"), 5)
-
- if subv.is_reference(imm):
- imm = bits.ref(imm, slice(12, 1))
- else:
- imm = bits.i(subv.untag(imm, "off12"), 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 = {
- # 'opr': (pack_r, 0x33),
- "load": (pack_i, 0x03),
- "opi": (pack_i, 0x13),
- "jalr": (pack_i, 0x67),
- "store": (pack_s, 0x23),
- "branch": (pack_b, 0x63),
- "lui": (pack_u, 0x37),
- "auipc": (pack_u, 0x17),
- "jal": (pack_j, 0x6F),
+format_map = {
+ # "r": pack_r,
+ "i": pack_i,
+ "s": pack_s,
+ "b": pack_b,
+ "u": pack_u,
+ "j": pack_j,
}
@@ -258,20 +194,14 @@ def format(iter):
for segment, line in iter:
if line["type"] == "instr" and segment == "code":
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"])
+ assert len(op) == 2, "instruction without format label: {}".format(op)
+
+ (op, format) = op
+ if format not in format_map:
+ raise ValueError("unknown instruction format: {}".format(format))
+ formatter = format_map[format]
+
+ line["instr"] = formatter(line["instr"][:])
line = yield subv.format(line)
else:
line = yield line["raw"]
diff --git a/subv.py b/subv.py
index 8a9b1d1..8871625 100644
--- a/subv.py
+++ b/subv.py
@@ -5,7 +5,7 @@ white = re.compile(r"[ \t\.\n]+")
hex = re.compile(r"^\-?(0x)?[0-9a-f]+$")
num = re.compile(r"^\d+$")
ref_re = re.compile(r"^([^\[+-]+)(?:([+-]\d+))?$")
-field_re = re.compile(r"^(imm|off)(\d+)(hi|lo)?$")
+immediate_re = re.compile(r"^(imm|off)(\d+)(hi|lo)?$")
# parsing
def parse_part(part):
@@ -91,6 +91,24 @@ def parse_label(line):
return line[:-1]
+def parse_immediate(particle):
+ match = immediate_re.match(particle)
+ if not match:
+ return None
+
+ mode, size, split = match.groups()
+
+ imm = {
+ "mode": mode,
+ "size": int(size),
+ }
+
+ if split is not None:
+ imm["split"] = split
+
+ return imm
+
+
def parse_reference(part):
"""parse a sliced-label part.
@@ -109,7 +127,7 @@ def parse_reference(part):
field = part[1]
label, off = ref_re.match(ref).groups()
- mode, size, split = field_re.match(field).groups()
+ mode, size, split = immediate_re.match(field).groups()
ref = {
"label": label,
@@ -280,6 +298,14 @@ def format_reference(ref):
return (label, "{mode}{size}".format(**ref), *ref["meta"])
+def format_immediate(imm):
+ tag = "{mode}{size}".format(**imm)
+ if "split" in imm:
+ tag += imm["split"]
+
+ return tag
+
+
def format_part(part):
"""opposite of parse_part.
diff --git a/survey.py b/survey.py
index 5f195f5..e98dc13 100755
--- a/survey.py
+++ b/survey.py
@@ -11,22 +11,22 @@ Resolves label references and substitutes them with literal values.
... 37/u 5/rd 10010/imm20
... # store 0x48 (H) in UART0+0
... 13/i 6/rd 0/funct3 0/rs 48/imm12
-... 23/s 5/rs1 0/off12 2/funct3 6/rs2
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # store 0x65 (e) in UART0+0
... 13/i 6/rd 0/funct3 0/rs 65/imm12
-... 23/s 5/rs1 0/off12 2/funct3 6/rs2
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # store 0x6c (l) in UART0+0
... 13/i 6/rd 0/funct3 0/rs 6c/imm12
-... 23/s 5/rs1 0/off12 2/funct3 6/rs2
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # store 0x6c (l) in UART0+0
... 13/i 6/rd 0/funct3 0/rs 6c/imm12
-... 23/s 5/rs1 0/off12 2/funct3 6/rs2
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # store 0x6f (o) in UART0+0
... 13/i 6/rd 0/funct3 0/rs 6f/imm12
-... 23/s 5/rs1 0/off12 2/funct3 6/rs2
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # store 0x0a (\\\\n) in UART0+0
... 13/i 6/rd 0/funct3 0/rs a/imm12
-... 23/s 5/rs1 0/off12 2/funct3 6/rs2
+... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
... # jump back up to the top
... 6f/j 0/rd main/off21
... '''[1:-1]))))
@@ -36,24 +36,24 @@ Resolves label references and substitutes them with literal values.
37/u 5/rd 10010/imm20
# store 0x48 (H) in UART0+0
13/i 6/rd 0/funct3 0/rs 48/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# store 0x65 (e) in UART0+0
13/i 6/rd 0/funct3 0/rs 65/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# store 0x6c (l) in UART0+0
13/i 6/rd 0/funct3 0/rs 6c/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# store 0x6c (l) in UART0+0
13/i 6/rd 0/funct3 0/rs 6c/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# store 0x6f (o) in UART0+0
13/i 6/rd 0/funct3 0/rs 6f/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# store 0x0a (\\n) in UART0+0
13/i 6/rd 0/funct3 0/rs a/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# jump back up to the top
-6f/j 0/rd -34/off21
+6f/j 0/rd -34/imm21
>>> # doctest: +REPORT_NDIFF
... print(subv.join_all(survey(StringIO('''
@@ -88,8 +88,8 @@ Resolves label references and substitutes them with literal values.
# store 0x0a (\\n) in UART0+0
13/i 0/subop/add 6/rd/t1 0/rs/x0 a/imm12
23/s 2/subop/word 5/rs/t0 6/rs/t1 0/off12
-17/u 7/rd/t2 0/off20
-67/i 0/subop 0/rd/x0 7/rs/t2 -1c/off12
+17/u 7/rd/t2 0/imm20
+67/i 0/subop 0/rd/x0 7/rs/t2 -1c/imm12
"""
import subv
import bits
@@ -105,19 +105,19 @@ def observe(word, pc, map):
>>> subv.format_part(observe(('label-2', 'imm20',), 0, {'label': 0x1234}))
'1232/imm20'
>>> subv.format_part(observe(('label', 'off32'), 0x1000, {'label': 0x1234}))
- '234/off32'
+ '234/imm32'
>>> subv.format_part(observe(('label+4', 'off32'), 0x1000, {'label': 0x1234}))
- '238/off32'
+ '238/imm32'
>>> subv.format_part(observe(('label', 'off32'), 0x1234, {'label': 0x1000}))
- '-234/off32'
+ '-234/imm32'
>>> subv.format_part(observe(('label', 'off20hi'), 0x1000, {'label': 0x3234}))
- '2/off20'
+ '2/imm20'
>>> subv.format_part(observe(('label', 'off12lo'), 0x1000, {'label': 0x3234}))
- '234/off12'
+ '234/imm12'
>>> subv.format_part(observe(('label', 'off20hi'), 0x3234, {'label': 0x1000}))
- '-2/off20'
+ '-2/imm20'
>>> subv.format_part(observe(('label', 'off12lo'), 0x3234, {'label': 0x1000}))
- '-234/off12'
+ '-234/imm12'
>>> observe(('label', 'imm32'), 0, {})
Traceback (most recent call last):
@@ -171,7 +171,7 @@ def observe(word, pc, map):
)
)
- return (value, "{mode}{size}".format(**ref))
+ return (value, "imm{size}".format(**ref))
@subv.with_parsed_lines
diff --git a/validate.py b/validate.py
index 452b4fa..84bb036 100755
--- a/validate.py
+++ b/validate.py
@@ -38,28 +38,27 @@ main:
37/u 5/rd 10010/imm20
# store 0x48 (H) in UART0+0
13/i 6/rd 0/funct3 0/rs 48/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# store 0x65 (e) in UART0+0
13/i 6/rd 0/funct3 0/rs 65/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# store 0x6c (l) in UART0+0
13/i 6/rd 0/funct3 0/rs 6c/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# store 0x6c (l) in UART0+0
13/i 6/rd 0/funct3 0/rs 6c/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# store 0x6f (o) in UART0+0
13/i 6/rd 0/funct3 0/rs 6f/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# store 0x0a (\\n) in UART0+0
13/i 6/rd 0/funct3 0/rs a/imm12
-23/s 5/rs1 0/off12 2/funct3 6/rs2
+23/s 5/rs1 0/imm12 2/funct3 6/rs2
# jump back up to the top
6f/j 0/rd main/off21
"""
import subv
-import bits
def pop_piece(line, labels):
@@ -71,48 +70,26 @@ def pop_piece(line, labels):
raise ValueError("Expected a part with labels {}".format(labels))
-REG_NAMES = {}
-REG_NAMES.update(
- {
- name: i
- for i, name in enumerate(
- [
- "zero",
- "ra",
- "sp",
- "gp",
- "tp",
- "t0",
- "t1",
- "t2",
- "s0",
- "s1",
- "a0",
- "a1",
- "a2",
- "a3",
- "a4",
- "a5",
- "a6",
- "a7",
- "s2",
- "s3",
- "s4",
- "s5",
- "s6",
- "s7",
- "s8",
- "s9",
- "s10",
- "s11",
- "t3",
- "t4",
- "t5",
- "t6",
- ]
- )
- }
-)
+def pop_immediate(line, sizes, allow_offset=False):
+ if isinstance(sizes, int):
+ sizes = [sizes]
+
+ for part in line:
+ imm = subv.parse_immediate(part[1])
+ if imm and imm["size"] in sizes:
+ line.remove(part)
+ if not isinstance(part[0], str):
+ imm["mode"] = "imm"
+
+ return (part[0], subv.format_immediate(imm))
+
+ raise ValueError(
+ "Expected an immediate with size {}".format("/".join(str(s) for s in sizes))
+ )
+
+
+REG_NAMES = "zero,ra,sp,gp,tp,t0,t1,t2,s0,s1,a0,a1,a2,a3,a4,a5,a6,a7,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,t3,t4,t5,t6"
+REG_NAMES = {name: i for i, name in enumerate(REG_NAMES.split(","))}
REG_NAMES.update({"x{}".format(i): i for i in range(32)})
@@ -143,35 +120,22 @@ def pop_register(line, labels):
raise ValueError("Expected a register with labels {}".format(labels))
-def validate_u(inputs):
+def validate_r(inputs):
op = inputs.pop(0)
- rd = pop_register(inputs, ["rd", "dest"])
- imm = inputs.pop()
- assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
-
- return [
- (op[0], "u"),
- rd,
- imm,
- ]
-
-
-def validate_s(inputs):
- op = inputs.pop(0)
- width = pop_piece(inputs, ["funct3", "funct", "width"])
- base = pop_register(inputs, ["rs1", "rs", "base"])
- src = pop_register(inputs, ["rs2", "rs", "src"])
- offset = inputs.pop()
+ dest = pop_register(inputs, ["rd", "dest"])
+ funct = pop_piece(inputs, ["funct7", "funct", "subop"])
+ rs1 = pop_register(inputs, ["rs1", "rs", "src1", "src"])
+ rs2 = pop_register(inputs, ["rs2", "rs", "src2", "src"])
assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
return [
- (op[0], "s"),
- base,
- offset,
- width,
- src,
+ (op[0], "r"),
+ dest,
+ funct,
+ rs1,
+ rs2,
]
@@ -185,7 +149,7 @@ def validate_i(inputs):
dest = pop_register(inputs, ["rd", "dest"])
funct = pop_piece(inputs, ["funct3", "funct", "subop"])
rs = pop_register(inputs, ["rs", rs_name])
- imm = inputs.pop()
+ imm = pop_immediate(inputs, 12)
assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
@@ -198,69 +162,82 @@ def validate_i(inputs):
]
-def validate_r(inputs):
+def validate_s(inputs):
op = inputs.pop(0)
+ base = pop_register(inputs, ["rs1", "rs", "base"])
+ offset = pop_immediate(inputs, 12, allow_offset=True)
+ width = pop_piece(inputs, ["funct3", "funct", "width"])
+ src = pop_register(inputs, ["rs2", "rs", "src"])
- dest = pop_register(inputs, ["rd", "dest"])
- funct = pop_piece(inputs, ["funct7", "funct", "subop"])
+ assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
+
+ return [
+ (op[0], "s"),
+ base,
+ offset,
+ width,
+ src,
+ ]
+
+
+def validate_b(inputs):
+ op = inputs.pop(0)
+
+ funct = pop_piece(inputs, ["funct3", "funct", "subop"])
rs1 = pop_register(inputs, ["rs1", "rs", "src1", "src"])
rs2 = pop_register(inputs, ["rs2", "rs", "src2", "src"])
+ offset = pop_immediate(inputs, [12, 13], allow_offset=True)
assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
return [
- (op[0], "r"),
- dest,
+ (op[0], "b"),
funct,
- rs1,
- rs2,
+ src1,
+ src2,
+ offset,
]
-def validate_j(inputs):
+def validate_u(inputs):
op = inputs.pop(0)
-
- dest = pop_register(inputs, ["rd", "dest"])
- offset = inputs.pop()
+ rd = pop_register(inputs, ["rd", "dest"])
+ imm = pop_immediate(inputs, 20, allow_offset=True)
assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
return [
- (op[0], "j"),
- dest,
- offset,
+ (op[0], "u"),
+ rd,
+ imm,
]
-def validate_b(inputs):
+def validate_j(inputs):
op = inputs.pop(0)
- funct = pop_piece(inputs, ["funct3", "funct", "subop"])
- rs1 = pop_register(inputs, ["rs1", "rs", "src1", "src"])
- rs2 = pop_register(inputs, ["rs2", "rs", "src2", "src"])
- offset = inputs.pop()
+ dest = pop_register(inputs, ["rd", "dest"])
+ offset = pop_immediate(inputs, [21, 20], allow_offset=True)
assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
return [
- (op[0], "b"),
- funct,
- src1,
- src2,
+ (op[0], "j"),
+ dest,
offset,
]
instr_map = {
- "opi": (validate_i, 0x13),
"opr": (validate_r, 0x33),
+ "opi": (validate_i, 0x13),
"load": (validate_i, 0x03),
- "store": (validate_s, 0x23),
- "jal": (validate_j, 0x6F),
"jalr": (validate_i, 0x67),
+ "store": (validate_s, 0x23),
"branch": (validate_b, 0x63),
"lui": (validate_u, 0x37),
"auipc": (validate_u, 0x17),
+ "jal": (validate_j, 0x6F),
}