diff options
author | Joakim Sindholt <opensource@zhasha.com> | 2009-09-29 20:46:17 +0200 |
---|---|---|
committer | Joakim Sindholt <opensource@zhasha.com> | 2009-09-29 20:46:17 +0200 |
commit | 86c0b9917af583f3b933ef586da8a60737714e3d (patch) | |
tree | e5872cabc65c8bd39ccb6ff3d5b8fd4a8fdb331e /radeonreg.py |
Initial commit
Diffstat (limited to 'radeonreg.py')
-rwxr-xr-x | radeonreg.py | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/radeonreg.py b/radeonreg.py new file mode 100755 index 0000000..a7aeb3f --- /dev/null +++ b/radeonreg.py @@ -0,0 +1,300 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import re + +class RadeonReg: + def __init__(self, unit, name, count, access, addr, stride, desc): + self.unit = unit + self.name = name + self.desc = desc + self.count = count + self.access = access + self.addr = addr + self.fields = [] + self.stride = stride + + def equals(self, rhs): + if self.unit != rhs.unit or \ + self.name != rhs.name or \ + self.desc != rhs.desc or \ + self.count != rhs.count or \ + self.access != rhs.access or \ + self.addr != rhs.addr or \ + self.stride != rhs.stride or \ + len(self.fields) != len(rhs.fields): return False + + for i in xrange(len(self.fields)): + if not self.fields[i].equals(rhs.fields[i]): return False + + return True + +class RadeonField: + def __init__(self, name, low, high, desc): + self.name = name + self.desc = desc + self.low = low if low <= high else high + self.high = high if high >= low else low + self.enum = None + + def equals(self, rhs): + if self.name == rhs.name and \ + self.desc == rhs.desc and \ + self.low == rhs.low and \ + self.high == rhs.high and \ + self.enum == rhs.enum: return True + return False + +class EnumEntry: + def __init__(self, val, name, desc): + self.val = val + self.name = name + self.desc = desc + +class RadeonEnum: + def __init__(self): + self.entries = [] + self.refs = 0 + + def add(self, val, name, desc): + self.entries.append(EnumEntry(val, name, desc)) + + def reference(self): + self.refs = self.refs + 1 + + def equals(self, rhs): + if len(self.entries) != len(rhs.entries): return False + for i in xrange(len(self.entries)): + if self.entries[i].val != rhs.entries[i].val: return False + if self.entries[i].name != rhs.entries[i].name: return False + if self.entries[i].desc != rhs.entries[i].desc: return False + return True + +enums = [] +def AddEnum(e): + for i in xrange(len(enums)): + if e.equals(enums[i]): + return i + enums.append(e) + return len(enums)-1 + +enum_regex = re.compile('(\d\d?)( - |: |=)((?:(?!\d\d?(?: - |: |=)).)*)', re.DOTALL) +enum_desc = re.compile('(\d\d?( - |: |=)|POSSIBLE VALUES:)') +enum_ename = re.compile('([A-Za-z0-9_]*)') +reserved_regex = re.compile('[Rr][Ee][Ss][Ee][Rr][Vv][Ee][Dd]') +def ExtractEnum(s): + dl = s.split('\n') + d = '' + for line in dl: + if enum_desc.match(line): break + d += ' ' + line + d = StripSpaces(d) + + enum = RadeonEnum() + m = enum_regex.findall(s) + for entry in m: + val = int(entry[0]) + desc = StripSpaces(entry[2].replace('\n', ' ')) + if reserved_regex.search(desc): continue + name = StripUnders(enum_ename.match(desc.replace(' ', '_')).group(1).upper()) + enum.add(val, name, desc) + + if len(enum.entries) == 0: enum = None + return [d, enum] + +subs = [re.compile('^.+ 2008 Advanced Micro Devices, Inc.$'), + re.compile('^Proprietary *[0-9]*$'), + re.compile('^. *Revision [0-9\.]* *[A-Za-z]* [0-9]{1,2}, [0-9]*$'), + re.compile('^.$'), + re.compile('^ *$'), + re.compile('\n'), + re.compile('^[0-9]+.[0-9]+ .* Registers.*$'), + re.compile('^\(Access: [RW]\)')] +stupid_linebreaks = re.compile('-\n0x') +def ReadPDFDump(filename): + pdffile = open(filename, 'r') + pdflines = pdffile.readlines() + pdffile.close() + + formatted = '' + for line in pdflines: + out = line + for regex in subs: + out = regex.sub('', out) + + if out != '': + formatted += out + '\n' + + formatted = stupid_linebreaks.sub('-0x', formatted); + return formatted + '\n' + +spaces = re.compile(' +') +spaces_end = re.compile('(^ | $)', re.MULTILINE) +def StripSpaces(s): + return spaces_end.sub('', spaces.sub(' ', s)) + +uscores = re.compile('_+') +uscores_end = re.compile('(^_|_$)', re.MULTILINE) +def StripUnders(s): + return uscores_end.sub('', uscores.sub('_', s)) + +reg_regex = re.compile( +'([A-Za-z0-9_]{1,4}):([A-Za-z0-9_]+)(\[([0-9]+)-([0-9]+)\]?|)([A-Za-z0-9_]*).*\[([RW\/]+)\].*[^,]? ?MMReg:0x([0-9A-Fa-f]{1,6})(-0x([0-9A-Fa-f]{1,6})|).*' +'(\nDESCRIPTION: (.*(\n.*)*?))?' +'\nField Name +.*? +Description.*\n' +'([^ยท]*\n)+' +) +field_regex = re.compile( +'([A-Za-z0-9_]+) +([0-9]{1,2})(:([0-9]{1,2})|) +(0x[0-9A-Fa-f]+|[Nn]one) +(.*(\n +.*)*)' +) + +def FormatPDFDump(pdf): + regs = [] + m = reg_regex.findall(pdf) + for reg in m: + unit = reg[0] + name = StripUnders(reg[1] + '_' + reg[5]) + addr = [ int(reg[7], 16), int(reg[9], 16) if reg[9] != '' else int(reg[7], 16) ] + access = reg[6].lower().replace('/', '') + count = (int(reg[4]) - int(reg[3]) + 1) if reg[3] != '' and reg[4] != '' else 1 + stride = ((addr[1] - addr[0]) / (count - 1)) if count > 1 else 4 + desc = StripSpaces(reg[11].replace('\n', ' ')) + regs.append(RadeonReg(unit, name, count, access, addr[0], stride, desc)) + + f = field_regex.findall(reg[13]) + for field in f: + fname = field[0] + fbits = [ int(field[1]), int(field[3]) if field[3] != '' else int(field[1]) ] + fdesc = StripSpaces(field[5]) + regs[-1].fields.append(RadeonField(fname, fbits[1], fbits[0], fdesc)) + + e = ExtractEnum(fdesc) + regs[-1].fields[-1].desc = e[0] + if e[1] != None: regs[-1].fields[-1].enum = AddEnum(e[1]) + + if len(regs[-1].fields) > 0: + if regs[-1].fields[0].low == 0 and regs[-1].fields[0].high == 31: + regs[-1].fields = [] + + return regs + +def CompareRegs(regs1, regs2): + regs_a = [] + regs_b = [] + regs_both = [] + + for r1r in regs1: + for r2r in regs2: + if r1r.equals(r2r): regs_both.append(r1r) + + for r1r in regs1: + inboth = False + for rb in regs_both: + if r1r.equals(rb): inboth = True + + if not inboth: + regs_a.append(r1r) + + for r2r in regs2: + inboth = False + for rb in regs_both: + if r2r.equals(rb): inboth = True + + if not inboth: + regs_b.append(r2r) + + return [regs_both, regs_a, regs_b] + +def XMLTags(s): + return s.replace('&', '&').replace('>', '>').replace('<', '<') + +def PrintEnum(enum, indent): + for entry in enums[enum].entries: + print indent + '<value value="%d" name="%s"><doc>%s</doc></value>' % (entry.val, entry.name, XMLTags(entry.desc)) + +def XMLGroup(regs, gname, prepend): + print '<group name="%s" prepend="%s_">' % (gname, prepend) + for reg in regs: + indent = ' ' + + if len(reg.fields) < 1 and reg.desc == '': + regstr = '<reg32 name="%s" access="%s" offset="0x%%04X" />' % (reg.name, reg.access) + else: + regstr = '<reg32 name="%s" access="%s" offset="0x%%04X">' % (reg.name, reg.access) + regstr += '\n' + indent + ' <doc>%s</doc>' % XMLTags(reg.desc) + + if reg.count > 1: + print ' <stripe offset="0x%04X" stride="0x%04X" length="%d">' % (reg.addr, reg.stride, reg.count) + print ' ' + regstr % 0 + indent += ' ' + else: + print ' ' + regstr % reg.addr + + for field in reg.fields: + print indent + ' <bitfield name="%s" high="%d" low="%d">' % (field.name, field.high, field.low) + print indent + ' <doc>%s</doc>' % XMLTags(field.desc) + + if field.enum != None: + if enums[field.enum].refs == 1: + PrintEnum(field.enum, indent + ' ') + else: + print indent + ' <use-enum ref="ENUM%d" />' % field.enum + + print indent + ' </bitfield>' + + if len(reg.fields) > 0 or reg.desc != '': + print indent + '</reg32>' + + if reg.count > 1: + print ' </stripe>' + print '</group>\n' + +def CreateXML(regs, variants): + print '<?xml version="1.0" encoding="UTF-8"?>' + print '<database xmlns="http://nouveau.freedesktop.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="rules-ng.xsd">' + print '<domain name="R300" />' + print '' + for i in xrange(len(enums)): + if enums[i].refs > 1: + print '<enum name="ENUM%d">' % i + PrintEnum(i, ' ') + print '</enum>' + print '' + + for (group, name, prepend) in regs: + XMLGroup(group, name, prepend) + + for (name, groups) in variants: + print '<variant id="%s">' % name + for group in groups: + print ' <use-group ref="%s" />' % group + print '</variant>' + + print '</database>' + +def ReferenceEnums(regs): + for reg in regs: + for field in reg.fields: + if field.enum != None: + enums[field.enum].reference() + +r300regs = FormatPDFDump(ReadPDFDump('R3xx_3D_Registers.txt')) +r500regs = FormatPDFDump(ReadPDFDump('R5xx_Acceleration_v1.3.txt')) +finalregs = CompareRegs(r300regs, r500regs) +regs_both = finalregs[0] +regs_r300 = finalregs[1] +regs_r500 = finalregs[2] +ReferenceEnums(regs_both) +ReferenceEnums(regs_r300) +ReferenceEnums(regs_r500) +CreateXML( + [ + [regs_both, 'rX00_regs', 'R300'], + [regs_r300, 'r300_regs', 'R300'], + [regs_r500, 'r500_regs', 'R500'] + ], + [ + ['r300', ['rX00_regs', 'r300_regs']], + ['r500', ['rX00_regs', 'r500_regs']] + ] +) |