summaryrefslogtreecommitdiff
path: root/radeonreg.py
diff options
context:
space:
mode:
authorJoakim Sindholt <opensource@zhasha.com>2009-09-29 20:46:17 +0200
committerJoakim Sindholt <opensource@zhasha.com>2009-09-29 20:46:17 +0200
commit86c0b9917af583f3b933ef586da8a60737714e3d (patch)
treee5872cabc65c8bd39ccb6ff3d5b8fd4a8fdb331e /radeonreg.py
Initial commit
Diffstat (limited to 'radeonreg.py')
-rwxr-xr-xradeonreg.py300
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('&', '&amp;').replace('>', '&gt;').replace('<', '&lt;')
+
+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']]
+ ]
+)