ok this is tricky: an extra parameter has to be passed into sv_insn_t::remap
[riscv-isa-sim.git] / id_regs.py
1 #!/usr/bin/env python
2 # Copyright (C) 2018 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3
4 """ identify registers used in riscv/insns/*.h and create code
5 that can be used in spike at runtime
6
7 the design of spike assumes that once an opcode is identified,
8 the role of decoding the instruction is implicitly rolled into
9 and included inside the function that emulates that opcode.
10
11 however there may be circumstances where the behaviour of an
12 instruction has to change depending on "tags" associated with
13 the registers (security extensions, simple-v extension).
14
15 therefore this code walks the instruction implementations
16 in riscv/insns/*.h looking for register usage patterns.
17 the resultant table can be used *prior* to the emulation,
18 without having to manually maintain such a table.
19 """
20
21 import os
22 import sys
23
24 insns_dir = "./riscv/insns"
25 def list_insns():
26 if len(sys.argv) == 2:
27 fullfname = sys.argv[1]
28 pth, fname = os.path.split(fullfname)
29 insn = fname[:-2]
30 return [(fullfname, insn)]
31
32 res = []
33 for fname in os.listdir(insns_dir):
34 if not fname.endswith(".h"):
35 continue
36 if fname.startswith("regs_"):
37 continue
38 insn = fname[:-2]
39 res.append((os.path.join(insns_dir, fname), insn))
40 return res
41
42 intpatterns = ['WRITE_RD', 'RS1', 'RS2', 'RS3']
43 floatpatterns = ['WRITE_FRD', 'FRS1', 'FRS2', 'FRS3']
44 patterns = intpatterns + floatpatterns
45
46 def find_registers(fname):
47 res = []
48 isintfloat = 0x0 + 0xf << 4
49 with open(fname) as f:
50 f = f.read()
51 for pattern in patterns:
52 x = f.find(pattern)
53 if x == -1:
54 continue
55 if pattern.startswith('R') and x != 0 and f[x-1] == 'F':
56 # botch-job/hack: RS1 also matches against FRS1 (etc.)
57 # check letter before match: if "F", skip it.
58 continue
59 p = pattern
60 if p.startswith('WRITE_'):
61 p = p[6:]
62 if pattern in intpatterns:
63 idx = intpatterns.index(pattern)
64 isintfloat += 1 << idx
65 if pattern in floatpatterns:
66 idx = floatpatterns.index(pattern)
67 isintfloat &= ~(1 << (idx+4))
68 res.append('#define USING_REG_%s' % p)
69 if not res:
70 return '#define USING_NOREGS\n' \
71 '#define REGS_PATTERN 0x0\n'
72 res.append('#define REGS_PATTERN 0x%x' % isintfloat)
73 return '\n'.join(res)
74
75 if __name__ == '__main__':
76 files = list_insns()
77 for (fname, insn) in files:
78 regsname = "regs_%s.h" % insn
79 regsname = os.path.join(insns_dir, regsname)
80 with open(regsname, "w") as f:
81 f.write(find_registers(fname))