OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [tools/] [pyelf/] [aistruct.py] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
import mmap
2
import struct
3
import os
4
 
5
class GFile(object):
6
        def __init__(self, filename, size):
7
                handle = open(filename, 'rb+')
8
                self.mapping = mmap.mmap(handle.fileno(), size)
9
 
10
        def set_byte_ordering(self, ordering):
11
                self.byte_ordering = ordering
12
 
13
        def get_byte_ordering(self):
14
                return self.byte_ordering
15
 
16
        def create_new(filename, size):
17
                assert size < 10240 # This is only for testing, really
18
                handle = open(filename, 'wb')
19
                handle.write('\0' * size)
20
                handle.close()
21
                return GFile(filename, size)
22
        create_new = staticmethod(create_new)
23
 
24
        def existing(filename):
25
                assert os.path.exists(filename)
26
                size = os.path.getsize(filename)
27
                return GFile(filename, size)
28
        existing = staticmethod(existing)
29
 
30
class BitPoker(object):
31
        """ """
32
        SIZE_MAP = {1: 'B',
33
                2: 'H',
34
                4: 'I',
35
                8: 'Q'}
36
        def set_mmapfile(self, mmapfile, offset_bytes = 0):
37
                self.mmapfile = mmapfile
38
                self.master_offset_bytes = offset_bytes
39
 
40
        def set_byte_ordering(self, byte_ordering):
41
                self.byte_ordering = byte_ordering
42
                self.struct_byte_ordering = {'lsb': '<', 'msb': '>'}[byte_ordering]
43
 
44
        def get_byte_ordering(self):
45
                return self.byte_ordering
46
 
47
        def read_value(self, numbytes, offset_bytes):
48
                # Seek to the right spot using absolute (whence=0) positioning
49
                self.mmapfile.seek(offset_bytes + self.master_offset_bytes, 0)
50
                data = self.mmapfile.read(numbytes)
51
                return struct.unpack('%s%s' % (self.struct_byte_ordering,
52
                                self.SIZE_MAP[numbytes]), data)
53
 
54
        def write_value_sized(self, value, numbytes, offset_bytes):
55
                data = struct.pack('%s%s' % (self.struct_byte_ordering,
56
                                self.SIZE_MAP[numbytes]), value)
57
                self.mmapfile.seek(offset_bytes + self.master_offset_bytes, 0)
58
                self.mmapfile.write(data)
59
 
60
        def read_value_sized(self, numbytes, offset_bytes):
61
                self.mmapfile.seek(offset_bytes + self.master_offset_bytes, 0)
62
                raw_data = self.mmapfile.read(numbytes)
63
                data = struct.unpack('%s%s' % (self.struct_byte_ordering,
64
                                self.SIZE_MAP[numbytes]), raw_data)
65
                return data[0]
66
 
67
        def read_c_string(self, offset_bytes):
68
                self.mmapfile.seek(offset_bytes + self.master_offset_bytes.get(), 0)
69
                result = ''
70
                c = self.mmapfile.read_byte()
71
                while c != '\0':
72
                        result += c
73
                        c = self.mmapfile.read_byte()
74
                return result
75
 
76
        def new_with_gfile(gfile, offset):
77
                poker = BitPoker()
78
                poker.set_mmapfile(gfile.mapping, offset)
79
                poker.set_byte_ordering(gfile.get_byte_ordering())
80
                return poker
81
        new_with_gfile = staticmethod(new_with_gfile)
82
 
83
        def new_with_poker(origpoker, offset):
84
                poker = BitPoker()
85
                poker.set_mmapfile(origpoker.mmapfile, origpoker.master_offset_bytes + offset)
86
                poker.set_byte_ordering(origpoker.get_byte_ordering())
87
                return poker
88
        new_with_poker = staticmethod(new_with_poker)
89
 
90
class AIStruct(object):
91
        SIZE32 = 32
92
        SIZE64 = 64
93
 
94
        class AIElement(object):
95
                _natural_size = None
96
                def __init__(self, word_size_in_bits, offset, names, format):
97
                        self.offset = offset #offset into memory-mapped file.
98
                        self.set_target_word_size(word_size_in_bits)
99
                        self.value = 0
