git.s-ol.nu subv / ce86c32
validate opi, system s-ol 20 days ago
1 changed file(s) with 126 addition(s) and 24 deletion(s). Raw diff Collapse all Expand all
6969 raise ValueError("Expected a {} with label {}".format(NAME, "/".join(labels)))
7070
7171
72 def try_pop_zeroes(line, labels):
73 try:
74 part = pop_part(line, labels)[:2]
75 except ValueError:
76 part = (0, labels[0])
77
78 if part[0] != 0:
79 raise ValueError("Expected {} value to be zero".format(subv.format_part(part)))
80
81 return part
82
83
7284 def validate_part(line, labels, MAP, NAME="part"):
7385 part = pop_part(line, labels, NAME)
7486
235247 }
236248
237249 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
250 "priv": 0, # fence, ecall, ebreak
251 "csrrw": 1, # CSR read/write
252 "csrrs": 2, # CSR read/set,
253 "csrrc": 3, # CSR read/clear,
254 "csrrwi": 5, # CSR read/write immediate
255 "csrrsi": 6, # CSR read/set, immediate
256 "csrrci": 7, # CSR read/clear, immediate
244257 }
245258
246259
280293 funct7 = validate_part(
281294 inputs, ["funct7", "mode"], {"norm": 0, "alt": 32}, NAME="comp-mode"
282295 )
283 cop = funct3[2]
284
285 expect_mode = "alt" if cop in ["sub", "sra"] else "norm"
296
297 expect_mode = "alt" if funct3[2] in ["sub", "sra"] else "norm"
286298 expect_val = 32 if expect_mode == "alt" else 0
287299
288300 if funct7[2] != expect_mode:
305317 ]
306318
307319
308 def validate_i(inputs):
320 def validate_opi(inputs):
321 """
322 validate integer register-immediate operations.
323
324 >>> validate_opi(subv.parse('13/opi 5/rd/t0 0/subop/add a/rs/a0 42/imm12')['instr'])
325 [(19, 'i'), (5, 'rd'), (0, 'funct3'), (10, 'rs'), (66, 'imm12')]
326 >>> validate_opi(subv.parse('13/opi 5/rd/t0 3/subop/sltu 5/rs/t0 8/imm12')['instr'])
327 [(19, 'i'), (5, 'rd'), (3, 'funct3'), (5, 'rs'), (8, 'imm12')]
328 >>> validate_opi(subv.parse('13/opi 5/rd/t0 1/subop/sll 0/imm7 5/rs/t0 8/imm5')['instr'])
329 [(19, 'i'), (5, 'rd'), (1, 'funct3'), (5, 'rs'), (8, 'imm12')]
330 >>> validate_opi(subv.parse('13/opi 5/rd/t0 1/subop/sll 5/rs/t0 8/imm12')['instr'])
331 [(19, 'i'), (5, 'rd'), (1, 'funct3'), (5, 'rs'), (8, 'imm12')]
332 >>> validate_opi(subv.parse('13/opi 5/rd/t0 5/subop/sra 20/imm7 5/rs/t0 8/imm5')['instr'])
333 [(19, 'i'), (5, 'rd'), (5, 'funct3'), (5, 'rs'), (1032, 'imm12')]
334 >>> validate_opi(subv.parse('13/opi 5/rd/t0 5/subop/sra 5/rs/t0 408/imm12')['instr'])
335 [(19, 'i'), (5, 'rd'), (5, 'funct3'), (5, 'rs'), (1032, 'imm12')]
336
337 >>> validate_opi(subv.parse('13/opi 5/rd/t0 1/subop/sll 12/imm7 5/rs/t0 8/imm5')['instr'])
338 Traceback (most recent call last):
339 ...
340 ValueError: comp-op 1/funct3/sll needs to go with comp-mode 0/imm7/norm
341 >>> validate_opi(subv.parse('13/opi 5/rd/t0 1/subop/sll 5/rs/t0 108/imm12')['instr'])
342 Traceback (most recent call last):
343 ...
344 ValueError: comp-op 1/funct3/sll needs to go with comp-mode 0/imm7/norm
345 >>> validate_opi(subv.parse('13/opi 5/rd/t0 5/subop/sra 10/imm7 5/rs/t0 8/imm5')['instr'])
346 Traceback (most recent call last):
347 ...
348 ValueError: comp-op 5/funct3/sra needs to go with comp-mode 20/imm7/alt
349 >>> validate_opi(subv.parse('13/opi 5/rd/t0 5/subop/sra 5/rs/t0 208/imm12')['instr'])
350 Traceback (most recent call last):
351 ...
352 ValueError: comp-op 5/funct3/sra needs to go with comp-mode 20/imm7/alt
353 """
309354 op = inputs.pop(0)
310355
311356 dest = validate_reg(inputs, ["rd", "dest"])
312 funct = pop_part(inputs, ["funct3", "funct", "subop"])
357 funct = validate_part(
358 inputs, ["funct3", "funct", "subop"], COMP_OP_NAMES, NAME="comp-op"
359 )
313360 src = validate_reg(inputs, ["rs", "rs1"])
314 imm = pop_immediate(inputs, 12)
361
362 if funct[2] in ["sll", "srl", "sra"]:
363 try:
364 shamt = pop_immediate(inputs, 5)
365 mode = pop_immediate(inputs, 7)
366 except ValueError:
367 imm = pop_immediate(inputs, 12)
368 shamt = ((imm[0] & 0b11111), 'imm5')
369 mode = (imm[0] >> 5, 'imm7')
370
371 expect_mode = "alt" if funct[2] == "sra" else "norm"
372 expect_val = 32 if expect_mode == "alt" else 0
373
374 if mode[0] != expect_val:
375 raise ValueError(
376 "comp-op {} needs to go with comp-mode {}".format(
377 subv.format_part(funct),
378 subv.format_part((expect_val, "imm7", expect_mode)),
379 )
380 )
381
382 imm = ((mode[0] << 5) | shamt[0], 'imm12')
383 else:
384 imm = pop_immediate(inputs, 12)
315385
316386 validate_empty(inputs)
317387
325395
326396
327397 def validate_jalr(inputs):
398 """
399 validate jalr operations.
400
401 >>> validate_jalr(subv.parse('67/jalr 0/rd/x0 0/subop 1/rs/ra 0/off12')['instr'])
402 [(103, 'i'), (0, 'rd'), (0, 'funct3'), (1, 'rs'), (0, 'imm12')]
403 >>> validate_jalr(subv.parse('67/jalr 0/rd/x0 1/rs/ra 0/off12')['instr'])
404 [(103, 'i'), (0, 'rd'), (0, 'funct3'), (1, 'rs'), (0, 'imm12')]
405
406 >>> validate_jalr(subv.parse('67/jalr 0/rd/x0 4/subop 1/rs/ra 0/off12')['instr'])
407 Traceback (most recent call last):
408 ...
409 ValueError: Expected 4/funct3 value to be zero
410 """
328411 op = inputs.pop(0)
329412
330413 dest = validate_reg(inputs, ["rd", "dest"])
331 funct = pop_part(inputs, ["funct3", "funct", "subop"])
414 funct = try_pop_zeroes(inputs, ["funct3", "funct", "subop"])
332415 src = validate_reg(inputs, ["rs", "rs1", "base"])
333416 offset = pop_immediate(inputs, 12, ["imm", "off"])
334417
355438 >>> validate_system(subv.parse('73/system 0/dest/x0 5/subop/csrrwi 7/imm5 afe/csr12')['instr'])
356439 [(115, 'i'), (0, 'rd'), (5, 'funct3'), (7, 'imm5'), (2814, 'imm12')]
357440
441 >>> validate_system(subv.parse('73/system 0/subop/priv 0/funct12/ecall')['instr'])
442 [(115, 'i'), (0, 'rd'), (0, 'funct3'), (0, 'rs'), (0, 'imm12')]
443 >>> validate_system(subv.parse('73/system 0/subop/priv 1/funct12/ebreak')['instr'])
444 [(115, 'i'), (0, 'rd'), (0, 'funct3'), (0, 'rs'), (1, 'imm12')]
445
358446 >>> validate_system(subv.parse('73/system 0/dest/x0 1/subop/csrrw 7/imm5 afe/csr12')['instr'])
359447 Traceback (most recent call last):
360448 ...
363451 Traceback (most recent call last):
364452 ...
365453 ValueError: Expected an immediate with size 5
366 """
367 op = inputs.pop(0)
368
369 dest = validate_reg(inputs, ["rd", "dest"])
454 >>> validate_system(subv.parse('73/system 1/dest/x1 0/subop/priv 1/funct12/ebreak')['instr'])
455 Traceback (most recent call last):
456 ...
457 ValueError: Expected 1/rd value to be zero
458 """
459 op = inputs.pop(0)
460
370461 funct = validate_part(
371462 inputs, ["funct3", "funct", "subop"], SYSTEM_OP_NAMES, "system-op"
372463 )
373 imm = pop_immediate(inputs, 12, ["imm", "csr"])
374
375 if funct[2][-1] == "i":
376 src = pop_immediate(inputs, 5)
464
465 if funct[0] == 0:
466 # ecall/ebreak
467 imm = validate_part(
468 inputs, ["imm12", "funct12"], {"ecall": 0, "ebreak": 1}, "system-priv-op"
469 )[:2]
470
471 dest = try_pop_zeroes(inputs, ["rd", "dest"])
472 src = try_pop_zeroes(inputs, ["rs", "rs1", "src"])
377473 else:
378 src = validate_reg(inputs, ["rs", "rs1", "src"])
474 dest = validate_reg(inputs, ["rd", "dest"])
475 imm = pop_immediate(inputs, 12, ["imm", "csr"])
476
477 if funct[2][-1] == "i":
478 src = pop_immediate(inputs, 5)
479 else:
480 src = validate_reg(inputs, ["rs", "rs1", "src"])
379481
380482 validate_empty(inputs)
381483
477579
478580 instr_map = {
479581 "opr": (validate_opr, 0x33),
480 "opi": (validate_i, 0x13),
582 "opi": (validate_opi, 0x13),
481583 "jalr": (validate_jalr, 0x67),
482584 "system": (validate_system, 0x73),
483585 "load": (validate_load, 0x03),
502604 (validator, expected) = instr_map[label]
503605 if op != expected:
504606 raise ValueError(
505 "opcode {} doesn't match label {} (expected {})".format(
607 "opcode {:02x} doesn't match label {} (expected {:02x})".format(
506608 op, label, expected
507609 )
508610 )