3 # Utility to decode register values
4 # Copyright (c) 2006 Jeremy Kerr <jk@ozlabs.org>
5 # Released under the GNU General Public License version 2 or later
7 # Documentation and updates at: http://ozlabs.org/~jk/code/bitfield
12 from pyparsing import Literal, Word, ZeroOrMore, Group, Dict, Optional, \
13 printables, ParseException, restOfLine
14 from getopt import getopt, GetoptError
16 conf = os.path.join(os.getenv("HOME"), ".bitfields.conf")
19 def __init__(self, start_bit, end_bit, name):
20 self.start_bit = start_bit
21 self.end_bit = end_bit
32 return 1 + self.end_bit - self.start_bit
34 def add_value(self, value, description):
35 self.values[int(value)] = description
37 def mask(self, reg_width, value):
38 shift = (reg_width - 1) - self.end_bit
39 return (((2 ** self.width() - 1) << (shift))
42 def value(self, value):
43 if value in self.values:
44 return self.values[value]
48 return "[%2d:%-2d] %s 0x%x" % (int(self.start_bit),
49 int(self.end_bit), self.name, self.mask())
52 def parse_bitfield(line):
53 a = line.split(None, 1)
59 if range_str.find(':') != -1:
60 r = range_str.split(":")
61 range = (int(r[0]),int(r[1]))
63 range = (int(range_str),int(range_str))
65 return bitfield(range[0], range[1], name)
68 def parse_value(line):
69 a = line.split(None, 1)
75 def __init__(self, name, width):
80 def add_field(self, field,):
81 self.fields.append(field)
83 def decode(self, value):
84 field_width = (self.width + 3) / 4
85 name_width = max(map(lambda f: len(f.name), self.fields))
86 str = "0x%0*lx [%d]\n" % (field_width, value, value)
87 for field in self.fields:
88 v = field.mask(self.width, value);
91 str += "%*s: 0x%s [%s]\n" \
92 % (name_width, field.name, v, desc)
94 str += "%*s: 0x%x\n" \
95 % (name_width, field.name, v)
99 str = self.name + "\n"
100 for f in self.fields:
105 for (id, r) in regs.iteritems():
106 print "%18s : %s" % (id, r.name)
108 def search_regs(regs, str):
109 return dict((k, regs[k]) for k in regs \
110 if str.lower() in regs[k].name.lower() + k.lower())
112 class ConfigurationError(Exception):
113 def __init__(self, file, message):
115 self.message = message
117 def parse_config(file):
118 lbrack = Literal("[").suppress()
119 rbrack = Literal("]").suppress()
120 colon = Literal(":").suppress()
123 comment = semi + Optional( restOfLine )
125 nonrbrack = "".join( [ c for c in printables if c != "]" ] ) + " \t"
126 nonequals = "".join( [ c for c in printables if c != ":" ] ) + " \t"
128 sectionDef = lbrack + Word( nonrbrack ) + rbrack
129 keyDef = ~lbrack + Word( nonequals ) + colon + restOfLine
131 bnf = Dict(ZeroOrMore(Group(sectionDef + ZeroOrMore(Group(keyDef)))))
136 tokens = bnf.parseString("".join(f.readlines()))
144 # default to 64 bit registers
153 elif t[0] == 'width':
155 elif t[0] == 'field':
156 f = bitfield.parse_bitfield(t[1])
158 raise ConfigurationError(file,
159 "Invalid field in %s" % id)
161 elif t[0] == 'value':
164 raise ConfigurationError(file,
165 "No field for value in %s" % id)
166 v = bitfield.parse_value(t[1])
168 raise ConfigurationError(file,
169 "Invalid value in %s" % id)
170 f.add_value(v[0], v[1])
172 if name is None or name == '':
173 raise ConfigurationError(file,
174 "No name for entry %s" %id)
177 raise ConfigurationError(file,
178 "Register %s has no fields" % id)
180 r = register(name, width)
190 print "Usage: %s <-l> | <-s pattern> | register [value...]" % prog
194 (opts, args) = getopt(sys.argv[1:], "hls:", \
195 ["help", "list", "search="])
201 regs = parse_config(conf)
203 except ConfigurationError, e:
204 print "Error parsing configuration file %s:\n\t%s" % \
209 if o in ("-h", "--help"):
213 if o in ("-l", "--list"):
217 if o in ("-s", "--search"):
218 list_regs(search_regs(regs, a))
227 if not regs.has_key(a):
228 print "No such register '%s'. Valid regs are:" % a
233 print "decoding as %s" % r.name
239 values = sys.stdin.readlines()
240 except KeyboardInterrupt, e:
244 i = long(value.strip(), 0)
249 if __name__ == "__main__":