a94bb43d41083432f1141e44a16ad11c1ab1c001
5 from openpower
.decoder
.power_fields
import BitRange
6 from operator
import (add
, sub
, mul
, floordiv
, truediv
, mod
, or_
, and_
, xor
,
7 neg
, inv
, lshift
, rshift
, lt
, eq
)
8 from openpower
.util
import log
11 def check_extsign(a
, b
):
12 if isinstance(b
, FieldSelectableInt
):
14 if isinstance(b
, int):
15 return SelectableInt(b
, a
.bits
)
18 return SelectableInt(b
.value
, a
.bits
)
21 @functools.total_ordering
22 class FieldSelectableInt
:
23 """FieldSelectableInt: allows bit-range selection onto another target
26 def __init__(self
, si
, br
):
27 if not isinstance(si
, (FieldSelectableInt
, SelectableInt
)):
30 if isinstance(br
, (list, tuple, range)):
32 for i
, v
in enumerate(br
):
36 if isinstance(si
, FieldSelectableInt
):
38 if len(br
) > len(fsi
.br
):
39 raise OverflowError(br
)
41 for (i
, v
) in br
.items():
46 self
.si
= si
# target selectable int
47 self
.br
= br
# map of indices
50 if isinstance(b
, int):
51 # convert integer to same SelectableInt of same bitlength as range
53 b
= SelectableInt(b
, blen
)
54 for i
in range(b
.bits
):
56 elif isinstance(b
, SelectableInt
):
57 for i
in range(b
.bits
):
73 def __getitem__(self
, key
):
74 log("getitem", key
, self
.br
)
75 if isinstance(key
, SelectableInt
):
78 if isinstance(key
, int):
79 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
81 elif isinstance(key
, slice):
83 return selectconcat(*[self
.si
[x
] for x
in key
])
84 elif isinstance(key
, (tuple, list, range)):
85 return FieldSelectableInt(si
=self
, br
=key
)
87 def __setitem__(self
, key
, value
):
88 if isinstance(key
, SelectableInt
):
90 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
91 if isinstance(key
, int):
92 return self
.si
.__setitem
__(key
, value
)
94 if not isinstance(value
, SelectableInt
):
95 value
= SelectableInt(value
, bits
=len(key
))
96 for i
, k
in enumerate(key
):
100 return self
._op
1(negate
)
102 def __invert__(self
):
103 return self
._op
1(inv
)
105 def __add__(self
, b
):
106 return self
._op
(add
, b
)
108 def __sub__(self
, b
):
109 return self
._op
(sub
, b
)
111 def __mul__(self
, b
):
112 return self
._op
(mul
, b
)
114 def __div__(self
, b
):
115 return self
._op
(truediv
, b
)
117 def __mod__(self
, b
):
118 return self
._op
(mod
, b
)
120 def __and__(self
, b
):
121 return self
._op
(and_
, b
)
124 return self
._op
(or_
, b
)
126 def __xor__(self
, b
):
127 return self
._op
(xor
, b
)
130 return self
._op
(lt
, b
)
133 return self
._op
(eq
, b
)
136 vi
= SelectableInt(0, len(self
.br
))
137 for k
, v
in self
.br
.items():
143 for i
, v
in fi
.br
.items():
148 return f
"{self.__class__.__name__}(si={self.si}, br={self.br})"
151 for key
in self
.br
.values():
152 bit
= self
.si
[key
].value
157 def asint(self
, msb0
=False):
160 for i
, key
in self
.br
.items():
161 log("asint", i
, key
, self
.si
[key
])
162 bit
= self
.si
[key
].value
163 #log("asint", i, key, bit)
164 res |
= bit
<< ((brlen
-i
-1) if msb0
else i
)
168 class FieldSelectableIntTestCase(unittest
.TestCase
):
169 def test_arith(self
):
170 a
= SelectableInt(0b10101, 5)
171 b
= SelectableInt(0b011, 3)
176 fs
= FieldSelectableInt(a
, br
)
179 #self.assertEqual(c.value, a.value + b.value)
181 def test_select(self
):
182 a
= SelectableInt(0b00001111, 8)
188 fs
= FieldSelectableInt(a
, br
)
190 self
.assertEqual(fs
.get_range(), 0b0011)
192 def test_select_range(self
):
193 a
= SelectableInt(0b00001111, 8)
199 fs
= FieldSelectableInt(a
, br
)
201 self
.assertEqual(fs
[2:4], 0b11)
204 self
.assertEqual(fs
.get_range(), 0b1011)
208 """SelectableInt - a class that behaves exactly like python int
210 this class is designed to mirror precisely the behaviour of python int.
211 the only difference is that it must contain the context of the bitwidth
212 (number of bits) associated with that integer.
214 FieldSelectableInt can then operate on partial bits, and because there
215 is a bit width associated with SelectableInt, slices operate correctly
216 including negative start/end points.
219 def __init__(self
, value
, bits
=None):
220 if isinstance(value
, SelectableInt
):
222 raise ValueError(value
)
225 elif isinstance(value
, FieldSelectableInt
):
227 raise ValueError(value
)
229 value
= value
.si
.value
231 if not isinstance(value
, int):
232 raise ValueError(value
)
234 raise ValueError(bits
)
235 mask
= (1 << bits
) - 1
236 self
.value
= value
& mask
238 self
.overflow
= (value
& ~mask
) != 0
244 def to_signed_int(self
):
245 log ("to signed?", self
.value
& (1<<(self
.bits
-1)), self
.value
)
246 if self
.value
& (1<<(self
.bits
-1)) != 0: # negative
247 res
= self
.value
- (1<<self
.bits
)
248 log (" val -ve:", self
.bits
, res
)
251 log (" val +ve:", res
)
254 def _op(self
, op
, b
):
255 if isinstance(b
, int):
256 b
= SelectableInt(b
, self
.bits
)
257 b
= check_extsign(self
, b
)
258 assert b
.bits
== self
.bits
259 return SelectableInt(op(self
.value
, b
.value
), self
.bits
)
261 def __add__(self
, b
):
262 return self
._op
(add
, b
)
264 def __sub__(self
, b
):
265 return self
._op
(sub
, b
)
267 def __mul__(self
, b
):
268 # different case: mul result needs to fit the total bitsize
269 if isinstance(b
, int):
270 b
= SelectableInt(b
, self
.bits
)
271 log("SelectableInt mul", hex(self
.value
), hex(b
.value
),
273 return SelectableInt(self
.value
* b
.value
, self
.bits
+ b
.bits
)
275 def __floordiv__(self
, b
):
276 return self
._op
(floordiv
, b
)
278 def __truediv__(self
, b
):
279 return self
._op
(truediv
, b
)
281 def __mod__(self
, b
):
282 return self
._op
(mod
, b
)
284 def __and__(self
, b
):
285 return self
._op
(and_
, b
)
288 return self
._op
(or_
, b
)
290 def __xor__(self
, b
):
291 return self
._op
(xor
, b
)
294 log("abs", self
.value
& (1 << (self
.bits
-1)))
295 if self
.value
& (1 << (self
.bits
-1)) != 0:
299 def __rsub__(self
, b
):
300 log("rsub", b
, self
.value
)
301 if isinstance(b
, int):
302 b
= SelectableInt(b
, 256) # max extent
303 #b = check_extsign(self, b)
304 #assert b.bits == self.bits
305 return SelectableInt(b
.value
- self
.value
, b
.bits
)
307 def __radd__(self
, b
):
308 if isinstance(b
, int):
309 b
= SelectableInt(b
, self
.bits
)
310 b
= check_extsign(self
, b
)
311 assert b
.bits
== self
.bits
312 return SelectableInt(b
.value
+ self
.value
, self
.bits
)
314 def __rxor__(self
, b
):
315 b
= check_extsign(self
, b
)
316 assert b
.bits
== self
.bits
317 return SelectableInt(self
.value ^ b
.value
, self
.bits
)
319 def __invert__(self
):
320 return SelectableInt(~self
.value
, self
.bits
)
323 res
= SelectableInt((~self
.value
) + 1, self
.bits
)
324 log ("neg", hex(self
.value
), hex(res
.value
))
327 def __lshift__(self
, b
):
328 b
= check_extsign(self
, b
)
329 return SelectableInt(self
.value
<< b
.value
, self
.bits
)
331 def __rshift__(self
, b
):
332 b
= check_extsign(self
, b
)
333 return SelectableInt(self
.value
>> b
.value
, self
.bits
)
335 def __getitem__(self
, key
):
336 log ("SelectableInt.__getitem__", self
, key
, type(key
))
337 if isinstance(key
, SelectableInt
):
339 if isinstance(key
, int):
340 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
342 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
343 # MSB is indexed **LOWEST** (sigh)
344 key
= self
.bits
- (key
+ 1)
346 value
= (self
.value
>> key
) & 1
347 log("getitem", key
, self
.bits
, hex(self
.value
), value
)
348 return SelectableInt(value
, 1)
349 elif isinstance(key
, slice):
350 assert key
.step
is None or key
.step
== 1
351 assert key
.start
< key
.stop
352 assert key
.start
>= 0
353 assert key
.stop
<= self
.bits
355 stop
= self
.bits
- key
.start
356 start
= self
.bits
- key
.stop
359 log ("__getitem__ slice num bits", start
, stop
, bits
)
360 mask
= (1 << bits
) - 1
361 value
= (self
.value
>> start
) & mask
362 log("getitem", stop
, start
, self
.bits
, hex(self
.value
), value
)
363 return SelectableInt(value
, bits
)
365 def __setitem__(self
, key
, value
):
366 if isinstance(key
, SelectableInt
):
368 if isinstance(key
, int):
369 if isinstance(value
, SelectableInt
):
370 assert value
.bits
== 1
372 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
374 assert key
< self
.bits
376 key
= self
.bits
- (key
+ 1)
380 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
381 elif isinstance(key
, slice):
382 kstart
, kstop
, kstep
= key
.start
, key
.stop
, key
.step
383 if isinstance(kstart
, SelectableInt
): kstart
= kstart
.asint()
384 if isinstance(kstop
, SelectableInt
): kstop
= kstop
.asint()
385 if isinstance(kstep
, SelectableInt
): kstep
= kstep
.asint()
386 log ("__setitem__ slice ", kstart
, kstop
, kstep
)
387 assert kstep
is None or kstep
== 1
388 assert kstart
< kstop
390 assert kstop
<= self
.bits
, \
391 "key stop %d bits %d" % (kstop
, self
.bits
)
393 stop
= self
.bits
- kstart
394 start
= self
.bits
- kstop
397 #log ("__setitem__ slice num bits", bits)
398 if isinstance(value
, SelectableInt
):
399 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
401 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
402 mask
= ((1 << bits
) - 1) << start
403 value
= value
<< start
404 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
406 def __ge__(self
, other
):
407 if isinstance(other
, FieldSelectableInt
):
408 other
= other
.get_range()
409 if isinstance(other
, SelectableInt
):
410 other
= check_extsign(self
, other
)
411 assert other
.bits
== self
.bits
412 other
= other
.to_signed_int()
413 if isinstance(other
, int):
414 return onebit(self
.to_signed_int() >= other
)
417 def __le__(self
, other
):
418 if isinstance(other
, FieldSelectableInt
):
419 other
= other
.get_range()
420 if isinstance(other
, SelectableInt
):
421 other
= check_extsign(self
, other
)
422 assert other
.bits
== self
.bits
423 other
= other
.to_signed_int()
424 if isinstance(other
, int):
425 return onebit(self
.to_signed_int() <= other
)
428 def __gt__(self
, other
):
429 if isinstance(other
, FieldSelectableInt
):
430 other
= other
.get_range()
431 if isinstance(other
, SelectableInt
):
432 other
= check_extsign(self
, other
)
433 assert other
.bits
== self
.bits
434 other
= other
.to_signed_int()
435 if isinstance(other
, int):
436 return onebit(self
.to_signed_int() > other
)
439 def __lt__(self
, other
):
440 log ("SelectableInt lt", self
, other
)
441 if isinstance(other
, FieldSelectableInt
):
442 other
= other
.get_range()
443 if isinstance(other
, SelectableInt
):
444 other
= check_extsign(self
, other
)
445 assert other
.bits
== self
.bits
446 other
= other
.to_signed_int()
447 if isinstance(other
, int):
448 a
= self
.to_signed_int()
449 res
= onebit(a
< other
)
450 log (" a < b", a
, other
, res
)
454 def __eq__(self
, other
):
455 log("__eq__", self
, other
)
456 if isinstance(other
, FieldSelectableInt
):
457 other
= other
.get_range()
458 if isinstance(other
, SelectableInt
):
459 other
= check_extsign(self
, other
)
460 assert other
.bits
== self
.bits
462 log (" eq", other
, self
.value
, other
== self
.value
)
463 if isinstance(other
, int):
464 return onebit(other
== self
.value
)
467 def narrow(self
, bits
):
468 assert bits
<= self
.bits
469 return SelectableInt(self
.value
, bits
)
472 return self
.value
!= 0
475 value
= f
"value={hex(self.value)}, bits={self.bits}"
476 return f
"{self.__class__.__name__}({value})"
488 """convert to double-precision float. TODO, properly convert
489 rather than a hack-job: must actually support Power IEEE754 FP
491 assert self
.bits
== 64 # must be 64-bit
492 data
= self
.value
.to_bytes(8, byteorder
='little')
493 return struct
.unpack('<d', data
)[0]
496 class SelectableIntMappingMeta(type):
497 @functools.total_ordering
498 class Field(FieldSelectableInt
):
500 return self
.asint(msb0
=True)
503 return int(self
).__lt
__(b
)
506 return int(self
).__eq
__(b
)
509 def __init__(self
, field
):
513 return self
.__field
.__repr
__()
515 def __get__(self
, instance
, owner
):
519 cls
= SelectableIntMappingMeta
.Field
520 factory
= lambda br
: cls(si
=instance
, br
=br
)
521 if isinstance(self
.__field
, dict):
522 return {k
:factory(br
=v
) for (k
, v
) in self
.__field
.items()}
524 return factory(br
=self
.__field
)
527 def __init__(self
, bits
):
530 def __get__(self
, instance
, owner
):
536 return self
.__bits
.__repr
__()
538 def __new__(metacls
, name
, bases
, attrs
, bits
=None, fields
=None):
544 if isinstance(value
, dict):
545 value
= dict(map(field
, value
.items()))
550 fields
= dict(map(field
, fields
.items()))
551 for (key
, value
) in fields
.items():
552 attrs
.setdefault(key
, metacls
.FieldProperty(value
))
556 bits
= getattr(base
, "bits", None)
560 if not isinstance(bits
, int):
561 raise ValueError(bits
)
562 attrs
.setdefault("bits", metacls
.BitsProperty(bits
))
564 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
565 cls
.__fields
= fields
569 for (key
, value
) in cls
.__fields
.items():
573 class SelectableIntMapping(SelectableInt
,
574 metaclass
=SelectableIntMappingMeta
, bits
=0):
575 def __init__(self
, value
=0, bits
=None):
576 if isinstance(value
, int) and bits
is None:
577 bits
= self
.__class
__.bits
578 return super().__init
__(value
, bits
)
582 return SelectableInt(1 if bit
else 0, 1)
585 def selectltu(lhs
, rhs
):
586 """ less-than (unsigned)
588 if isinstance(rhs
, SelectableInt
):
590 return onebit(lhs
.value
< rhs
)
593 def selectgtu(lhs
, rhs
):
594 """ greater-than (unsigned)
596 if isinstance(rhs
, SelectableInt
):
598 return onebit(lhs
.value
> rhs
)
601 # XXX this probably isn't needed...
602 def selectassign(lhs
, idx
, rhs
):
603 if isinstance(idx
, tuple):
608 lower
, upper
, step
= idx
609 toidx
= range(lower
, upper
, step
)
610 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
614 for t
, f
in zip(toidx
, fromidx
):
618 def selectconcat(*args
, repeat
=1):
619 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
620 args
= [SelectableInt(args
[0], 1)]
621 if repeat
!= 1: # multiplies the incoming arguments
623 for i
in range(repeat
):
628 if isinstance(i
, FieldSelectableInt
):
630 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
632 res
.value
= (res
.value
<< i
.bits
) | i
.value
633 log("concat", repeat
, res
)
637 class SelectableIntTestCase(unittest
.TestCase
):
638 def test_arith(self
):
639 a
= SelectableInt(5, 8)
640 b
= SelectableInt(9, 8)
647 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
648 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
649 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
650 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
651 self
.assertEqual(c
.bits
, a
.bits
)
652 self
.assertEqual(d
.bits
, a
.bits
)
653 self
.assertEqual(e
.bits
, a
.bits
)
654 self
.assertEqual(a
.bits
, f
.bits
)
655 self
.assertEqual(a
.bits
, h
.bits
)
657 def test_logic(self
):
658 a
= SelectableInt(0x0F, 8)
659 b
= SelectableInt(0xA5, 8)
664 self
.assertEqual(c
.value
, a
.value
& b
.value
)
665 self
.assertEqual(d
.value
, a
.value | b
.value
)
666 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
667 self
.assertEqual(f
.value
, 0xF0)
670 a
= SelectableInt(0xa2, 8)
671 # These should be big endian
672 self
.assertEqual(a
[7], 0)
673 self
.assertEqual(a
[0:4], 10)
674 self
.assertEqual(a
[4:8], 2)
677 a
= SelectableInt(0x5, 8)
678 a
[7] = SelectableInt(0, 1)
679 self
.assertEqual(a
, 4)
681 self
.assertEqual(a
, 9)
683 self
.assertEqual(a
, 0x39)
685 self
.assertEqual(a
, 0x99)
687 def test_concat(self
):
688 a
= SelectableInt(0x1, 1)
689 c
= selectconcat(a
, repeat
=8)
690 self
.assertEqual(c
, 0xff)
691 self
.assertEqual(c
.bits
, 8)
692 a
= SelectableInt(0x0, 1)
693 c
= selectconcat(a
, repeat
=8)
694 self
.assertEqual(c
, 0x00)
695 self
.assertEqual(c
.bits
, 8)
698 for i
in range(65536):
699 a
= SelectableInt(i
, 16)
701 self
.assertEqual(a
, b
)
704 a
= SelectableInt(10, bits
=8)
705 b
= SelectableInt(5, bits
=8)
706 self
.assertTrue(a
> b
)
707 self
.assertFalse(a
< b
)
708 self
.assertTrue(a
!= b
)
709 self
.assertFalse(a
== b
)
711 def test_unsigned(self
):
712 a
= SelectableInt(0x80, bits
=8)
713 b
= SelectableInt(0x7f, bits
=8)
714 self
.assertTrue(a
> b
)
715 self
.assertFalse(a
< b
)
716 self
.assertTrue(a
!= b
)
717 self
.assertFalse(a
== b
)
719 def test_maxint(self
):
720 a
= SelectableInt(0xffffffffffffffff, bits
=64)
721 b
= SelectableInt(0, bits
=64)
723 self
.assertTrue(result
.value
== 0xffffffffffffffff)
725 def test_double_1(self
):
726 """use http://weitz.de/ieee/,
728 for asint
, asfloat
in [(0x4000000000000000, 2.0),
729 (0x4056C00000000000, 91.0),
730 (0xff80000000000000, -1.4044477616111843e+306),
732 a
= SelectableInt(asint
, bits
=64)
734 log ("test_double_1", asint
, asfloat
, convert
)
735 self
.assertTrue(asfloat
== convert
)
738 if __name__
== "__main__":