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
, SelectableInt
):
29 self
.si
= si
# target selectable int
30 if isinstance(br
, (list, tuple, range)):
32 for i
, v
in enumerate(br
):
35 self
.br
= br
# map of indices.
38 if isinstance(b
, int):
39 # convert integer to same SelectableInt of same bitlength as range
41 b
= SelectableInt(b
, blen
)
42 for i
in range(b
.bits
):
44 elif isinstance(b
, SelectableInt
):
45 for i
in range(b
.bits
):
61 def __getitem__(self
, key
):
62 log("getitem", key
, self
.br
)
63 if isinstance(key
, SelectableInt
):
65 if isinstance(key
, int):
66 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
68 if isinstance(key
, slice):
70 return selectconcat(*[self
.si
[x
] for x
in key
])
72 def __setitem__(self
, key
, value
):
73 if isinstance(key
, SelectableInt
):
75 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
76 if isinstance(key
, int):
77 return self
.si
.__setitem
__(key
, value
)
79 if not isinstance(value
, SelectableInt
):
80 value
= SelectableInt(value
, bits
=len(key
))
81 for i
, k
in enumerate(key
):
85 return self
._op
1(negate
)
91 return self
._op
(add
, b
)
94 return self
._op
(sub
, b
)
97 return self
._op
(mul
, b
)
100 return self
._op
(truediv
, b
)
102 def __mod__(self
, b
):
103 return self
._op
(mod
, b
)
105 def __and__(self
, b
):
106 return self
._op
(and_
, b
)
109 return self
._op
(or_
, b
)
111 def __xor__(self
, b
):
112 return self
._op
(xor
, b
)
115 return self
._op
(lt
, b
)
118 return self
._op
(eq
, b
)
121 vi
= SelectableInt(0, len(self
.br
))
122 for k
, v
in self
.br
.items():
128 for i
, v
in fi
.br
.items():
133 return f
"{self.__class__.__name__}(si={self.si}, br={self.br})"
135 def asint(self
, msb0
=False):
138 for i
, key
in self
.br
.items():
139 log("asint", i
, key
, self
.si
[key
])
140 bit
= self
.si
[key
].value
141 #log("asint", i, key, bit)
142 res |
= bit
<< ((brlen
-i
-1) if msb0
else i
)
146 class FieldSelectableIntTestCase(unittest
.TestCase
):
147 def test_arith(self
):
148 a
= SelectableInt(0b10101, 5)
149 b
= SelectableInt(0b011, 3)
154 fs
= FieldSelectableInt(a
, br
)
157 #self.assertEqual(c.value, a.value + b.value)
159 def test_select(self
):
160 a
= SelectableInt(0b00001111, 8)
166 fs
= FieldSelectableInt(a
, br
)
168 self
.assertEqual(fs
.get_range(), 0b0011)
170 def test_select_range(self
):
171 a
= SelectableInt(0b00001111, 8)
177 fs
= FieldSelectableInt(a
, br
)
179 self
.assertEqual(fs
[2:4], 0b11)
182 self
.assertEqual(fs
.get_range(), 0b1011)
186 """SelectableInt - a class that behaves exactly like python int
188 this class is designed to mirror precisely the behaviour of python int.
189 the only difference is that it must contain the context of the bitwidth
190 (number of bits) associated with that integer.
192 FieldSelectableInt can then operate on partial bits, and because there
193 is a bit width associated with SelectableInt, slices operate correctly
194 including negative start/end points.
197 def __init__(self
, value
, bits
=None):
198 if isinstance(value
, SelectableInt
):
200 raise ValueError(value
)
203 elif isinstance(value
, FieldSelectableInt
):
205 raise ValueError(value
)
207 value
= value
.si
.value
209 if not isinstance(value
, int):
210 raise ValueError(value
)
212 raise ValueError(bits
)
213 mask
= (1 << bits
) - 1
214 self
.value
= value
& mask
216 self
.overflow
= (value
& ~mask
) != 0
222 def to_signed_int(self
):
223 log ("to signed?", self
.value
& (1<<(self
.bits
-1)), self
.value
)
224 if self
.value
& (1<<(self
.bits
-1)) != 0: # negative
225 res
= self
.value
- (1<<self
.bits
)
226 log (" val -ve:", self
.bits
, res
)
229 log (" val +ve:", res
)
232 def _op(self
, op
, b
):
233 if isinstance(b
, int):
234 b
= SelectableInt(b
, self
.bits
)
235 b
= check_extsign(self
, b
)
236 assert b
.bits
== self
.bits
237 return SelectableInt(op(self
.value
, b
.value
), self
.bits
)
239 def __add__(self
, b
):
240 return self
._op
(add
, b
)
242 def __sub__(self
, b
):
243 return self
._op
(sub
, b
)
245 def __mul__(self
, b
):
246 # different case: mul result needs to fit the total bitsize
247 if isinstance(b
, int):
248 b
= SelectableInt(b
, self
.bits
)
249 log("SelectableInt mul", hex(self
.value
), hex(b
.value
),
251 return SelectableInt(self
.value
* b
.value
, self
.bits
+ b
.bits
)
253 def __floordiv__(self
, b
):
254 return self
._op
(floordiv
, b
)
256 def __truediv__(self
, b
):
257 return self
._op
(truediv
, b
)
259 def __mod__(self
, b
):
260 return self
._op
(mod
, b
)
262 def __and__(self
, b
):
263 return self
._op
(and_
, b
)
266 return self
._op
(or_
, b
)
268 def __xor__(self
, b
):
269 return self
._op
(xor
, b
)
272 log("abs", self
.value
& (1 << (self
.bits
-1)))
273 if self
.value
& (1 << (self
.bits
-1)) != 0:
277 def __rsub__(self
, b
):
278 log("rsub", b
, self
.value
)
279 if isinstance(b
, int):
280 b
= SelectableInt(b
, 256) # max extent
281 #b = check_extsign(self, b)
282 #assert b.bits == self.bits
283 return SelectableInt(b
.value
- self
.value
, b
.bits
)
285 def __radd__(self
, b
):
286 if isinstance(b
, int):
287 b
= SelectableInt(b
, self
.bits
)
288 b
= check_extsign(self
, b
)
289 assert b
.bits
== self
.bits
290 return SelectableInt(b
.value
+ self
.value
, self
.bits
)
292 def __rxor__(self
, b
):
293 b
= check_extsign(self
, b
)
294 assert b
.bits
== self
.bits
295 return SelectableInt(self
.value ^ b
.value
, self
.bits
)
297 def __invert__(self
):
298 return SelectableInt(~self
.value
, self
.bits
)
301 res
= SelectableInt((~self
.value
) + 1, self
.bits
)
302 log ("neg", hex(self
.value
), hex(res
.value
))
305 def __lshift__(self
, b
):
306 b
= check_extsign(self
, b
)
307 return SelectableInt(self
.value
<< b
.value
, self
.bits
)
309 def __rshift__(self
, b
):
310 b
= check_extsign(self
, b
)
311 return SelectableInt(self
.value
>> b
.value
, self
.bits
)
313 def __getitem__(self
, key
):
314 log ("SelectableInt.__getitem__", self
, key
, type(key
))
315 if isinstance(key
, SelectableInt
):
317 if isinstance(key
, int):
318 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
320 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
321 # MSB is indexed **LOWEST** (sigh)
322 key
= self
.bits
- (key
+ 1)
324 value
= (self
.value
>> key
) & 1
325 log("getitem", key
, self
.bits
, hex(self
.value
), value
)
326 return SelectableInt(value
, 1)
327 elif isinstance(key
, slice):
328 assert key
.step
is None or key
.step
== 1
329 assert key
.start
< key
.stop
330 assert key
.start
>= 0
331 assert key
.stop
<= self
.bits
333 stop
= self
.bits
- key
.start
334 start
= self
.bits
- key
.stop
337 log ("__getitem__ slice num bits", start
, stop
, bits
)
338 mask
= (1 << bits
) - 1
339 value
= (self
.value
>> start
) & mask
340 log("getitem", stop
, start
, self
.bits
, hex(self
.value
), value
)
341 return SelectableInt(value
, bits
)
343 def __setitem__(self
, key
, value
):
344 if isinstance(key
, SelectableInt
):
346 if isinstance(key
, int):
347 if isinstance(value
, SelectableInt
):
348 assert value
.bits
== 1
350 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
352 assert key
< self
.bits
354 key
= self
.bits
- (key
+ 1)
358 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
359 elif isinstance(key
, slice):
360 kstart
, kstop
, kstep
= key
.start
, key
.stop
, key
.step
361 if isinstance(kstart
, SelectableInt
): kstart
= kstart
.asint()
362 if isinstance(kstop
, SelectableInt
): kstop
= kstop
.asint()
363 if isinstance(kstep
, SelectableInt
): kstep
= kstep
.asint()
364 log ("__setitem__ slice ", kstart
, kstop
, kstep
)
365 assert kstep
is None or kstep
== 1
366 assert kstart
< kstop
368 assert kstop
<= self
.bits
, \
369 "key stop %d bits %d" % (kstop
, self
.bits
)
371 stop
= self
.bits
- kstart
372 start
= self
.bits
- kstop
375 #log ("__setitem__ slice num bits", bits)
376 if isinstance(value
, SelectableInt
):
377 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
379 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
380 mask
= ((1 << bits
) - 1) << start
381 value
= value
<< start
382 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
384 def __ge__(self
, other
):
385 if isinstance(other
, FieldSelectableInt
):
386 other
= other
.get_range()
387 if isinstance(other
, SelectableInt
):
388 other
= check_extsign(self
, other
)
389 assert other
.bits
== self
.bits
390 other
= other
.to_signed_int()
391 if isinstance(other
, int):
392 return onebit(self
.to_signed_int() >= other
)
395 def __le__(self
, other
):
396 if isinstance(other
, FieldSelectableInt
):
397 other
= other
.get_range()
398 if isinstance(other
, SelectableInt
):
399 other
= check_extsign(self
, other
)
400 assert other
.bits
== self
.bits
401 other
= other
.to_signed_int()
402 if isinstance(other
, int):
403 return onebit(self
.to_signed_int() <= other
)
406 def __gt__(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 __lt__(self
, other
):
418 log ("SelectableInt lt", self
, other
)
419 if isinstance(other
, FieldSelectableInt
):
420 other
= other
.get_range()
421 if isinstance(other
, SelectableInt
):
422 other
= check_extsign(self
, other
)
423 assert other
.bits
== self
.bits
424 other
= other
.to_signed_int()
425 if isinstance(other
, int):
426 a
= self
.to_signed_int()
427 res
= onebit(a
< other
)
428 log (" a < b", a
, other
, res
)
432 def __eq__(self
, other
):
433 log("__eq__", self
, other
)
434 if isinstance(other
, FieldSelectableInt
):
435 other
= other
.get_range()
436 if isinstance(other
, SelectableInt
):
437 other
= check_extsign(self
, other
)
438 assert other
.bits
== self
.bits
440 log (" eq", other
, self
.value
, other
== self
.value
)
441 if isinstance(other
, int):
442 return onebit(other
== self
.value
)
445 def narrow(self
, bits
):
446 assert bits
<= self
.bits
447 return SelectableInt(self
.value
, bits
)
450 return self
.value
!= 0
453 value
= f
"value={hex(self.value)}, bits={self.bits}"
454 return f
"{self.__class__.__name__}({value})"
463 """convert to double-precision float. TODO, properly convert
464 rather than a hack-job: must actually support Power IEEE754 FP
466 assert self
.bits
== 64 # must be 64-bit
467 data
= self
.value
.to_bytes(8, byteorder
='little')
468 return struct
.unpack('<d', data
)[0]
471 class SelectableIntMappingMeta(type):
472 @functools.total_ordering
473 class Field(FieldSelectableInt
):
475 return self
.asint(msb0
=True)
478 return int(self
).__lt
__(b
)
481 return int(self
).__eq
__(b
)
484 def __init__(self
, field
):
488 return self
.__field
.__repr
__()
490 def __get__(self
, instance
, owner
):
494 cls
= SelectableIntMappingMeta
.Field
495 factory
= lambda br
: cls(si
=instance
, br
=br
)
496 if isinstance(self
.__field
, dict):
497 return {k
:factory(br
=v
) for (k
, v
) in self
.__field
.items()}
499 return factory(br
=self
.__field
)
502 def __init__(self
, bits
):
505 def __get__(self
, instance
, owner
):
511 return self
.__bits
.__repr
__()
513 def __new__(metacls
, name
, bases
, attrs
, bits
=None, fields
=None):
519 if isinstance(value
, dict):
520 value
= dict(map(field
, value
.items()))
525 fields
= dict(map(field
, fields
.items()))
526 for (key
, value
) in fields
.items():
527 attrs
.setdefault(key
, metacls
.FieldProperty(value
))
531 bits
= getattr(base
, "bits", None)
535 if not isinstance(bits
, int):
536 raise ValueError(bits
)
537 attrs
.setdefault("bits", metacls
.BitsProperty(bits
))
539 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
540 cls
.__fields
= fields
544 for (key
, value
) in cls
.__fields
.items():
548 class SelectableIntMapping(SelectableInt
, metaclass
=SelectableIntMappingMeta
,
550 def __init__(self
, value
=0, bits
=None):
551 if isinstance(value
, int) and bits
is None:
552 bits
= self
.__class
__.bits
553 return super().__init
__(value
, bits
)
557 return SelectableInt(1 if bit
else 0, 1)
560 def selectltu(lhs
, rhs
):
561 """ less-than (unsigned)
563 if isinstance(rhs
, SelectableInt
):
565 return onebit(lhs
.value
< rhs
)
568 def selectgtu(lhs
, rhs
):
569 """ greater-than (unsigned)
571 if isinstance(rhs
, SelectableInt
):
573 return onebit(lhs
.value
> rhs
)
576 # XXX this probably isn't needed...
577 def selectassign(lhs
, idx
, rhs
):
578 if isinstance(idx
, tuple):
583 lower
, upper
, step
= idx
584 toidx
= range(lower
, upper
, step
)
585 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
589 for t
, f
in zip(toidx
, fromidx
):
593 def selectconcat(*args
, repeat
=1):
594 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
595 args
= [SelectableInt(args
[0], 1)]
596 if repeat
!= 1: # multiplies the incoming arguments
598 for i
in range(repeat
):
603 if isinstance(i
, FieldSelectableInt
):
605 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
607 res
.value
= (res
.value
<< i
.bits
) | i
.value
608 log("concat", repeat
, res
)
612 class SelectableIntTestCase(unittest
.TestCase
):
613 def test_arith(self
):
614 a
= SelectableInt(5, 8)
615 b
= SelectableInt(9, 8)
622 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
623 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
624 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
625 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
626 self
.assertEqual(c
.bits
, a
.bits
)
627 self
.assertEqual(d
.bits
, a
.bits
)
628 self
.assertEqual(e
.bits
, a
.bits
)
629 self
.assertEqual(a
.bits
, f
.bits
)
630 self
.assertEqual(a
.bits
, h
.bits
)
632 def test_logic(self
):
633 a
= SelectableInt(0x0F, 8)
634 b
= SelectableInt(0xA5, 8)
639 self
.assertEqual(c
.value
, a
.value
& b
.value
)
640 self
.assertEqual(d
.value
, a
.value | b
.value
)
641 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
642 self
.assertEqual(f
.value
, 0xF0)
645 a
= SelectableInt(0xa2, 8)
646 # These should be big endian
647 self
.assertEqual(a
[7], 0)
648 self
.assertEqual(a
[0:4], 10)
649 self
.assertEqual(a
[4:8], 2)
652 a
= SelectableInt(0x5, 8)
653 a
[7] = SelectableInt(0, 1)
654 self
.assertEqual(a
, 4)
656 self
.assertEqual(a
, 9)
658 self
.assertEqual(a
, 0x39)
660 self
.assertEqual(a
, 0x99)
662 def test_concat(self
):
663 a
= SelectableInt(0x1, 1)
664 c
= selectconcat(a
, repeat
=8)
665 self
.assertEqual(c
, 0xff)
666 self
.assertEqual(c
.bits
, 8)
667 a
= SelectableInt(0x0, 1)
668 c
= selectconcat(a
, repeat
=8)
669 self
.assertEqual(c
, 0x00)
670 self
.assertEqual(c
.bits
, 8)
673 for i
in range(65536):
674 a
= SelectableInt(i
, 16)
676 self
.assertEqual(a
, b
)
679 a
= SelectableInt(10, bits
=8)
680 b
= SelectableInt(5, bits
=8)
681 self
.assertTrue(a
> b
)
682 self
.assertFalse(a
< b
)
683 self
.assertTrue(a
!= b
)
684 self
.assertFalse(a
== b
)
686 def test_unsigned(self
):
687 a
= SelectableInt(0x80, bits
=8)
688 b
= SelectableInt(0x7f, bits
=8)
689 self
.assertTrue(a
> b
)
690 self
.assertFalse(a
< b
)
691 self
.assertTrue(a
!= b
)
692 self
.assertFalse(a
== b
)
694 def test_maxint(self
):
695 a
= SelectableInt(0xffffffffffffffff, bits
=64)
696 b
= SelectableInt(0, bits
=64)
698 self
.assertTrue(result
.value
== 0xffffffffffffffff)
700 def test_double_1(self
):
701 """use http://weitz.de/ieee/,
703 for asint
, asfloat
in [(0x4000000000000000, 2.0),
704 (0x4056C00000000000, 91.0),
705 (0xff80000000000000, -1.4044477616111843e+306),
707 a
= SelectableInt(asint
, bits
=64)
709 log ("test_double_1", asint
, asfloat
, convert
)
710 self
.assertTrue(asfloat
== convert
)
713 if __name__
== "__main__":