diff options
| author | s-ol <s+removethis@s-ol.nu> | 2021-07-09 14:23:19 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2021-07-09 14:36:35 +0000 |
| commit | ce86c3272d7cf49a9672a13b353ee7fe1f6bfdaf (patch) | |
| tree | 98e1c62b397e743e54dc2cdba6fbc1f0bbf466fb /validate.py | |
| parent | add kakoune highlighting file (diff) | |
| download | subv-ce86c3272d7cf49a9672a13b353ee7fe1f6bfdaf.tar.gz subv-ce86c3272d7cf49a9672a13b353ee7fe1f6bfdaf.zip | |
validate opi, system
Diffstat (limited to 'validate.py')
| -rwxr-xr-x | validate.py | 140 |
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 ) ) |