100
                        self.names = names
101
                        self.format = format
102
 
103
                def set_target_word_size(self, target_word_size):
104
                        self.target_word_size = target_word_size
105
 
106
                def get_size_bits(self):
107
                        return self._natural_size
108
 
109
                def set_args(self):
110
                        pass
111
 
112
                def set(self, value):
113
                        if type(value) is str and len(value) == 1:
114
                                value = ord(value)
115
                        self.value = value
116
 
117
                def get(self):
118
                        return self.value
119
 
120
                def write(self, bitpoker):
121
                        bitpoker.write_value_sized(self.value, self.get_size_bits() / 8,
122
                                        self.offset)
123
 
124
                def read(self, bitpoker):
125
                        self.value = bitpoker.read_value_sized(self.get_size_bits() / 8, self.offset)
126
 
127
                def __cmp__(self, value):
128
                        return cmp(self.value, value)
129
 
130
                def __add__(self, other):
131
                        if  isinstance(other, AIStruct.AIElement):
132
                                return self.value + other.value
133
                        else:
134
                                return self.value + other
135
 
136
                def __mul__(self, other):
137
                        if  isinstance(other, AIStruct.AIElement):
138
                                return self.value * other.value
139
                        else:
140
                                return self.value * other
141
 
142
 
143
                def __str__(self):
144
                        if self.format:
145
                                if type(self.format) == type(""):
146
                                        return self.format % self.value
147
                                else:
148
                                        return self.format(self.value)
149
                        if self.names:
150
                                return self.names.get(self.value, str(self.value))
151
                        else:
152
                                return str(self.value)
153
 
154
        class WORD(AIElement):
155
                def get_size_bits(self):
156
                        return self.target_word_size
157
 
158
        class INT8(AIElement):
159
                _natural_size = 8
160
        UINT8 = INT8
161
 
162
        class INT16(AIElement):
163
                _natural_size = 16
164
        UINT16 = INT16
165
 
166
        class INT32(AIElement):
167
                _natural_size = 32
168
        UINT32 = INT32
169
 
170
        class INT64(AIElement):
171
                _natural_size = 64
172
        UINT64 = INT64
173
 
174
        class BITFIELD(AIElement):
175
                class AttributeBasedProperty(object):
176
                        def __init__(self, bitfield_inst):
177
                                self.bitfield_inst = bitfield_inst
178
 
179
                        def get_length_and_offset_for_key(self, key):
180
                                offset = 0
181
                                length = 0
182
                                for name, sizes_dict in self.bitfield_inst.components:
183
                                        if name == key:
184
                                                length = sizes_dict[self.bitfield_inst.target_word_size]
185
                                                break
186
                                        offset += sizes_dict[self.bitfield_inst.target_word_size]
187
                                if length == 0:
188
                                        raise AttributeError(key)
189
                                return length, offset
190
 
191
                        def __getitem__(self, key):
192
                                length, offset = self.get_length_and_offset_for_key(key)
193
                                # We have the position of the desired key in value.
194
                                # Retrieve it by right-shifting by "offset" and
195
                                # then masking away anything > length.
196
                                result = self.bitfield_inst.value >> offset
197
                                result &= ( (1<<length) - 1)
198
                                if self.bitfield_inst.post_get is not None:
199
                                        return self.bitfield_inst.post_get(key, result)
200
                                else:
201
                                        return result
202
 
203
                        def __setitem__(self, key, new_value):
204
                                if self.bitfield_inst.pre_set is not None:
205
                                        new_value = self.bitfield_inst.pre_set(key, new_value)
206
                                length, offset = self.get_length_and_offset_for_key(key)
207
                                assert new_value < (1 << length)
208
                                # Generate the result in three stages
209
                                # ... insert the new value:
210
                                result = new_value << offset
211
                                # ... | the stuff above the value:
212
                                result |= ( self.bitfield_inst.value >> (offset + length) << (offset + length) )
213
                                # ... | the stuff below the value.
214
                                result |= ( self.bitfield_inst.value & ( (1 << offset) - 1 ) )
215
                                self.bitfield_inst.value = result
216
 
217
                def __init__(self, *args, **kwargs):
