git.s-ol.nu subv / 6368fb5
wip more validation logic s-ol 21 days ago
4 changed file(s) with 398 addition(s) and 135 deletion(s). Raw diff Collapse all Expand all
1717 ... 37/u 5/rd 10010/imm20
1818 ... # store 0x48 (H) in UART0+0
1919 ... 13/i 6/rd 0/funct3 0/rs 48/imm12
20 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
20 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
2121 ... # store 0x65 (e) in UART0+0
2222 ... 13/i 6/rd 0/funct3 0/rs 65/imm12
23 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
23 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
2424 ... # store 0x6c (l) in UART0+0
2525 ... 13/i 6/rd 0/funct3 0/rs 6c/imm12
26 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
26 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
2727 ... # store 0x6c (l) in UART0+0
2828 ... 13/i 6/rd 0/funct3 0/rs 6c/imm12
29 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
29 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
3030 ... # store 0x6f (o) in UART0+0
3131 ... 13/i 6/rd 0/funct3 0/rs 6f/imm12
32 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
32 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
3333 ... # store 0x0a (\\\\n) in UART0+0
3434 ... 13/i 6/rd 0/funct3 0/rs a/imm12
35 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
35 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
3636 ... # jump back up to the top
3737 ... 6f/j 0/rd -34/imm21
3838 ... '''[1:-1]))))
7070 return " ".join(map(str, words))
7171
7272
73 def pack_r(instr):
74 """verify & pack R-type instructions.
75
76 >>> _test_format(pack_r([(0x33, 'r'), (5, 'rd'), (0, 'funct3'), (0xa, 'rs1'), (0xb, 'rs2'), (0, 'funct7')]))
77 '33/7 05/5 0/3 0a/5 0b/5 00/7'
78 """
79 (op, rd, funct3, rs1, rs2, funct7) = instr
80 op = bits.u(subv.untag(op), 7)
81 rd = bits.u(subv.untag(rd, "rd"), 5)
82 funct3 = bits.u(subv.untag(funct3, "funct3"), 3)
83 rs1 = bits.u(subv.untag(rs1, "rs1"), 5)
84 rs2 = bits.u(subv.untag(rs2, "rs2"), 5)
85 funct7 = bits.u(subv.untag(funct7, "funct7"), 7)
86
87 return [op, rd, funct3, rs1, rs2, funct7]
88
89
7390 def pack_i(instr):
7491 """verify & pack I-type instructions.
7592
7794 '13/7 06/5 0/3 00/5 065/12'
7895 """
7996 (op, rd, funct, rs, imm) = instr
80 op_tag = op[1]
8197 op = bits.u(subv.untag(op), 7)
8298 rd = bits.u(subv.untag(rd, "rd"), 5)
8399 funct = bits.u(subv.untag(funct, "funct3"), 3)
90106 def pack_s(instr):
91107 """verify & pack S-type instructions.
92108
93 >>> _test_format(pack_s([(0x23, 's'), (5, 'rs1'), (0, 'imm12'), (2, 'funct3'), (6, 'rs2')]))
109 >>> _test_format(pack_s([(0x23, 's'), (2, 'funct3'), (5, 'rs1'), (0, 'imm12'), (6, 'rs2')]))
94110 '23/7 00/5 2/3 05/5 06/5 00/7'
95111 """
96 (op, rs1, imm, funct, rs2) = instr
97 op = bits.u(subv.untag(op), 7)
112 (op, funct, rs1, imm, rs2) = instr
113 op = bits.u(subv.untag(op), 7)
114 funct = bits.u(subv.untag(funct, "funct3"), 3)
98115 rs1 = bits.u(subv.untag(rs1, "rs1"), 5)
99116 imm = bits.i(subv.untag(imm, "imm12"), 12)
100 funct = bits.u(subv.untag(funct, "funct3"), 3)
101117 rs2 = bits.u(subv.untag(rs2, "rs2"), 5)
102118
103119 imm_lo = imm[4:0]
179195
180196
181197 format_map = {
182 # "r": pack_r,
198 "r": pack_r,
183199 "i": pack_i,
184200 "s": pack_s,
185201 "b": pack_b,
44 hex = re.compile(r"^\-?(0x)?[0-9a-f]+$")
55 num = re.compile(r"^\d+$")
66 ref_re = re.compile(r"^([^\[+-]+)(?:([+-]\d+))?$")
7 immediate_re = re.compile(r"^(imm|off)(\d+)(hi|lo)?$")
7 immediate_re = re.compile(r"^(imm|off|csr)(\d+)(hi|lo)?$")
88
99
1010 # parsing
1010 ... 37/u 5/rd 10010/imm20
1111 ... # store 0x48 (H) in UART0+0
1212 ... 13/i 6/rd 0/funct3 0/rs 48/imm12
13 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
13 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
1414 ... # store 0x65 (e) in UART0+0
1515 ... 13/i 6/rd 0/funct3 0/rs 65/imm12
16 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
16 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
1717 ... # store 0x6c (l) in UART0+0
1818 ... 13/i 6/rd 0/funct3 0/rs 6c/imm12
19 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
19 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
2020 ... # store 0x6c (l) in UART0+0
2121 ... 13/i 6/rd 0/funct3 0/rs 6c/imm12
22 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
22 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
2323 ... # store 0x6f (o) in UART0+0
2424 ... 13/i 6/rd 0/funct3 0/rs 6f/imm12
25 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
25 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
2626 ... # store 0x0a (\\\\n) in UART0+0
2727 ... 13/i 6/rd 0/funct3 0/rs a/imm12
28 ... 23/s 5/rs1 0/imm12 2/funct3 6/rs2
28 ... 23/s 2/funct3 5/rs1 0/imm12 6/rs2
2929 ... # jump back up to the top
3030 ... 6f/j 0/rd main/off21
3131 ... '''[1:-1]))))
3535 37/u 5/rd 10010/imm20
3636 # store 0x48 (H) in UART0+0
3737 13/i 6/rd 0/funct3 0/rs 48/imm12
38 23/s 5/rs1 0/imm12 2/funct3 6/rs2
38 23/s 2/funct3 5/rs1 0/imm12 6/rs2
3939 # store 0x65 (e) in UART0+0
4040 13/i 6/rd 0/funct3 0/rs 65/imm12
41 23/s 5/rs1 0/imm12 2/funct3 6/rs2
41 23/s 2/funct3 5/rs1 0/imm12 6/rs2
4242 # store 0x6c (l) in UART0+0
4343 13/i 6/rd 0/funct3 0/rs 6c/imm12
44 23/s 5/rs1 0/imm12 2/funct3 6/rs2
44 23/s 2/funct3 5/rs1 0/imm12 6/rs2
4545 # store 0x6c (l) in UART0+0
4646 13/i 6/rd 0/funct3 0/rs 6c/imm12
47 23/s 5/rs1 0/imm12 2/funct3 6/rs2
47 23/s 2/funct3 5/rs1 0/imm12 6/rs2
4848 # store 0x6f (o) in UART0+0
4949 13/i 6/rd 0/funct3 0/rs 6f/imm12
50 23/s 5/rs1 0/imm12 2/funct3 6/rs2
50 23/s 2/funct3 5/rs1 0/imm12 6/rs2
5151 # store 0x0a (\\n) in UART0+0
5252 13/i 6/rd 0/funct3 0/rs a/imm12
53 23/s 5/rs1 0/imm12 2/funct3 6/rs2
53 23/s 2/funct3 5/rs1 0/imm12 6/rs2
5454 # jump back up to the top
5555 6f/j 0/rd -34/imm21
5656
9191 67/i 0/subop 0/rd/x0 7/rs/t2 -1c/imm12
9292 """
9393 import subv
94 import bits
9594
9695
9796 def observe(word, pc, map):
1111 ... # load 0x10010000 (UART0) into t0
1212 ... 37/lui 5/rd/t0 0x10010/imm20
1313 ... # store 0x48 (H) in UART0+0
14 ... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 48/imm12
15 ... 23/store 2/width/word 5/rs/t0 6/rs/t1 0/off12
14 ... 13/opi 6/rd/t1 0/subop/add 0/rs/x0 48/imm12
15 ... 23/store 2/width/word 5/rs/t0 0/off12 6/rs/t1
1616 ... # store 0x65 (e) in UART0+0
17 ... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 65/imm12
18 ... 23/store 2/width/word 5/rs/t0 6/rs/t1 0/off12
17 ... 13/opi 6/rd/t1 0/subop/add 0/rs/x0 65/imm12
18 ... 23/store 2/width/word 5/rs/t0 0/off12 6/rs/t1
1919 ... # store 0x6c (l) in UART0+0
20 ... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6c/imm12
21 ... 23/store 2/width/word 5/rs/t0 6/rs/t1 0/off12
20 ... 13/opi 6/rd/t1 0/subop/add 0/rs/x0 6c/imm12
21 ... 23/store 2/width/word 5/rs/t0 0/off12 6/rs/t1
2222 ... # store 0x6c (l) in UART0+0
23 ... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6c/imm12
24 ... 23/store 2/width/word 5/rs/t0 6/rs/t1 0/off12
23 ... 13/opi 6/rd/t1 0/subop/add 0/rs/x0 6c/imm12
24 ... 23/store 2/width/word 5/rs/t0 0/off12 6/rs/t1
2525 ... # store 0x6f (o) in UART0+0
26 ... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6f/imm12
27 ... 23/store 2/width/word 5/rs/t0 6/rs/t1 0/off12
26 ... 13/opi 6/rd/t1 0/subop/add 0/rs/x0 6f/imm12
27 ... 23/store 2/width/word 5/rs/t0 0/off12 6/rs/t1
2828 ... # store 0x0a (\\\\n) in UART0+0
29 ... 13/opi 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12
30 ... 23/store 2/width/word 5/rs/t0 6/rs/t1 0/off12
29 ... 13/opi 6/rd/t1 0/subop/add 0/rs/x0 0a/imm12
30 ... 23/store 2/width/word 5/rs/t0 0/off12 6/rs/t1
3131 ... # jump back up to the top
3232 ... 6f/jal 0/rd/x0 main/off21
3333 ... '''[1:-1]))))
3737 37/u 5/rd 10010/imm20
3838 # store 0x48 (H) in UART0+0
3939 13/i 6/rd 0/funct3 0/rs 48/imm12
40 23/s 5/rs1 0/imm12 2/funct3 6/rs2
40 23/s 2/funct3 5/rs1 0/imm12 6/rs2
4141 # store 0x65 (e) in UART0+0
4242 13/i 6/rd 0/funct3 0/rs 65/imm12
43 23/s 5/rs1 0/imm12 2/funct3 6/rs2
43 23/s 2/funct3 5/rs1 0/imm12 6/rs2
4444 # store 0x6c (l) in UART0+0
4545 13/i 6/rd 0/funct3 0/rs 6c/imm12
46 23/s 5/rs1 0/imm12 2/funct3 6/rs2
46 23/s 2/funct3 5/rs1 0/imm12 6/rs2
4747 # store 0x6c (l) in UART0+0
4848 13/i 6/rd 0/funct3 0/rs 6c/imm12
49 23/s 5/rs1 0/imm12 2/funct3 6/rs2
49 23/s 2/funct3 5/rs1 0/imm12 6/rs2
5050 # store 0x6f (o) in UART0+0
5151 13/i 6/rd 0/funct3 0/rs 6f/imm12
52 23/s 5/rs1 0/imm12 2/funct3 6/rs2
52 23/s 2/funct3 5/rs1 0/imm12 6/rs2
5353 # store 0x0a (\\n) in UART0+0
5454 13/i 6/rd 0/funct3 0/rs a/imm12
55 23/s 5/rs1 0/imm12 2/funct3 6/rs2
55 23/s 2/funct3 5/rs1 0/imm12 6/rs2
5656 # jump back up to the top
5757 6f/j 0/rd main/off21
5858 """
6060 import subv
6161
6262
63 def pop_piece(line, labels):
63 def pop_part(line, labels, NAME="part"):
6464 for part in line:
6565 if part[1] in labels:
6666 line.remove(part)
67 return (part[0], labels[0])
68
69 raise ValueError("Expected a part with labels {}".format(labels))
70
71
72 def pop_immediate(line, sizes, allow_offset=False):
67 return (part[0], labels[0]) + part[2:]
68
69 raise ValueError("Expected a {} with label {}".format(NAME, "/".join(labels)))
70
71
72 def validate_part(line, labels, MAP, NAME="part"):
73 part = pop_part(line, labels, NAME)
74
75 MNEMONICS = "\nvalid mnemonics are: " + ", ".join(
76 subv.format_part((MAP[name], labels[0], name)) for name in MAP
77 )
78
79 if len(part) != 3:
80 raise ValueError(
81 "{} part {} needs a value mnemonic".format(NAME, subv.format_part(part))
82 + MNEMONICS
83 )
84
85 value, _, name = part
86
87 if name not in MAP:
88 raise ValueError("Unknown {} mnemonic '{}'".format(NAME, name) + MNEMONICS)
89
90 if value != MAP[name]:
91 raise ValueError(
92 "{} code doesn't match mnemonic (got {}, expected {})".format(
93 NAME,
94 subv.format_part(part),
95 subv.format_part((MAP[name],) + part[1:]),
96 )
97 )
98
99 return part
100
101
102 def pop_immediate(line, sizes, modes=["imm"]):
73103 if isinstance(sizes, int):
74104 sizes = [sizes]
75105
77107 imm = subv.parse_immediate(part[1])
78108 if imm and imm["size"] in sizes:
79109 line.remove(part)
110
111 if imm["mode"] not in modes:
112 raise ValueError(
113 "Expected immediate {} to use mode {}".format(
114 subv.format_part(part), "/".join(modes)
115 )
116 )
117
80118 if not isinstance(part[0], str):
81 imm["mode"] = "imm"
119 imm["mode"] = modes[0]
82120
83121 return (part[0], subv.format_immediate(imm))
84122
87125 )
88126
89127
128 def validate_empty(inputs):
129 if len(inputs) != 0:
130 raise ValueError("Extra arguments: {}".format(inputs))
131
132
90133 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"
91134 REG_NAMES = {name: i for i, name in enumerate(REG_NAMES.split(","))}
92135 REG_NAMES.update({"x{}".format(i): i for i in range(32)})
93136
94137
95 def pop_register(line, labels):
96 for part in line:
97 if part[1] in labels:
98 line.remove(part)
99
100 value = part[0]
101 if value < 0 or value > 31:
102 raise ValueError(
103 "Invalid register value {} (expected 0...31)".format(value)
104 )
105
106 if len(part) > 2:
107 name = part[2]
108 try:
109 assert value == REG_NAMES[name], ValueError(
110 "Invalid register value {} for '{}', expected {}".format(
111 value, name, REG_NAMES[name]
112 )
113 )
114 except KeyError:
115 raise ValueError("Unknown register name '{}'".format(name))
116
117 return (part[0], labels[0])
118
119 raise ValueError("Expected a register with labels {}".format(labels))
120
121
122 def validate_r(inputs):
123 op = inputs.pop(0)
124
125 dest = pop_register(inputs, ["rd", "dest"])
126 funct = pop_piece(inputs, ["funct7", "funct", "subop"])
127 rs1 = pop_register(inputs, ["rs1", "rs", "src1", "src"])
128 rs2 = pop_register(inputs, ["rs2", "rs", "src2", "src"])
129
130 assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
138 def validate_reg(line, labels):
139 """pop a register and validate its mnemonic.
140
141 >>> validate_reg([(5, 'rd', 't0')], ['rd', 'dest'])
142 (5, 'rd')
143 >>> validate_reg([(5, 'rd', 'x5')], ['rd', 'dest'])
144 (5, 'rd')
145 >>> validate_reg([(5, 'dest', 'x5')], ['rd', 'dest'])
146 (5, 'rd')
147
148 >>> validate_reg([(5, 'rd')], ['rd']) # doctest: +ELLIPSIS
149 Traceback (most recent call last):
150 ...
151 ValueError: register part 5/rd needs a value mnemonic
152 valid mnemonics are: 0/rd/zero, 1/rd/ra, 2/rd/sp, ...
153 >>> validate_reg([(5, 'rd', 'xxx')], ['rd']) # doctest: +ELLIPSIS
154 Traceback (most recent call last):
155 ...
156 ValueError: Unknown register mnemonic 'xxx'
157 valid mnemonics are: 0/rd/zero, 1/rd/ra, 2/rd/sp, ...
158 >>> validate_reg([(3, 'rd', 't0')], ['rd'])
159 Traceback (most recent call last):
160 ...
161 ValueError: register code doesn't match mnemonic (got 3/rd/t0, expected 5/rd/t0)
162 >>> validate_reg([(5, 'rd')], ['rs'])
163 Traceback (most recent call last):
164 ...
165 ValueError: Expected a register with label rs
166 >>> validate_reg([], ['rd', 'dest'])
167 Traceback (most recent call last):
168 ...
169 ValueError: Expected a register with label rd/dest
170 """
171
172 return validate_part(line, labels, REG_NAMES, "register")[:2]
173
174
175 COMP_OP_NAMES = {
176 "add": 0,
177 "sub": 0,
178 "xor": 4,
179 "or": 6,
180 "and": 7,
181 "sll": 1,
182 "slt": 2,
183 "sltu": 3,
184 "srl": 5,
185 "sra": 5,
186 }
187
188 STORE_WIDTHS = {
189 # ISA names
190 # byte
191 "b": 0,
192 "byte": 0,
193 # halfword
194 "h": 1,
195 "half": 1,
196 # word
197 "w": 2,
198 "word": 2,
199 }
200
201 LOAD_WIDTHS = STORE_WIDTHS | {
202 # unsigned byte
203 "bu": 4,
204 "ubyte": 4,
205 # unsigned halfword
206 "hu": 5,
207 "uhalf": 5,
208 }
209
210 BRANCH_NAMES = {
211 # equal
212 "beq": 0,
213 "eq": 0,
214 "==": 0,
215 # not equal
216 "bne": 1,
217 "ne": 1,
218 "!=": 1,
219 # lower than
220 "blt": 4,
221 "lt": 4,
222 "<": 4,
223 # greater/equal than
224 "bge": 5,
225 "ge": 5,
226 ">=": 5,
227 # unsigned lower than
228 "bltu": 6,
229 "ltu": 6,
230 "<u": 6,
231 # unsigned greater/equal than
232 "bgeu": 7,
233 "geu": 7,
234 ">=u": 7,
235 }
236
237 SYSTEM_OP_NAMES = {
238 "csrrw": 1, # read/write
239 "csrrs": 2, # read/set,
240 "csrrc": 3, # read/clear,
241 "csrrwi": 5, # read/write immediate
242 "csrrsi": 6, # read/set, immediate
243 "csrrci": 7, # read/clear, immediate
244 }
245
246
247 def validate_opr(inputs):
248 """
249 validate integer register-register operations.
250
251 >>> validate_opr(subv.parse('33/opr 0/mode/norm 0/subop/add 5/rd/t0 a/rs/a0 b/rs/a1')['instr'])
252 [(51, 'r'), (5, 'rd'), (0, 'funct3'), (10, 'rs1'), (11, 'rs2'), (0, 'funct7')]
253 >>> validate_opr(subv.parse('33/opr 20/mode/alt 0/subop/sub 5/rd/t0 a/rs/a0 b/rs/a1')['instr'])
254 [(51, 'r'), (5, 'rd'), (0, 'funct3'), (10, 'rs1'), (11, 'rs2'), (32, 'funct7')]
255 >>> validate_opr(subv.parse('33/opr 20/mode/alt 5/subop/sra 5/rd/t0 a/rs/a0 b/rs/a1')['instr'])
256 [(51, 'r'), (5, 'rd'), (5, 'funct3'), (10, 'rs1'), (11, 'rs2'), (32, 'funct7')]
257
258 >>> validate_opr(subv.parse('33/opr 20/mode/alt 0/subop/add 5/rd/t0 a/rs/a0 b/rs/a1')['instr'])
259 Traceback (most recent call last):
260 ...
261 ValueError: comp-op 0/funct3/add needs to go with comp-mode 0/funct7/norm
262 >>> validate_opr(subv.parse('33/opr 0/mode/norm 0/subop/sub 5/rd/t0 a/rs/a0 b/rs/a1')['instr'])
263 Traceback (most recent call last):
264 ...
265 ValueError: comp-op 0/funct3/sub needs to go with comp-mode 20/funct7/alt
266 >>> validate_opr(subv.parse('33/opr 0/mode/norm 5/subop/sra 5/rd/t0 a/rs/a0 b/rs/a1')['instr'])
267 Traceback (most recent call last):
268 ...
269 ValueError: comp-op 5/funct3/sra needs to go with comp-mode 20/funct7/alt
270 """
271 op = inputs.pop(0)
272
273 dest = validate_reg(inputs, ["rd", "dest"])
274 rs1 = validate_reg(inputs, ["rs1", "rs", "src1", "src"])
275 rs2 = validate_reg(inputs, ["rs2", "rs", "src2", "src"])
276
277 funct3 = validate_part(
278 inputs, ["funct3", "funct", "subop"], COMP_OP_NAMES, NAME="comp-op"
279 )
280 funct7 = validate_part(
281 inputs, ["funct7", "mode"], {"norm": 0, "alt": 32}, NAME="comp-mode"
282 )
283 cop = funct3[2]
284
285 expect_mode = "alt" if cop in ["sub", "sra"] else "norm"
286 expect_val = 32 if expect_mode == "alt" else 0
287
288 if funct7[2] != expect_mode:
289 raise ValueError(
290 "comp-op {} needs to go with comp-mode {}".format(
291 subv.format_part(funct3),
292 subv.format_part((expect_val, "funct7", expect_mode)),
293 )
294 )
295
296 validate_empty(inputs)
131297
132298 return [
133299 (op[0], "r"),
134300 dest,
135 funct,
301 funct3[:2],
136302 rs1,
137303 rs2,
304 funct7[:2],
138305 ]
139306
140307
141308 def validate_i(inputs):
142309 op = inputs.pop(0)
143310
144 rs_name = "src"
145 if op[1] in ["load", "jalr"]:
146 rs_name = "base"
147
148 dest = pop_register(inputs, ["rd", "dest"])
149 funct = pop_piece(inputs, ["funct3", "funct", "subop"])
150 rs = pop_register(inputs, ["rs", rs_name])
311 dest = validate_reg(inputs, ["rd", "dest"])
312 funct = pop_part(inputs, ["funct3", "funct", "subop"])
313 src = validate_reg(inputs, ["rs", "rs1"])
151314 imm = pop_immediate(inputs, 12)
152315
153 assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
316 validate_empty(inputs)
154317
155318 return [
156319 (op[0], "i"),
157320 dest,
158 funct,
159 rs,
321 funct[:2],
322 src,
160323 imm,
161324 ]
162325
163326
164 def validate_s(inputs):
165 op = inputs.pop(0)
166 base = pop_register(inputs, ["rs1", "rs", "base"])
167 offset = pop_immediate(inputs, 12, allow_offset=True)
168 width = pop_piece(inputs, ["funct3", "funct", "width"])
169 src = pop_register(inputs, ["rs2", "rs", "src"])
170
171 assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
172
173 return [
174 (op[0], "s"),
327 def validate_jalr(inputs):
328 op = inputs.pop(0)
329
330 dest = validate_reg(inputs, ["rd", "dest"])
331 funct = pop_part(inputs, ["funct3", "funct", "subop"])
332 src = validate_reg(inputs, ["rs", "rs1", "base"])
333 offset = pop_immediate(inputs, 12, ["imm", "off"])
334
335 if funct[0] != 0:
336 raise ValueError("Expected 0/funct3, got {}".format(subv.format_part(funct)))
337
338 validate_empty(inputs)
339
340 return [
341 (op[0], "i"),
342 dest,
343 funct[:2],
344 src,
345 offset,
346 ]
347
348
349 def validate_csr(inputs):
350 """
351 validate system operations.
352
353 >>> validate_csr(subv.parse('73/system 0/dest/x0 1/subop/csrrw 5/rs/t0 afe/csr12')['instr'])
354 [(115, 'i'), (0, 'rd'), (1, 'funct3'), (5, 'rs'), (2814, 'imm12')]
355 >>> validate_csr(subv.parse('73/system 0/dest/x0 5/subop/csrrwi 7/imm5 afe/csr12')['instr'])
356 [(115, 'i'), (0, 'rd'), (5, 'funct3'), (7, 'imm5'), (2814, 'imm12')]
357
358 >>> validate_csr(subv.parse('73/system 0/dest/x0 1/subop/csrrw 7/imm5 afe/csr12')['instr'])
359 Traceback (most recent call last):
360 ...
361 ValueError: Expected a register with label rs/rs1/src
362 >>> validate_csr(subv.parse('73/system 0/dest/x0 5/subop/csrrwi 5/rs/t0 afe/csr12')['instr'])
363 Traceback (most recent call last):
364 ...
365 ValueError: Expected an immediate with size 5
366 """
367 op = inputs.pop(0)
368
369 dest = validate_reg(inputs, ["rd", "dest"])
370 funct = validate_part(
371 inputs, ["funct3", "funct", "subop"], SYSTEM_OP_NAMES, "system-op"
372 )
373 imm = pop_immediate(inputs, 12, ["imm", "csr"])
374
375 if funct[2][-1] == "i":
376 src = pop_immediate(inputs, 5)
377 else:
378 src = validate_reg(inputs, ["rs", "rs1", "src"])
379
380 validate_empty(inputs)
381
382 return [
383 (op[0], "i"),
384 dest,
385 funct[:2],
386 src,
387 imm,
388 ]
389
390
391 def validate_load(inputs):
392 op = inputs.pop(0)
393
394 dest = validate_reg(inputs, ["rd", "dest"])
395 width = validate_part(inputs, ["funct3", "funct", "width"], LOAD_WIDTHS, "width")
396 base = validate_reg(inputs, ["rs", "base"])
397 offset = pop_immediate(inputs, 12, ["imm", "off"])
398
399 validate_empty(inputs)
400
401 return [
402 (op[0], "i"),
403 dest,
404 width[:2],
175405 base,
176406 offset,
177 width,
407 ]
408
409
410 def validate_store(inputs):
411 op = inputs.pop(0)
412 width = validate_part(inputs, ["funct3", "funct", "width"], STORE_WIDTHS, "width")
413 base = validate_reg(inputs, ["rs1", "rs", "base"])
414 offset = pop_immediate(inputs, 12, ["imm", "off"])
415 src = validate_reg(inputs, ["rs2", "rs", "src"])
416
417 validate_empty(inputs)
418
419 return [
420 (op[0], "s"),
421 width[:2],
422 base,
423 offset,
178424 src,
179425 ]
180426
181427
182 def validate_b(inputs):
183 op = inputs.pop(0)
184
185 funct = pop_piece(inputs, ["funct3", "funct", "subop"])
186 rs1 = pop_register(inputs, ["rs1", "rs", "src1", "src"])
187 rs2 = pop_register(inputs, ["rs2", "rs", "src2", "src"])
188 offset = pop_immediate(inputs, [12, 13], allow_offset=True)
189
190 assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
428 def validate_branch(inputs):
429 op = inputs.pop(0)
430
431 funct = validate_part(
432 inputs, ["funct3", "funct", "subop"], BRANCH_NAMES, "branch-op"
433 )
434 rs1 = validate_reg(inputs, ["rs1", "rs", "src1", "src"])
435 rs2 = validate_reg(inputs, ["rs2", "rs", "src2", "src"])
436 offset = pop_immediate(inputs, [12, 13], ["imm", "off"])
437
438 validate_empty(inputs)
191439
192440 return [
193441 (op[0], "b"),
194 funct,
442 funct[:2],
195443 rs1,
196444 rs2,
197445 offset,
200448
201449 def validate_u(inputs):
202450 op = inputs.pop(0)
203 rd = pop_register(inputs, ["rd", "dest"])
204 imm = pop_immediate(inputs, 20, allow_offset=True)
205
206 assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
451 rd = validate_reg(inputs, ["rd", "dest"])
452 imm = pop_immediate(inputs, 20, ["imm", "off"])
453
454 validate_empty(inputs)
207455
208456 return [
209457 (op[0], "u"),
215463 def validate_j(inputs):
216464 op = inputs.pop(0)
217465
218 dest = pop_register(inputs, ["rd", "dest"])
219 offset = pop_immediate(inputs, [21, 20], allow_offset=True)
220
221 assert len(inputs) == 0, ValueError("Extra arguments: {}".format(inputs))
466 dest = validate_reg(inputs, ["rd", "dest"])
467 offset = pop_immediate(inputs, [21, 20], ["imm", "off"])
468
469 validate_empty(inputs)
222470
223471 return [
224472 (op[0], "j"),
228476
229477
230478 instr_map = {
231 "opr": (validate_r, 0x33),
479 "opr": (validate_opr, 0x33),
232480 "opi": (validate_i, 0x13),
233 "load": (validate_i, 0x03),
234 "jalr": (validate_i, 0x67),
235 "system": (validate_i, 0x73),
236 "store": (validate_s, 0x23),
237 "branch": (validate_b, 0x63),
481 "jalr": (validate_jalr, 0x67),
482 "system": (validate_csr, 0x73),
483 "load": (validate_load, 0x03),
484 "store": (validate_store, 0x23),
485 "branch": (validate_branch, 0x63),
238486 "lui": (validate_u, 0x37),
239487 "auipc": (validate_u, 0x17),
240488 "jal": (validate_j, 0x6F),