b0181b0cc7bec1bb3741486315efcf1493f27c6b
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 print ("SelectableInt.__getitem__", self
, key
, type(key
))
315 assert type(key
) != tuple # XXX error here
316 if isinstance(key
, SelectableInt
):
318 if isinstance(key
, int):
319 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
321 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
322 # MSB is indexed **LOWEST** (sigh)
323 key
= self
.bits
- (key
+ 1)
325 value
= (self
.value
>> key
) & 1
326 log("getitem", key
, self
.bits
, hex(self
.value
), value
)
327 return SelectableInt(value
, 1)
328 elif isinstance(key
, slice):
329 assert key
.step
is None or key
.step
== 1
330 assert key
.start
< key
.stop
331 assert key
.start
>= 0
332 assert key
.stop
<= self
.bits
334 stop
= self
.bits
- key
.start
335 start
= self
.bits
- key
.stop
338 log ("__getitem__ slice num bits", start
, stop
, bits
)
339 mask
= (1 << bits
) - 1
340 value
= (self
.value
>> start
) & mask
341 log("getitem", stop
, start
, self
.bits
, hex(self
.value
), value
)
342 return SelectableInt(value
, bits
)
344 def __setitem__(self
, key
, value
):
345 if isinstance(key
, SelectableInt
):
347 if isinstance(key
, int):
348 if isinstance(value
, SelectableInt
):
349 assert value
.bits
== 1
351 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
353 assert key
< self
.bits
355 key
= self
.bits
- (key
+ 1)
359 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
360 elif isinstance(key
, slice):
361 kstart
, kstop
, kstep
= key
.start
, key
.stop
, key
.step
362 if isinstance(kstart
, SelectableInt
): kstart
= kstart
.asint()
363 if isinstance(kstop
, SelectableInt
): kstop
= kstop
.asint()
364 if isinstance(kstep
, SelectableInt
): kstep
= kstep
.asint()
365 log ("__setitem__ slice ", kstart
, kstop
, kstep
)
366 assert kstep
is None or kstep
== 1
367 assert kstart
< kstop
369 assert kstop
<= self
.bits
, \
370 "key stop %d bits %d" % (kstop
, self
.bits
)
372 stop
= self
.bits
- kstart
373 start
= self
.bits
- kstop
376 #log ("__setitem__ slice num bits", bits)
377 if isinstance(value
, SelectableInt
):
378 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
380 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
381 mask
= ((1 << bits
) - 1) << start
382 value
= value
<< start
383 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
385 def __ge__(self
, other
):
386 if isinstance(other
, FieldSelectableInt
):
387 other
= other
.get_range()
388 if isinstance(other
, SelectableInt
):
389 other
= check_extsign(self
, other
)
390 assert other
.bits
== self
.bits
391 other
= other
.to_signed_int()
392 if isinstance(other
, int):
393 return onebit(self
.to_signed_int() >= other
)
396 def __le__(self
, other
):
397 if isinstance(other
, FieldSelectableInt
):
398 other
= other
.get_range()
399 if isinstance(other
, SelectableInt
):
400 other
= check_extsign(self
, other
)
401 assert other
.bits
== self
.bits
402 other
= other
.to_signed_int()
403 if isinstance(other
, int):
404 return onebit(self
.to_signed_int() <= other
)
407 def __gt__(self
, other
):
408 if isinstance(other
, FieldSelectableInt
):
409 other
= other
.get_range()
410 if isinstance(other
, SelectableInt
):
411 other
= check_extsign(self
, other
)
412 assert other
.bits
== self
.bits
413 other
= other
.to_signed_int()
414 if isinstance(other
, int):
415 return onebit(self
.to_signed_int() > other
)
418 def __lt__(self
, other
):
419 log ("SelectableInt lt", self
, other
)
420 if isinstance(other
, FieldSelectableInt
):
421 other
= other
.get_range()
422 if isinstance(other
, SelectableInt
):
423 other
= check_extsign(self
, other
)
424 assert other
.bits
== self
.bits
425 other
= other
.to_signed_int()
426 if isinstance(other
, int):
427 a
= self
.to_signed_int()
428 res
= onebit(a
< other
)
429 log (" a < b", a
, other
, res
)
433 def __eq__(self
, other
):
434 log("__eq__", self
, other
)
435 if isinstance(other
, FieldSelectableInt
):
436 other
= other
.get_range()
437 if isinstance(other
, SelectableInt
):
438 other
= check_extsign(self
, other
)
439 assert other
.bits
== self
.bits
441 log (" eq", other
, self
.value
, other
== self
.value
)
442 if isinstance(other
, int):
443 return onebit(other
== self
.value
)
446 def narrow(self
, bits
):
447 assert bits
<= self
.bits
448 return SelectableInt(self
.value
, bits
)
451 return self
.value
!= 0
454 value
= f
"value={hex(self.value)}, bits={self.bits}"
455 return f
"{self.__class__.__name__}({value})"
464 """convert to double-precision float. TODO, properly convert
465 rather than a hack-job: must actually support Power IEEE754 FP
467 assert self
.bits
== 64 # must be 64-bit
468 data
= self
.value
.to_bytes(8, byteorder
='little')
469 return struct
.unpack('<d', data
)[0]
472 class SelectableIntMappingMeta(type):
473 @functools.total_ordering
474 class Field(FieldSelectableInt
):
476 a
= self
.asint(msb0
=True)
480 a
= self
.asint(msb0
=True)
484 def __init__(self
, field
):
487 def __get__(self
, instance
, owner
):
490 res
= FieldSelectableInt(si
=instance
, br
=self
.__field
)
491 print ("FieldProperty", res
, type(res
.br
))
492 return res
.asint(msb0
=True)
495 def __init__(self
, bits
):
498 def __get__(self
, instance
, owner
):
503 def __new__(metacls
, name
, bases
, attrs
, bits
=None, fields
=None):
509 if isinstance(value
, dict):
510 value
= dict(map(field
, value
.items()))
515 for (key
, value
) in map(field
, fields
.items()):
516 attrs
.setdefault(key
, metacls
.FieldProperty(value
))
520 bits
= getattr(base
, "bits", None)
524 if not isinstance(bits
, int):
525 raise ValueError(bits
)
526 attrs
.setdefault("bits", metacls
.BitsProperty(bits
))
528 return super().__new
__(metacls
, name
, bases
, attrs
)
531 for (key
, value
) in cls
.__fields
.items():
535 class SelectableIntMapping(SelectableInt
, metaclass
=SelectableIntMappingMeta
,
537 def __init__(self
, value
=0, bits
=None):
538 if isinstance(value
, int) and bits
is None:
539 bits
= self
.__class
__.bits
540 return super().__init
__(value
, bits
)
544 return SelectableInt(1 if bit
else 0, 1)
547 def selectltu(lhs
, rhs
):
548 """ less-than (unsigned)
550 if isinstance(rhs
, SelectableInt
):
552 return onebit(lhs
.value
< rhs
)
555 def selectgtu(lhs
, rhs
):
556 """ greater-than (unsigned)
558 if isinstance(rhs
, SelectableInt
):
560 return onebit(lhs
.value
> rhs
)
563 # XXX this probably isn't needed...
564 def selectassign(lhs
, idx
, rhs
):
565 if isinstance(idx
, tuple):
570 lower
, upper
, step
= idx
571 toidx
= range(lower
, upper
, step
)
572 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
576 for t
, f
in zip(toidx
, fromidx
):
580 def selectconcat(*args
, repeat
=1):
581 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
582 args
= [SelectableInt(args
[0], 1)]
583 if repeat
!= 1: # multiplies the incoming arguments
585 for i
in range(repeat
):
590 if isinstance(i
, FieldSelectableInt
):
592 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
594 res
.value
= (res
.value
<< i
.bits
) | i
.value
595 log("concat", repeat
, res
)
599 class SelectableIntTestCase(unittest
.TestCase
):
600 def test_arith(self
):
601 a
= SelectableInt(5, 8)
602 b
= SelectableInt(9, 8)
609 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
610 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
611 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
612 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
613 self
.assertEqual(c
.bits
, a
.bits
)
614 self
.assertEqual(d
.bits
, a
.bits
)
615 self
.assertEqual(e
.bits
, a
.bits
)
616 self
.assertEqual(a
.bits
, f
.bits
)
617 self
.assertEqual(a
.bits
, h
.bits
)
619 def test_logic(self
):
620 a
= SelectableInt(0x0F, 8)
621 b
= SelectableInt(0xA5, 8)
626 self
.assertEqual(c
.value
, a
.value
& b
.value
)
627 self
.assertEqual(d
.value
, a
.value | b
.value
)
628 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
629 self
.assertEqual(f
.value
, 0xF0)
632 a
= SelectableInt(0xa2, 8)
633 # These should be big endian
634 self
.assertEqual(a
[7], 0)
635 self
.assertEqual(a
[0:4], 10)
636 self
.assertEqual(a
[4:8], 2)
639 a
= SelectableInt(0x5, 8)
640 a
[7] = SelectableInt(0, 1)
641 self
.assertEqual(a
, 4)
643 self
.assertEqual(a
, 9)
645 self
.assertEqual(a
, 0x39)
647 self
.assertEqual(a
, 0x99)
649 def test_concat(self
):
650 a
= SelectableInt(0x1, 1)
651 c
= selectconcat(a
, repeat
=8)
652 self
.assertEqual(c
, 0xff)
653 self
.assertEqual(c
.bits
, 8)
654 a
= SelectableInt(0x0, 1)
655 c
= selectconcat(a
, repeat
=8)
656 self
.assertEqual(c
, 0x00)
657 self
.assertEqual(c
.bits
, 8)
660 for i
in range(65536):
661 a
= SelectableInt(i
, 16)
663 self
.assertEqual(a
, b
)
666 a
= SelectableInt(10, bits
=8)
667 b
= SelectableInt(5, bits
=8)
668 self
.assertTrue(a
> b
)
669 self
.assertFalse(a
< b
)
670 self
.assertTrue(a
!= b
)
671 self
.assertFalse(a
== b
)
673 def test_unsigned(self
):
674 a
= SelectableInt(0x80, bits
=8)
675 b
= SelectableInt(0x7f, bits
=8)
676 self
.assertTrue(a
> b
)
677 self
.assertFalse(a
< b
)
678 self
.assertTrue(a
!= b
)
679 self
.assertFalse(a
== b
)
681 def test_maxint(self
):
682 a
= SelectableInt(0xffffffffffffffff, bits
=64)
683 b
= SelectableInt(0, bits
=64)
685 self
.assertTrue(result
.value
== 0xffffffffffffffff)
687 def test_double_1(self
):
688 """use http://weitz.de/ieee/,
690 for asint
, asfloat
in [(0x4000000000000000, 2.0),
691 (0x4056C00000000000, 91.0),
692 (0xff80000000000000, -1.4044477616111843e+306),
694 a
= SelectableInt(asint
, bits
=64)
696 log ("test_double_1", asint
, asfloat
, convert
)
697 self
.assertTrue(asfloat
== convert
)
700 if __name__
== "__main__":