code-cleanup (comments) and rename "i" to "XO"
[openpower-isa.git] / src / openpower / decoder / power_table.py
1 import pathlib
2 from openpower.decoder.power_enums import find_wiki_dir
3 from openpower.decoder.power_insn import (Database, MarkdownDatabase,
4 FieldsDatabase, PPCDatabase,
5 IntegerOpcode, PatternOpcode,
6 parse, Section, BitSel,
7 FieldsOpcode)
8 root = find_wiki_dir()
9 root = pathlib.Path(root)
10 mdwndb = MarkdownDatabase()
11 fieldsdb = FieldsDatabase()
12
13 # create by-sections first. these will be the markdown tables
14 sections = {}
15 insns = {}
16 path = (root / "insndb.csv")
17 with open(path, "r", encoding="UTF-8") as stream:
18 for section in parse(stream, Section.CSV):
19 sections[str(section.path)] = section
20 insns[str(section.path)] = []
21 for (name, section) in sections.items():
22 print (name, section)
23
24 # enumerate all instructions and drop them into sections
25 db = Database(root)
26 for insn in db:
27 insns[str(insn.section.path)].append(insn)
28 print (insn)
29
30 def maxme(num, s):
31 return s.ljust(num)
32
33 def binmaxed(num, v):
34 return format(v, "0%db" % num)
35
36 # create one table
37 def do_table(fname, insns, section, divpoint):
38 insns = insns[fname]
39 section = sections[fname]
40 start, end = section.bitsel.start, section.bitsel.end
41 print ("start-end", start, end)
42 bitlen = end-start+1
43 half = divpoint
44 lowermask = (1<<half)-1
45 uppermask = (1<<(bitlen-half))-1
46 table_entries = {}
47 # debug-print all opcodes first
48 opcode_per_insn = {}
49 for insn in insns:
50 opcodes = []
51 for op in insn.ppc: # insn.ppc is a MultiPPCRecord which is a tuple
52 opcodes.append(op.opcode)
53 for op in opcodes:
54 print ("op", insn.name, op)
55 if insn.name not in opcode_per_insn:
56 opcode_per_insn[insn.name] = []
57 opcode_per_insn[insn.name] += opcodes
58
59 # along the way work out the maximum length of the instruction name
60 # that goes into the table.
61 maxnamelen = 0
62
63 # for every possible XO value, work out the row and column as lower and
64 # upper halves, and if there is a opcode match put the instruction
65 # name into that XO table_entry
66
67 for XO in range(1<<bitlen):
68 # calculate row, column
69 lower = XO & lowermask
70 upper = (XO>>half) & uppermask
71 print ("search", XO, bin(XO), bin(lower), bin(upper))
72 if upper not in table_entries: # really should use defaultdict here
73 table_entries[upper] = {}
74 table_entries[upper][lower] = None
75 # hunt through all instructions, check XO against value/mask
76 for insn in insns:
77 opcode = opcode_per_insn[insn.name]
78 for op in opcode:
79 #print (" search", XO, hex(key), insn.name,
80 # hex(op.value), hex(op.mask))
81 if ((op.value & op.mask) == (XO & op.mask)):
82 print (" match", bin(XO), insn.name)
83 assert table_entries[upper][lower] is None, \
84 "entry %d %d should be empty " \
85 "contains %s conflicting %s" % \
86 (lower, upper, str(table_entries[upper][lower]),
87 insn.name)
88 table_entries[upper][lower] = insn.name
89 maxnamelen = max(maxnamelen, len(insn.name))
90 continue
91
92 print (table_entries)
93 # now got the table: print it out
94
95 table = []
96 line = [" "*6]
97 for j in range(1<<(half)):
98 hdr = binmaxed(half, j)
99 line.append(maxme(maxnamelen, hdr))
100 line.append(" "*6)
101 table.append("|" + "|".join(line) + "|")
102 line = ["-"*6] + ["-"*maxnamelen] * (1<<(half)) + ["-"*6]
103 table.append("|" + "|".join(line) + "|")
104
105 for i in range(1<<(bitlen-half)):
106 hdr = binmaxed(6, i)
107 line = [hdr]
108 for j in range(1<<(half)):
109 line.append(maxme(maxnamelen, table_entries[i][j] or " "))
110 line.append(hdr)
111 table.append("|" + "|".join(line) + "|")
112
113 print ("\n".join(table))
114
115 do_table('minor_30.csv', insns, sections, divpoint=2)
116 #do_table('minor_22.csv', insns, sections, divpoint=5)
117