add option to cut out SVP64 from PowerDecoder2
[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, floordiv, truediv, mod, or_, and_, xor,
5 neg, inv, lshift, rshift)
6
7
8 def check_extsign(a, b):
9 if isinstance(b, FieldSelectableInt):
10 b = b.get_range()
11 if isinstance(b, int):
12 return SelectableInt(b, a.bits)
13 if b.bits != 256:
14 return b
15 return SelectableInt(b.value, a.bits)
16
17
18 class FieldSelectableInt:
19 """FieldSelectableInt: allows bit-range selection onto another target
20 """
21
22 def __init__(self, si, br):
23 self.si = si # target selectable int
24 if isinstance(br, list) or isinstance(br, tuple):
25 _br = BitRange()
26 for i, v in enumerate(br):
27 _br[i] = v
28 br = _br
29 self.br = br # map of indices.
30
31 def eq(self, b):
32 if isinstance(b, SelectableInt):
33 for i in range(b.bits):
34 self[i] = b[i]
35 else:
36 self.si = copy(b.si)
37 self.br = copy(b.br)
38
39 def _op(self, op, b):
40 vi = self.get_range()
41 vi = op(vi, b)
42 return self.merge(vi)
43
44 def _op1(self, op):
45 vi = self.get_range()
46 vi = op(vi)
47 return self.merge(vi)
48
49 def __getitem__(self, key):
50 print("getitem", key, self.br)
51 if isinstance(key, SelectableInt):
52 key = key.value
53 if isinstance(key, int):
54 key = self.br[key] # don't do POWER 1.3.4 bit-inversion
55 return self.si[key]
56 if isinstance(key, slice):
57 key = self.br[key]
58 return selectconcat(*[self.si[x] for x in key])
59
60 def __setitem__(self, key, value):
61 if isinstance(key, SelectableInt):
62 key = key.value
63 key = self.br[key] # don't do POWER 1.3.4 bit-inversion
64 if isinstance(key, int):
65 return self.si.__setitem__(key, value)
66 else:
67 if not isinstance(value, SelectableInt):
68 value = SelectableInt(value, bits=len(key))
69 for i, k in enumerate(key):
70 self.si[k] = value[i]
71
72 def __negate__(self):
73 return self._op1(negate)
74
75 def __invert__(self):
76 return self._op1(inv)
77
78 def __add__(self, b):
79 return self._op(add, b)
80
81 def __sub__(self, b):
82 return self._op(sub, b)
83
84 def __mul__(self, b):
85 return self._op(mul, b)
86
87 def __div__(self, b):
88 return self._op(truediv, b)
89
90 def __mod__(self, b):
91 return self._op(mod, b)
92
93 def __and__(self, b):
94 return self._op(and_, b)
95
96 def __or__(self, b):
97 return self._op(or_, b)
98
99 def __xor__(self, b):
100 return self._op(xor, b)
101
102 def get_range(self):
103 vi = SelectableInt(0, len(self.br))
104 for k, v in self.br.items():
105 vi[k] = self.si[v]
106 return vi
107
108 def merge(self, vi):
109 fi = copy(self)
110 for i, v in fi.br.items():
111 fi.si[v] = vi[i]
112 return fi
113
114 def __repr__(self):
115 return "FieldSelectableInt(si=%s, br=%s)" % (self.si, self.br)
116
117 def asint(self, msb0=False):
118 res = 0
119 brlen = len(self.br)
120 for i, key in self.br.items():
121 bit = self.si[key].value
122 #print("asint", i, key, bit)
123 res |= bit << ((brlen-i-1) if msb0 else i)
124 return res
125
126
127 class FieldSelectableIntTestCase(unittest.TestCase):
128 def test_arith(self):
129 a = SelectableInt(0b10101, 5)
130 b = SelectableInt(0b011, 3)
131 br = BitRange()
132 br[0] = 0
133 br[1] = 2
134 br[2] = 3
135 fs = FieldSelectableInt(a, br)
136 c = fs + b
137 print(c)
138 #self.assertEqual(c.value, a.value + b.value)
139
140 def test_select(self):
141 a = SelectableInt(0b00001111, 8)
142 br = BitRange()
143 br[0] = 0
144 br[1] = 1
145 br[2] = 4
146 br[3] = 5
147 fs = FieldSelectableInt(a, br)
148
149 self.assertEqual(fs.get_range(), 0b0011)
150
151 def test_select_range(self):
152 a = SelectableInt(0b00001111, 8)
153 br = BitRange()
154 br[0] = 0
155 br[1] = 1
156 br[2] = 4
157 br[3] = 5
158 fs = FieldSelectableInt(a, br)
159
160 self.assertEqual(fs[2:4], 0b11)
161
162 fs[0:2] = 0b10
163 self.assertEqual(fs.get_range(), 0b1011)
164
165 class SelectableInt:
166 """SelectableInt - a class that behaves exactly like python int
167
168 this class is designed to mirror precisely the behaviour of python int.
169 the only difference is that it must contain the context of the bitwidth
170 (number of bits) associated with that integer.
171
172 FieldSelectableInt can then operate on partial bits, and because there
173 is a bit width associated with SelectableInt, slices operate correctly
174 including negative start/end points.
175 """
176
177 def __init__(self, value, bits):
178 if isinstance(value, SelectableInt):
179 value = value.value
180 mask = (1 << bits) - 1
181 self.value = value & mask
182 self.bits = bits
183 self.overflow = (value & ~mask) != 0
184
185 def eq(self, b):
186 self.value = b.value
187 self.bits = b.bits
188
189 def to_signed_int(self):
190 print ("to signed?", self.value & (1<<(self.bits-1)), self.value)
191 if self.value & (1<<(self.bits-1)) != 0: # negative
192 res = self.value - (1<<self.bits)
193 print (" val -ve:", self.bits, res)
194 else:
195 res = self.value
196 print (" val +ve:", res)
197 return res
198
199 def _op(self, op, b):
200 if isinstance(b, int):
201 b = SelectableInt(b, self.bits)
202 b = check_extsign(self, b)
203 assert b.bits == self.bits
204 return SelectableInt(op(self.value, b.value), self.bits)
205
206 def __add__(self, b):
207 return self._op(add, b)
208
209 def __sub__(self, b):
210 return self._op(sub, b)
211
212 def __mul__(self, b):
213 # different case: mul result needs to fit the total bitsize
214 if isinstance(b, int):
215 b = SelectableInt(b, self.bits)
216 print("SelectableInt mul", hex(self.value), hex(b.value),
217 self.bits, b.bits)
218 return SelectableInt(self.value * b.value, self.bits + b.bits)
219
220 def __floordiv__(self, b):
221 return self._op(floordiv, b)
222
223 def __truediv__(self, b):
224 return self._op(truediv, b)
225
226 def __mod__(self, b):
227 return self._op(mod, b)
228
229 def __and__(self, b):
230 return self._op(and_, b)
231
232 def __or__(self, b):
233 return self._op(or_, b)
234
235 def __xor__(self, b):
236 return self._op(xor, b)
237
238 def __abs__(self):
239 print("abs", self.value & (1 << (self.bits-1)))
240 if self.value & (1 << (self.bits-1)) != 0:
241 return -self
242 return self
243
244 def __rsub__(self, b):
245 if isinstance(b, int):
246 b = SelectableInt(b, self.bits)
247 b = check_extsign(self, b)
248 assert b.bits == self.bits
249 return SelectableInt(b.value - self.value, self.bits)
250
251 def __radd__(self, b):
252 if isinstance(b, int):
253 b = SelectableInt(b, self.bits)
254 b = check_extsign(self, b)
255 assert b.bits == self.bits
256 return SelectableInt(b.value + self.value, self.bits)
257
258 def __rxor__(self, b):
259 b = check_extsign(self, b)
260 assert b.bits == self.bits
261 return SelectableInt(self.value ^ b.value, self.bits)
262
263 def __invert__(self):
264 return SelectableInt(~self.value, self.bits)
265
266 def __neg__(self):
267 res = SelectableInt((~self.value) + 1, self.bits)
268 print ("neg", hex(self.value), hex(res.value))
269 return res
270
271 def __lshift__(self, b):
272 b = check_extsign(self, b)
273 return SelectableInt(self.value << b.value, self.bits)
274
275 def __rshift__(self, b):
276 b = check_extsign(self, b)
277 return SelectableInt(self.value >> b.value, self.bits)
278
279 def __getitem__(self, key):
280 if isinstance(key, SelectableInt):
281 key = key.value
282 if isinstance(key, int):
283 assert key < self.bits, "key %d accessing %d" % (key, self.bits)
284 assert key >= 0
285 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
286 # MSB is indexed **LOWEST** (sigh)
287 key = self.bits - (key + 1)
288
289 value = (self.value >> key) & 1
290 print("getitem", key, self.bits, hex(self.value), value)
291 return SelectableInt(value, 1)
292 elif isinstance(key, slice):
293 assert key.step is None or key.step == 1
294 assert key.start < key.stop
295 assert key.start >= 0
296 assert key.stop <= self.bits
297
298 stop = self.bits - key.start
299 start = self.bits - key.stop
300
301 bits = stop - start
302 #print ("__getitem__ slice num bits", start, stop, bits)
303 mask = (1 << bits) - 1
304 value = (self.value >> start) & mask
305 print("getitem", stop, start, self.bits, hex(self.value), value)
306 return SelectableInt(value, bits)
307
308 def __setitem__(self, key, value):
309 if isinstance(key, SelectableInt):
310 key = key.value
311 print("setitem", key, self.bits, hex(self.value))
312 if isinstance(key, int):
313 assert key < self.bits
314 assert key >= 0
315 key = self.bits - (key + 1)
316 if isinstance(value, SelectableInt):
317 assert value.bits == 1
318 value = value.value
319
320 value = value << key
321 mask = 1 << key
322 self.value = (self.value & ~mask) | (value & mask)
323 elif isinstance(key, slice):
324 assert key.step is None or key.step == 1
325 assert key.start < key.stop
326 assert key.start >= 0
327 assert key.stop <= self.bits
328
329 stop = self.bits - key.start
330 start = self.bits - key.stop
331
332 bits = stop - start
333 #print ("__setitem__ slice num bits", bits)
334 if isinstance(value, SelectableInt):
335 assert value.bits == bits, "%d into %d" % (value.bits, bits)
336 value = value.value
337 mask = ((1 << bits) - 1) << start
338 value = value << start
339 self.value = (self.value & ~mask) | (value & mask)
340
341 def __ge__(self, other):
342 if isinstance(other, FieldSelectableInt):
343 other = other.get_range()
344 if isinstance(other, SelectableInt):
345 other = check_extsign(self, other)
346 assert other.bits == self.bits
347 other = other.to_signed_int()
348 if isinstance(other, int):
349 return onebit(self.to_signed_int() >= other)
350 assert False
351
352 def __le__(self, other):
353 if isinstance(other, FieldSelectableInt):
354 other = other.get_range()
355 if isinstance(other, SelectableInt):
356 other = check_extsign(self, other)
357 assert other.bits == self.bits
358 other = other.to_signed_int()
359 if isinstance(other, int):
360 return onebit(self.to_signed_int() <= other)
361 assert False
362
363 def __gt__(self, other):
364 if isinstance(other, FieldSelectableInt):
365 other = other.get_range()
366 if isinstance(other, SelectableInt):
367 other = check_extsign(self, other)
368 assert other.bits == self.bits
369 other = other.to_signed_int()
370 if isinstance(other, int):
371 return onebit(self.to_signed_int() > other)
372 assert False
373
374 def __lt__(self, other):
375 print ("SelectableInt lt", self, other)
376 if isinstance(other, FieldSelectableInt):
377 other = other.get_range()
378 if isinstance(other, SelectableInt):
379 other = check_extsign(self, other)
380 assert other.bits == self.bits
381 other = other.to_signed_int()
382 if isinstance(other, int):
383 a = self.to_signed_int()
384 res = onebit(a < other)
385 print (" a < b", a, other, res)
386 return res
387 assert False
388
389 def __eq__(self, other):
390 print("__eq__", self, other)
391 if isinstance(other, FieldSelectableInt):
392 other = other.get_range()
393 if isinstance(other, SelectableInt):
394 other = check_extsign(self, other)
395 assert other.bits == self.bits
396 other = other.value
397 print (" eq", other, self.value, other == self.value)
398 if isinstance(other, int):
399 return onebit(other == self.value)
400 assert False
401
402 def narrow(self, bits):
403 assert bits <= self.bits
404 return SelectableInt(self.value, bits)
405
406 def __bool__(self):
407 return self.value != 0
408
409 def __repr__(self):
410 return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
411 self.bits)
412
413 def __len__(self):
414 return self.bits
415
416 def asint(self):
417 return self.value
418
419
420 def onebit(bit):
421 return SelectableInt(1 if bit else 0, 1)
422
423
424 def selectltu(lhs, rhs):
425 """ less-than (unsigned)
426 """
427 if isinstance(rhs, SelectableInt):
428 rhs = rhs.value
429 return onebit(lhs.value < rhs)
430
431
432 def selectgtu(lhs, rhs):
433 """ greater-than (unsigned)
434 """
435 if isinstance(rhs, SelectableInt):
436 rhs = rhs.value
437 return onebit(lhs.value > rhs)
438
439
440 # XXX this probably isn't needed...
441 def selectassign(lhs, idx, rhs):
442 if isinstance(idx, tuple):
443 if len(idx) == 2:
444 lower, upper = idx
445 step = None
446 else:
447 lower, upper, step = idx
448 toidx = range(lower, upper, step)
449 fromidx = range(0, upper-lower, step) # XXX eurgh...
450 else:
451 toidx = [idx]
452 fromidx = [0]
453 for t, f in zip(toidx, fromidx):
454 lhs[t] = rhs[f]
455
456
457 def selectconcat(*args, repeat=1):
458 if repeat != 1 and len(args) == 1 and isinstance(args[0], int):
459 args = [SelectableInt(args[0], 1)]
460 if repeat != 1: # multiplies the incoming arguments
461 tmp = []
462 for i in range(repeat):
463 tmp += args
464 args = tmp
465 res = copy(args[0])
466 for i in args[1:]:
467 if isinstance(i, FieldSelectableInt):
468 i = i.si
469 assert isinstance(i, SelectableInt), "can only concat SIs, sorry"
470 res.bits += i.bits
471 res.value = (res.value << i.bits) | i.value
472 print("concat", repeat, res)
473 return res
474
475
476 class SelectableIntTestCase(unittest.TestCase):
477 def test_arith(self):
478 a = SelectableInt(5, 8)
479 b = SelectableInt(9, 8)
480 c = a + b
481 d = a - b
482 e = a * b
483 f = -a
484 g = abs(f)
485 h = abs(a)
486 self.assertEqual(c.value, a.value + b.value)
487 self.assertEqual(d.value, (a.value - b.value) & 0xFF)
488 self.assertEqual(e.value, (a.value * b.value) & 0xFF)
489 self.assertEqual(f.value, (-a.value) & 0xFF)
490 self.assertEqual(c.bits, a.bits)
491 self.assertEqual(d.bits, a.bits)
492 self.assertEqual(e.bits, a.bits)
493 self.assertEqual(a.bits, f.bits)
494 self.assertEqual(a.bits, h.bits)
495
496 def test_logic(self):
497 a = SelectableInt(0x0F, 8)
498 b = SelectableInt(0xA5, 8)
499 c = a & b
500 d = a | b
501 e = a ^ b
502 f = ~a
503 self.assertEqual(c.value, a.value & b.value)
504 self.assertEqual(d.value, a.value | b.value)
505 self.assertEqual(e.value, a.value ^ b.value)
506 self.assertEqual(f.value, 0xF0)
507
508 def test_get(self):
509 a = SelectableInt(0xa2, 8)
510 # These should be big endian
511 self.assertEqual(a[7], 0)
512 self.assertEqual(a[0:4], 10)
513 self.assertEqual(a[4:8], 2)
514
515 def test_set(self):
516 a = SelectableInt(0x5, 8)
517 a[7] = SelectableInt(0, 1)
518 self.assertEqual(a, 4)
519 a[4:8] = 9
520 self.assertEqual(a, 9)
521 a[0:4] = 3
522 self.assertEqual(a, 0x39)
523 a[0:4] = a[4:8]
524 self.assertEqual(a, 0x99)
525
526 def test_concat(self):
527 a = SelectableInt(0x1, 1)
528 c = selectconcat(a, repeat=8)
529 self.assertEqual(c, 0xff)
530 self.assertEqual(c.bits, 8)
531 a = SelectableInt(0x0, 1)
532 c = selectconcat(a, repeat=8)
533 self.assertEqual(c, 0x00)
534 self.assertEqual(c.bits, 8)
535
536 def test_repr(self):
537 for i in range(65536):
538 a = SelectableInt(i, 16)
539 b = eval(repr(a))
540 self.assertEqual(a, b)
541
542 def test_cmp(self):
543 a = SelectableInt(10, bits=8)
544 b = SelectableInt(5, bits=8)
545 self.assertTrue(a > b)
546 self.assertFalse(a < b)
547 self.assertTrue(a != b)
548 self.assertFalse(a == b)
549
550 def test_unsigned(self):
551 a = SelectableInt(0x80, bits=8)
552 b = SelectableInt(0x7f, bits=8)
553 self.assertTrue(a > b)
554 self.assertFalse(a < b)
555 self.assertTrue(a != b)
556 self.assertFalse(a == b)
557
558
559 if __name__ == "__main__":
560 unittest.main()