allow FieldSelectableInt to initialise from list or tuple
[soc.git] / src / soc / decoder / selectable_int.py
1 import unittest
2 from copy import copy
3 from soc.decoder.power_fields import BitRange
4 from operator import (add, sub, mul, div, mod, or_, and_, xor, neg, inv)
5
6
7 def check_extsign(a, b):
8 if b.bits != 256:
9 return b
10 return SelectableInt(b.value, a.bits)
11
12
13 class FieldSelectableInt:
14 """FieldSelectableInt: allows bit-range selection onto another target
15 """
16 def __init__(self, si, br):
17 self.si = si # target selectable int
18 if isinstance(br, list) or isinstance(br, tuple):
19 _br = BitRange()
20 for i, v in enumerate(br):
21 _br[i] = v
22 br = _br
23 self.br = br # map of indices.
24
25 def _op(self, op, b):
26 vi = self.get_range()
27 vi = op(vi + b)
28 return self.merge(vi)
29
30 def _op1(self, op):
31 vi = self.get_range()
32 vi = op(vi)
33 return self.merge(vi)
34
35 def __getitem__(self, key):
36 key = self.br[key]
37 return self.si[key]
38
39 def __setitem__(self, key, value)
40 key = self.br[key]
41 return self.si__setitem__(key, value)
42
43 def __negate__(self):
44 return self._op1(negate)
45 def __invert__(self):
46 return self._op1(inv)
47 def __add__(self, b):
48 return self._op(add, b)
49 def __sub__(self, b):
50 return self._op(sub, b)
51 def __mul__(self, b):
52 return self._op(mul, b)
53 def __div__(self, b):
54 return self._op(div, b)
55 def __and__(self, b):
56 return self._op(and_, b)
57 def __or__(self, b):
58 return self._op(or_, b)
59 def __xor__(self, b):
60 return self._op(xor, b)
61
62 def get_range(self):
63 print ("get_range", self.si)
64 vi = SelectableInt(0, len(self.br))
65 for k, v in self.br.items():
66 print ("get_range", k, v, self.si[v])
67 vi[k] = self.si[v]
68 print ("get_range", vi)
69 return vi
70
71 def merge(self, vi):
72 fi = copy(self)
73 for i, v in fi.br.items():
74 fi.si[v] = vi[i]
75 return fi
76
77 def __repr__(self):
78 return "FieldSelectableInt(si=%s, br=%s)" % (self.si, self.br)
79
80
81 class FieldSelectableIntTestCase(unittest.TestCase):
82 def test_arith(self):
83 a = SelectableInt(0b10101, 5)
84 b = SelectableInt(0b011, 3)
85 br = BitRange()
86 br[0] = 0
87 br[1] = 2
88 br[2] = 3
89 fs = FieldSelectableInt(a, br)
90 c = fs + b
91 print (c)
92 #self.assertEqual(c.value, a.value + b.value)
93
94
95 class SelectableInt:
96 def __init__(self, value, bits):
97 mask = (1 << bits) - 1
98 self.value = value & mask
99 self.bits = bits
100
101 def __add__(self, b):
102 if isinstance(b, int):
103 b = SelectableInt(b, self.bits)
104 b = check_extsign(self, b)
105 assert b.bits == self.bits
106 return SelectableInt(self.value + b.value, self.bits)
107
108 def __sub__(self, b):
109 if isinstance(b, int):
110 b = SelectableInt(b, self.bits)
111 b = check_extsign(self, b)
112 assert b.bits == self.bits
113 return SelectableInt(self.value - b.value, self.bits)
114
115 def __mul__(self, b):
116 b = check_extsign(self, b)
117 assert b.bits == self.bits
118 return SelectableInt(self.value * b.value, self.bits)
119
120 def __div__(self, b):
121 b = check_extsign(self, b)
122 assert b.bits == self.bits
123 return SelectableInt(self.value / b.value, self.bits)
124
125 def __mod__(self, b):
126 b = check_extsign(self, b)
127 assert b.bits == self.bits
128 return SelectableInt(self.value % b.value, self.bits)
129
130 def __or__(self, b):
131 b = check_extsign(self, b)
132 assert b.bits == self.bits
133 return SelectableInt(self.value | b.value, self.bits)
134
135 def __and__(self, b):
136 b = check_extsign(self, b)
137 assert b.bits == self.bits
138 return SelectableInt(self.value & b.value, self.bits)
139
140 def __xor__(self, b):
141 b = check_extsign(self, b)
142 assert b.bits == self.bits
143 return SelectableInt(self.value ^ b.value, self.bits)
144
145 def __invert__(self):
146 return SelectableInt(~self.value, self.bits)
147
148 def __neg__(self):
149 return SelectableInt(~self.value + 1, self.bits)
150
151 def __getitem__(self, key):
152 if isinstance(key, int):
153 assert key < self.bits, "key %d accessing %d" % (key, self.bits)
154 assert key >= 0
155 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
156 # MSB is indexed **LOWEST** (sigh)
157 key = self.bits - (key + 1)
158
159 value = (self.value >> key) & 1
160 return SelectableInt(value, 1)
161 elif isinstance(key, slice):
162 assert key.step is None or key.step == 1
163 assert key.start < key.stop
164 assert key.start >= 0
165 assert key.stop <= self.bits
166
167 stop = self.bits - key.start
168 start = self.bits - key.stop
169
170 bits = stop - start + 1
171 mask = (1 << bits) - 1
172 value = (self.value >> start) & mask
173 return SelectableInt(value, bits)
174
175 def __setitem__(self, key, value):
176 if isinstance(key, int):
177 assert key < self.bits
178 assert key >= 0
179 key = self.bits - (key + 1)
180 if isinstance(value, SelectableInt):
181 assert value.bits == 1
182 value = value.value
183
184 value = value << key
185 mask = 1 << key
186 self.value = (self.value & ~mask) | (value & mask)
187 elif isinstance(key, slice):
188 assert key.step is None or key.step == 1
189 assert key.start < key.stop
190 assert key.start >= 0
191 assert key.stop <= self.bits
192
193 stop = self.bits - key.start
194 start = self.bits - key.stop
195
196 bits = stop - start + 1
197 if isinstance(value, SelectableInt):
198 assert value.bits == bits, "%d into %d" % (value.bits, bits)
199 value = value.value
200 mask = ((1 << bits) - 1) << start
201 value = value << start
202 self.value = (self.value & ~mask) | (value & mask)
203
204 def __ge__(self, other):
205 if isinstance(other, SelectableInt):
206 other = check_extsign(self, other)
207 assert other.bits == self.bits
208 other = other.value
209 if isinstance(other, int):
210 return other >= self.value
211 assert False
212
213 def __le__(self, other):
214 if isinstance(other, SelectableInt):
215 other = check_extsign(self, other)
216 assert other.bits == self.bits
217 other = other.value
218 if isinstance(other, int):
219 return onebit(other <= self.value)
220 assert False
221
222 def __gt__(self, other):
223 if isinstance(other, SelectableInt):
224 other = check_extsign(self, other)
225 assert other.bits == self.bits
226 other = other.value
227 if isinstance(other, int):
228 return onebit(other > self.value)
229 assert False
230
231 def __lt__(self, other):
232 if isinstance(other, SelectableInt):
233 other = check_extsign(self, other)
234 assert other.bits == self.bits
235 other = other.value
236 if isinstance(other, int):
237 return onebit(other < self.value)
238 assert False
239
240 def __eq__(self, other):
241 if isinstance(other, SelectableInt):
242 other = check_extsign(self, other)
243 assert other.bits == self.bits
244 other = other.value
245 if isinstance(other, int):
246 return onebit(other == self.value)
247 assert False
248
249 def narrow(self, bits):
250 assert bits <= self.bits
251 return SelectableInt(self.value, bits)
252
253 def __bool__(self):
254 return self.value != 0
255
256 def __repr__(self):
257 return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
258 self.bits)
259
260 def onebit(bit):
261 return SelectableInt(1 if bit else 0, 1)
262
263 def selectltu(lhs, rhs):
264 """ less-than (unsigned)
265 """
266 if isinstance(rhs, SelectableInt):
267 rhs = rhs.value
268 return onebit(lhs.value < rhs)
269
270 def selectgtu(lhs, rhs):
271 """ greater-than (unsigned)
272 """
273 if isinstance(rhs, SelectableInt):
274 rhs = rhs.value
275 return onebit(lhs.value > rhs)
276
277
278 # XXX this probably isn't needed...
279 def selectassign(lhs, idx, rhs):
280 if isinstance(idx, tuple):
281 if len(idx) == 2:
282 lower, upper = idx
283 step = None
284 else:
285 lower, upper, step = idx
286 toidx = range(lower, upper, step)
287 fromidx = range(0, upper-lower, step) # XXX eurgh...
288 else:
289 toidx = [idx]
290 fromidx = [0]
291 for t, f in zip(toidx, fromidx):
292 lhs[t] = rhs[f]
293
294
295 def selectconcat(*args, repeat=1):
296 if repeat != 1 and len(args) == 1 and isinstance(args[0], int):
297 args = [SelectableInt(args[0], 1)]
298 if repeat != 1: # multiplies the incoming arguments
299 tmp = []
300 for i in range(repeat):
301 tmp += args
302 args = tmp
303 res = copy(args[0])
304 for i in args[1:]:
305 assert isinstance(i, SelectableInt), "can only concat SIs, sorry"
306 res.bits += i.bits
307 res.value = (res.value << i.bits) | i.value
308 print ("concat", repeat, res)
309 return res
310
311
312 class SelectableIntTestCase(unittest.TestCase):
313 def test_arith(self):
314 a = SelectableInt(5, 8)
315 b = SelectableInt(9, 8)
316 c = a + b
317 d = a - b
318 e = a * b
319 f = -a
320 self.assertEqual(c.value, a.value + b.value)
321 self.assertEqual(d.value, (a.value - b.value) & 0xFF)
322 self.assertEqual(e.value, (a.value * b.value) & 0xFF)
323 self.assertEqual(f.value, (-a.value) & 0xFF)
324 self.assertEqual(c.bits, a.bits)
325 self.assertEqual(d.bits, a.bits)
326 self.assertEqual(e.bits, a.bits)
327
328 def test_logic(self):
329 a = SelectableInt(0x0F, 8)
330 b = SelectableInt(0xA5, 8)
331 c = a & b
332 d = a | b
333 e = a ^ b
334 f = ~a
335 self.assertEqual(c.value, a.value & b.value)
336 self.assertEqual(d.value, a.value | b.value)
337 self.assertEqual(e.value, a.value ^ b.value)
338 self.assertEqual(f.value, 0xF0)
339
340 def test_get(self):
341 a = SelectableInt(0xa2, 8)
342 # These should be big endian
343 self.assertEqual(a[7], 0)
344 self.assertEqual(a[0:4], 10)
345 self.assertEqual(a[4:8], 2)
346
347 def test_set(self):
348 a = SelectableInt(0x5, 8)
349 a[7] = SelectableInt(0, 1)
350 self.assertEqual(a, 4)
351 a[4:8] = 9
352 self.assertEqual(a, 9)
353 a[0:4] = 3
354 self.assertEqual(a, 0x39)
355 a[0:4] = a[4:8]
356 self.assertEqual(a, 0x199)
357
358 def test_concat(self):
359 a = SelectableInt(0x1, 1)
360 c = selectconcat(a, repeat=8)
361 self.assertEqual(c, 0xff)
362 self.assertEqual(c.bits, 8)
363 a = SelectableInt(0x0, 1)
364 c = selectconcat(a, repeat=8)
365 self.assertEqual(c, 0x00)
366 self.assertEqual(c.bits, 8)
367
368 def test_repr(self):
369 for i in range(65536):
370 a = SelectableInt(i, 16)
371 b = eval(repr(a))
372 self.assertEqual(a, b)
373
374 if __name__ == "__main__":
375 unittest.main()