aboutsummaryrefslogtreecommitdiffstats
path: root/validate.py
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2021-07-09 14:23:19 +0000
committers-ol <s+removethis@s-ol.nu>2021-07-09 14:36:35 +0000
commitce86c3272d7cf49a9672a13b353ee7fe1f6bfdaf (patch)
tree98e1c62b397e743e54dc2cdba6fbc1f0bbf466fb /validate.py
parentadd kakoune highlighting file (diff)
downloadsubv-ce86c3272d7cf49a9672a13b353ee7fe1f6bfdaf.tar.gz
subv-ce86c3272d7cf49a9672a13b353ee7fe1f6bfdaf.zip
validate opi, system
Diffstat (limited to 'validate.py')
-rwxr-xr-xvalidate.py140
1 files changed, 121 insertions, 19 deletions
diff --git a/validate.py b/validate.py
index 30cef46..2e46a9b 100755
--- a/validate.py
+++ b/validate.py
@@ -70,6 +70,18 @@ def pop_part(line, labels, NAME="part"):
raise ValueError("Expected a {} with label {}".format(NAME, "/".join(labels)))
+def try_pop_zeroes(line, labels):
+ try:
+ part = pop_part(line, labels)[:2]
+ except ValueError:
+ part = (0, labels[0])
+
+ if part[0] != 0:
+ raise ValueError("Expected {} value to be zero".format(subv.format_part(part)))
+
+ return part
+
+
def validate_part(line, labels, MAP, NAME="part"):
part = pop_part(line, labels, NAME)
@@ -236,12 +248,13 @@ BRANCH_NAMES = {
}
SYSTEM_OP_NAMES = {
- "csrrw": 1, # read/write
- "csrrs": 2, # read/set,
- "csrrc": 3, # read/clear,
- "csrrwi": 5, # read/write immediate
- "csrrsi": 6, # read/set, immediate
- "csrrci": 7, # read/clear, immediate
+ "priv": 0, # fence, ecall, ebreak
+ "csrrw": 1, # CSR read/write
+ "csrrs": 2, # CSR read/set,
+ "csrrc": 3, # CSR read/clear,
+ "csrrwi": 5, # CSR read/write immediate
+ "csrrsi": 6, # CSR read/set, immediate
+ "csrrci": 7, # CSR read/clear, immediate
}
@@ -281,9 +294,8 @@ def validate_opr(inputs):
funct7 = validate_part(
inputs, ["funct7", "mode"], {"norm": 0, "alt": 32}, NAME="comp-mode"
)
- cop = funct3[2]
- expect_mode = "alt" if cop in ["sub", "sra"] else "norm"
+ expect_mode = "alt" if funct3[2] in ["sub", "sra"] else "norm"
expect_val = 32 if expect_mode == "alt" else 0
if funct7[2] != expect_mode:
@@ -306,13 +318,71 @@ def validate_opr(inputs):
]
-def validate_i(inputs):
+def validate_opi(inputs):
+ """
+ validate integer register-immediate operations.
+
+ >>> validate_opi(subv.parse('13/opi 5/rd/t0 0/subop/add a/rs/a0 42/imm12')['instr'])
+ [(19, 'i'), (5, 'rd'), (0, 'funct3'), (10, 'rs'), (66, 'imm12')]
+ >>> validate_opi(subv.parse('13/opi 5/rd/t0 3/subop/sltu 5/rs/t0 8/imm12')['instr'])
+ [(19, 'i'), (5, 'rd'), (3, 'funct3'), (5, 'rs'), (8, 'imm12')]
+ >>> validate_opi(subv.parse('13/opi 5/rd/t0 1/subop/sll 0/imm7 5/rs/t0 8/imm5')['instr'])
+ [(19, 'i'), (5, 'rd'), (1, 'funct3'), (5, 'rs'), (8, 'imm12')]
+ >>> validate_opi(subv.parse('13/opi 5/rd/t0 1/subop/sll 5/rs/t0 8/imm12')['instr'])
+ [(19, 'i'), (5, 'rd'), (1, 'funct3'), (5, 'rs'), (8, 'imm12')]
+ >>> validate_opi(subv.parse('13/opi 5/rd/t0 5/subop/sra 20/imm7 5/rs/t0 8/imm5')['instr'])
+ [(19, 'i'), (5, 'rd'), (5, 'funct3'), (5, 'rs'), (1032, 'imm12')]
+ >>> validate_opi(subv.parse('13/opi 5/rd/t0 5/subop/sra 5/rs/t0 408/imm12')['instr'])
+ [(19, 'i'), (5, 'rd'), (5, 'funct3'), (5, 'rs'), (1032, 'imm12')]
+
+ >>> validate_opi(subv.parse('13/opi 5/rd/t0 1/subop/sll 12/imm7 5/rs/t0 8/imm5')['instr'])
+ Traceback (most recent call last):
+ ...
+ ValueError: comp-op 1/funct3/sll needs to go with comp-mode 0/imm7/norm
+ >>> validate_opi(subv.parse('13/opi 5/rd/t0 1/subop/sll 5/rs/t0 108/imm12')['instr'])
+ Traceback (most recent call last):
+ ...
+ ValueError: comp-op 1/funct3/sll needs to go with comp-mode 0/imm7/norm
+ >>> validate_opi(subv.parse('13/opi 5/rd/t0 5/subop/sra 10/imm7 5/rs/t0 8/imm5')['instr'])
+ Traceback (most recent call last):
+ ...
+ ValueError: comp-op 5/funct3/sra needs to go with comp-mode 20/imm7/alt
+ >>> validate_opi(subv.parse('13/opi 5/rd/t0 5/subop/sra 5/rs/t0 208/imm12')['instr'])
+ Traceback (most recent call last):
+ ...
+ ValueError: comp-op 5/funct3/sra needs to go with comp-mode 20/imm7/alt
+ """
op = inputs.pop(0)
dest = validate_reg(inputs, ["rd", "dest"])
- funct = pop_part(inputs, ["funct3", "funct", "subop"])
+ funct = validate_part(
+ inputs, ["funct3", "funct", "subop"], COMP_OP_NAMES, NAME="comp-op"
+ )
src = validate_reg(inputs, ["rs", "rs1"])
- imm = pop_immediate(inputs, 12)
+
+ if funct[2] in ["sll", "srl", "sra"]:
+ try:
+ shamt = pop_immediate(inputs, 5)
+ mode = pop_immediate(inputs, 7)
+ except ValueError:
+ imm = pop_immediate(inputs, 12)
+ shamt = ((imm[0] & 0b11111), 'imm5')
+ mode = (imm[0] >> 5, 'imm7')
+
+ expect_mode = "alt" if funct[2] == "sra" else "norm"
+ expect_val = 32 if expect_mode == "alt" else 0
+
+ if mode[0] != expect_val:
+ raise ValueError(
+ "comp-op {} needs to go with comp-mode {}".format(
+ subv.format_part(funct),
+ subv.format_part((expect_val, "imm7", expect_mode)),
+ )
+ )
+
+ imm = ((mode[0] << 5) | shamt[0], 'imm12')
+ else:
+ imm = pop_immediate(inputs, 12)
validate_empty(inputs)
@@ -326,10 +396,23 @@ def validate_i(inputs):
def validate_jalr(inputs):
+ """
+ validate jalr operations.
+
+ >>> validate_jalr(subv.parse('67/jalr 0/rd/x0 0/subop 1/rs/ra 0/off12')['instr'])
+ [(103, 'i'), (0, 'rd'), (0, 'funct3'), (1, 'rs'), (0, 'imm12')]
+ >>> validate_jalr(subv.parse('67/jalr 0/rd/x0 1/rs/ra 0/off12')['instr'])
+ [(103, 'i'), (0, 'rd'), (0, 'funct3'), (1, 'rs'), (0, 'imm12')]
+
+ >>> validate_jalr(subv.parse('67/jalr 0/rd/x0 4/subop 1/rs/ra 0/off12')['instr'])
+ Traceback (most recent call last):
+ ...
+ ValueError: Expected 4/funct3 value to be zero
+ """
op = inputs.pop(0)
dest = validate_reg(inputs, ["rd", "dest"])
- funct = pop_part(inputs, ["funct3", "funct", "subop"])
+ funct = try_pop_zeroes(inputs, ["funct3", "funct", "subop"])
src = validate_reg(inputs, ["rs", "rs1", "base"])
offset = pop_immediate(inputs, 12, ["imm", "off"])
@@ -356,6 +439,11 @@ def validate_system(inputs):
>>> validate_system(subv.parse('73/system 0/dest/x0 5/subop/csrrwi 7/imm5 afe/csr12')['instr'])
[(115, 'i'), (0, 'rd'), (5, 'funct3'), (7, 'imm5'), (2814, 'imm12')]
+ >>> validate_system(subv.parse('73/system 0/subop/priv 0/funct12/ecall')['instr'])
+ [(115, 'i'), (0, 'rd'), (0, 'funct3'), (0, 'rs'), (0, 'imm12')]
+ >>> validate_system(subv.parse('73/system 0/subop/priv 1/funct12/ebreak')['instr'])
+ [(115, 'i'), (0, 'rd'), (0, 'funct3'), (0, 'rs'), (1, 'imm12')]
+
>>> validate_system(subv.parse('73/system 0/dest/x0 1/subop/csrrw 7/imm5 afe/csr12')['instr'])
Traceback (most recent call last):
...
@@ -364,19 +452,33 @@ def validate_system(inputs):
Traceback (most recent call last):
...
ValueError: Expected an immediate with size 5
+ >>> validate_system(subv.parse('73/system 1/dest/x1 0/subop/priv 1/funct12/ebreak')['instr'])
+ Traceback (most recent call last):
+ ...
+ ValueError: Expected 1/rd value to be zero
"""
op = inputs.pop(0)
- dest = validate_reg(inputs, ["rd", "dest"])
funct = validate_part(
inputs, ["funct3", "funct", "subop"], SYSTEM_OP_NAMES, "system-op"
)
- imm = pop_immediate(inputs, 12, ["imm", "csr"])
- if funct[2][-1] == "i":
- src = pop_immediate(inputs, 5)
+ if funct[0] == 0:
+ # ecall/ebreak
+ imm = validate_part(
+ inputs, ["imm12", "funct12"], {"ecall": 0, "ebreak": 1}, "system-priv-op"
+ )[:2]
+
+ dest = try_pop_zeroes(inputs, ["rd", "dest"])
+ src = try_pop_zeroes(inputs, ["rs", "rs1", "src"])
else:
- src = validate_reg(inputs, ["rs", "rs1", "src"])
+ dest = validate_reg(inputs, ["rd", "dest"])
+ imm = pop_immediate(inputs, 12, ["imm", "csr"])
+
+ if funct[2][-1] == "i":
+ src = pop_immediate(inputs, 5)
+ else:
+ src = validate_reg(inputs, ["rs", "rs1", "src"])
validate_empty(inputs)
@@ -478,7 +580,7 @@ def validate_j(inputs):
instr_map = {
"opr": (validate_opr, 0x33),
- "opi": (validate_i, 0x13),
+ "opi": (validate_opi, 0x13),
"jalr": (validate_jalr, 0x67),
"system": (validate_system, 0x73),
"load": (validate_load, 0x03),
@@ -503,7 +605,7 @@ def validate(iter):
(validator, expected) = instr_map[label]
if op != expected:
raise ValueError(
- "opcode {} doesn't match label {} (expected {})".format(
+ "opcode {:02x} doesn't match label {} (expected {:02x})".format(
op, label, expected
)
)