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})"
466 """convert to double-precision float. TODO, properly convert
467 rather than a hack-job: must actually support Power IEEE754 FP
469 assert self
.bits
== 64 # must be 64-bit
470 data
= self
.value
.to_bytes(8, byteorder
='little')
471 return struct
.unpack('<d', data
)[0]
474 class SelectableIntMappingMeta(type):
475 @functools.total_ordering
476 class Field(FieldSelectableInt
):
478 return self
.asint(msb0
=True)
481 return int(self
).__lt
__(b
)
484 return int(self
).__eq
__(b
)
487 def __init__(self
, field
):
491 return self
.__field
.__repr
__()
493 def __get__(self
, instance
, owner
):
497 cls
= SelectableIntMappingMeta
.Field
498 factory
= lambda br
: cls(si
=instance
, br
=br
)
499 if isinstance(self
.__field
, dict):
500 return {k
:factory(br
=v
) for (k
, v
) in self
.__field
.items()}
502 return factory(br
=self
.__field
)
505 def __init__(self
, bits
):
508 def __get__(self
, instance
, owner
):
514 return self
.__bits
.__repr
__()
516 def __new__(metacls
, name
, bases
, attrs
, bits
=None, fields
=None):
522 if isinstance(value
, dict):
523 value
= dict(map(field
, value
.items()))
528 fields
= dict(map(field
, fields
.items()))
529 for (key
, value
) in fields
.items():
530 attrs
.setdefault(key
, metacls
.FieldProperty(value
))
534 bits
= getattr(base
, "bits", None)
538 if not isinstance(bits
, int):
539 raise ValueError(bits
)
540 attrs
.setdefault("bits", metacls
.BitsProperty(bits
))
542 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
543 cls
.__fields
= fields
547 for (key
, value
) in cls
.__fields
.items():
551 class SelectableIntMapping(SelectableInt
, metaclass
=SelectableIntMappingMeta
,
553 def __init__(self
, value
=0, bits
=None):
554 if isinstance(value
, int) and bits
is None:
555 bits
= self
.__class
__.bits
556 return super().__init
__(value
, bits
)
560 return SelectableInt(1 if bit
else 0, 1)
563 def selectltu(lhs
, rhs
):
564 """ less-than (unsigned)
566 if isinstance(rhs
, SelectableInt
):
568 return onebit(lhs
.value
< rhs
)
571 def selectgtu(lhs
, rhs
):
572 """ greater-than (unsigned)
574 if isinstance(rhs
, SelectableInt
):
576 return onebit(lhs
.value
> rhs
)
579 # XXX this probably isn't needed...
580 def selectassign(lhs
, idx
, rhs
):
581 if isinstance(idx
, tuple):
586 lower
, upper
, step
= idx
587 toidx
= range(lower
, upper
, step
)
588 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
592 for t
, f
in zip(toidx
, fromidx
):
596 def selectconcat(*args
, repeat
=1):
597 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
598 args
= [SelectableInt(args
[0], 1)]
599 if repeat
!= 1: # multiplies the incoming arguments
601 for i
in range(repeat
):
606 if isinstance(i
, FieldSelectableInt
):
608 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
610 res
.value
= (res
.value
<< i
.bits
) | i
.value
611 log("concat", repeat
, res
)
615 class SelectableIntTestCase(unittest
.TestCase
):
616 def test_arith(self
):
617 a
= SelectableInt(5, 8)
618 b
= SelectableInt(9, 8)
625 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
626 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
627 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
628 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
629 self
.assertEqual(c
.bits
, a
.bits
)
630 self
.assertEqual(d
.bits
, a
.bits
)
631 self
.assertEqual(e
.bits
, a
.bits
)
632 self
.assertEqual(a
.bits
, f
.bits
)
633 self
.assertEqual(a
.bits
, h
.bits
)
635 def test_logic(self
):
636 a
= SelectableInt(0x0F, 8)
637 b
= SelectableInt(0xA5, 8)
642 self
.assertEqual(c
.value
, a
.value
& b
.value
)
643 self
.assertEqual(d
.value
, a
.value | b
.value
)
644 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
645 self
.assertEqual(f
.value
, 0xF0)
648 a
= SelectableInt(0xa2, 8)
649 # These should be big endian
650 self
.assertEqual(a
[7], 0)
651 self
.assertEqual(a
[0:4], 10)
652 self
.assertEqual(a
[4:8], 2)
655 a
= SelectableInt(0x5, 8)
656 a
[7] = SelectableInt(0, 1)
657 self
.assertEqual(a
, 4)
659 self
.assertEqual(a
, 9)
661 self
.assertEqual(a
, 0x39)
663 self
.assertEqual(a
, 0x99)
665 def test_concat(self
):
666 a
= SelectableInt(0x1, 1)
667 c
= selectconcat(a
, repeat
=8)
668 self
.assertEqual(c
, 0xff)
669 self
.assertEqual(c
.bits
, 8)
670 a
= SelectableInt(0x0, 1)
671 c
= selectconcat(a
, repeat
=8)
672 self
.assertEqual(c
, 0x00)
673 self
.assertEqual(c
.bits
, 8)
676 for i
in range(65536):
677 a
= SelectableInt(i
, 16)
679 self
.assertEqual(a
, b
)
682 a
= SelectableInt(10, bits
=8)
683 b
= SelectableInt(5, bits
=8)
684 self
.assertTrue(a
> b
)
685 self
.assertFalse(a
< b
)
686 self
.assertTrue(a
!= b
)
687 self
.assertFalse(a
== b
)
689 def test_unsigned(self
):
690 a
= SelectableInt(0x80, bits
=8)
691 b
= SelectableInt(0x7f, bits
=8)
692 self
.assertTrue(a
> b
)
693 self
.assertFalse(a
< b
)
694 self
.assertTrue(a
!= b
)
695 self
.assertFalse(a
== b
)
697 def test_maxint(self
):
698 a
= SelectableInt(0xffffffffffffffff, bits
=64)
699 b
= SelectableInt(0, bits
=64)
701 self
.assertTrue(result
.value
== 0xffffffffffffffff)
703 def test_double_1(self
):
704 """use http://weitz.de/ieee/,
706 for asint
, asfloat
in [(0x4000000000000000, 2.0),
707 (0x4056C00000000000, 91.0),
708 (0xff80000000000000, -1.4044477616111843e+306),
710 a
= SelectableInt(asint
, bits
=64)
712 log ("test_double_1", asint
, asfloat
, convert
)
713 self
.assertTrue(asfloat
== convert
)
716 if __name__
== "__main__":