218
                        super(AIStruct.BITFIELD, self).__init__(*args, **kwargs)
219
                        self.components = []
220
                        self.attribute_based_property = AIStruct.BITFIELD.AttributeBasedProperty(self)
221
 
222
                def set_args(self, components=None, post_get=None, pre_set=None):
223
                        if components is not None:
224
                                self.components = components
225
                        self.post_get = post_get
226
                        self.pre_set = pre_set
227
 
228
                def get_size_bits(self):
229
                        size_bits = 0
230
                        for comp_name, comp_sizes in self.components:
231
                                size_bits += comp_sizes[self.target_word_size]
232
                        return size_bits
233
 
234
                def get(self):
235
                        return self.attribute_based_property
236
 
237
                def set(self, value):
238
                        raise AttributeError("set() shouldn't be called here!")
239
 
240
        def __init__(self, word_size_in_bits):
241
                self.word_size_in_bits = word_size_in_bits
242
                self.thestruct = []
243
 
244
        def _setup_attributes(self, allprops):
245
                # So Python sucks and you can only set properties on class objects,
246
                # not class instance objects. Hence this crud...
247
                class AI(object):
248
                        pass
249
                for key in allprops:
250
                        setattr(AI, key, allprops[key])
251
                self.ai = AI()
252
 
253
        def _setup_one(self, etypename, ename, args, offset, names, format):
254
                elementclass = getattr(self, etypename)
255
                elementinst = elementclass(self.word_size_in_bits, offset, names, format)
256
                elementinst.set_args(**args)
257
                self.thestruct.append(elementinst)
258
                def get_item(obj):
259
                        return elementinst
260
                def set_item(obj, value):
261
                        return elementinst.set(value)
262
                newprop = {'%s' % (ename): property(get_item, set_item)}
263
                return (elementinst.get_size_bits() / 8, newprop)
264
 
265
        def _setup_multiprop(self, ename, times):
266
                def mp_get(obj):
267
                        return [getattr(self.ai, '%s_%s' % (ename, counter)) for counter in range(1, times+1)]
268
                def mp_set(obj, value):
269
                        for num, item in enumerate(value):
270
                                setattr(self.ai, '%s_%s' % (ename, num + 1), item)
271
                return {'%s' % (ename): property(mp_get, mp_set)}
272
 
273
        def setup(self, *elements):
274
                offset = 0
275
                allprops = {}
276
                for element in elements:
277
                        etypename, ename = element[:2]
278
                        args = {}
279
                        if len(element) == 3:
280
                                args = element[2]
281
                        times = args.get('times', None)
282
                        names = args.get('names', None)
283
                        format = args.get('format', None)
284
                        if names is not None:
285
                                del args['names']
286
                        if format is not None:
287
                                del args['format']
288
                        if times is not None:
289
                                del args['times']
290
                                for time in range(times):
291
                                        size, propdict = self._setup_one(etypename, '%s_%s' % (ename, time + 1), args, offset, names, format)
292
                                        offset += size
293
                                        allprops.update(propdict)
294
                                allprops.update(self._setup_multiprop(ename, times))
295
                        else:
296
                                size, propdict = self._setup_one(etypename, ename, args, offset, names, format)
297
                                offset += size
298
                                allprops.update(propdict)
299
 
300
 
301
                self._setup_attributes(allprops)
302
 
303
        def struct_size(self):
304
                size = 0
305
                for element in self.thestruct:
306
                        size += element.get_size_bits()
307
                return size / 8
308
 
309
        def set_poker(self, poker):
310
                self.poker = poker
311
 
312
        def write(self):
313
                for element in self.thestruct:
314
                        element.write(self.poker)
315
 
316
        def read_from_poker(self, poker):
317
                self.set_poker(poker)
318
                for element in self.thestruct:
319
                        element.read(self.poker)
320
 
321
        def write_new(self, filename):
322
                """convenience function to create a new file and store the KCP in it. """
323
                newfile = GFile.create_new(filename, self.struct_size())
324
                poker = BitPoker('lsb') #FIXME
325
                poker.set_mmapfile(newfile.mapping, offset_bytes = 0)
326
                self.set_poker(poker)
327
                self.write()

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.