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