move reading into constructor
[soc.git] / src / soc / decoder / pseudo / pagereader.py
1 # Reads OpenPOWER ISA pages from http://libre-riscv.org/openpower/isa
2 """OpenPOWER ISA page parser
3
4 returns an OrderedDict of namedtuple "Ops" containing details of all
5 instructions listed in markdown files.
6
7 format must be strictly as follows (no optional sections) including whitespace:
8
9 # Compare Logical
10
11 X-Form
12
13 * cmpl BF,L,RA,RB
14
15 if L = 0 then a <- [0]*32 || (RA)[32:63]
16 b <- [0]*32 || (RB)[32:63]
17 else a <- (RA)
18 b <- (RB)
19 if a <u b then c <- 0b100
20 else if a >u b then c <- 0b010
21 else c <- 0b001
22 CR[4*BF+32:4*BF+35] <- c || XER[SO]
23
24 Special Registers Altered:
25
26 CR field BF
27 Another field
28
29 this translates to:
30
31 # heading
32 blank
33 Some-Form
34 blank
35 * instruction registerlist
36 * instruction registerlist
37 blank
38 4-space-indented pseudo-code
39 4-space-indented pseudo-code
40 blank
41 Special Registers Altered:
42 4-space-indented register description
43 blank
44 blank (optional)
45
46 """
47
48 from collections import namedtuple, OrderedDict
49 from copy import copy
50 import os
51
52 op = namedtuple("Ops", ("desc", "form", "opcode", "regs", "pcode", "sregs"))
53
54 def get_isa_dir():
55 fdir = os.path.abspath(os.path.dirname(__file__))
56 fdir = os.path.split(fdir)[0]
57 fdir = os.path.split(fdir)[0]
58 fdir = os.path.split(fdir)[0]
59 fdir = os.path.split(fdir)[0]
60 return os.path.join(fdir, "libreriscv", "openpower", "isa")
61
62 class ISA:
63
64 def __init__(self):
65 self.instr = OrderedDict()
66 self.forms = {}
67 for pth in os.listdir(os.path.join(get_isa_dir())):
68 print (get_isa_dir(), pth)
69 assert pth.endswith(".mdwn"), "only %s in isa dir" % pth
70 self.read_file(pth)
71
72 def read_file(self, fname):
73 fname = os.path.join(get_isa_dir(), fname)
74 with open(fname) as f:
75 lines = f.readlines()
76
77 d = {}
78 l = lines.pop(0).rstrip() # get first line
79 while lines:
80 print (l)
81 # expect get heading
82 assert l.startswith('#'), ("# not found in line %s" % l)
83 d['desc'] = l[1:].strip()
84
85 # whitespace expected
86 l = lines.pop(0).strip()
87 print (repr(l))
88 assert len(l) == 0, ("blank line not found %s" % l)
89
90 # Form expected
91 l = lines.pop(0).strip()
92 assert l.endswith('-Form'), ("line with -Form expected %s" % l)
93 d['form'] = l.split('-')[0]
94
95 # whitespace expected
96 l = lines.pop(0).strip()
97 assert len(l) == 0, ("blank line not found %s" % l)
98
99 # get list of opcodes
100 li = []
101 while True:
102 l = lines.pop(0).strip()
103 if len(l) == 0: break
104 assert l.startswith('*'), ("* not found in line %s" % l)
105 l = l[1:].split(' ') # lose star
106 l = filter(lambda x: len(x) != 0, l) # strip blanks
107 li.append(list(l))
108 opcodes = li
109
110 # get pseudocode
111 li = []
112 while True:
113 l = lines.pop(0).rstrip()
114 if len(l) == 0: break
115 assert l.startswith(' '), ("4spcs not found in line %s" % l)
116 l = l[4:] # lose 4 spaces
117 li.append(l)
118 d['pcode'] = li
119
120 # "Special Registers Altered" expected
121 l = lines.pop(0).rstrip()
122 assert l.startswith("Special"), ("special not found %s" % l)
123
124 # whitespace expected
125 l = lines.pop(0).strip()
126 assert len(l) == 0, ("blank line not found %s" % l)
127
128 # get special regs
129 li = []
130 while lines:
131 l = lines.pop(0).rstrip()
132 if len(l) == 0: break
133 assert l.startswith(' '), ("4spcs not found in line %s" % l)
134 l = l[4:] # lose 4 spaces
135 li.append(l)
136 d['sregs'] = li
137
138 # add in opcode
139 for o in opcodes:
140 self.add_op(o, d)
141
142 # expect and drop whitespace
143 while lines:
144 l = lines.pop(0).rstrip()
145 if len(l) != 0: break
146
147 def add_op(self, o, d):
148 opcode, regs = o[0], o[1:]
149 op = copy(d)
150 op['regs'] = regs
151 op['opcode'] = opcode
152 self.instr[opcode] = op
153
154 # create list of instructions by form
155 form = op['form']
156 fl = self.forms.get(form, [])
157 self.forms[form] = fl + [opcode]
158
159 def pprint_ops(self):
160 for k, v in self.instr.items():
161 print ("# %s %s" % (v['opcode'], v['desc']))
162 print ("Form: %s Regs: %s" % (v['form'], v['regs']))
163 print ('\n'.join(map(lambda x: " %s" % x, v['pcode'])))
164 print ("Specials")
165 print ('\n'.join(map(lambda x: " %s" % x, v['sregs'])))
166 print ()
167 for k, v in isa.forms.items():
168 print (k, v)
169
170 if __name__ == '__main__':
171 isa = ISA()
172 isa.pprint_ops()