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
)
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 class FieldSelectableInt
:
22 """FieldSelectableInt: allows bit-range selection onto another target
25 def __init__(self
, si
, br
):
26 self
.si
= si
# target selectable int
27 if isinstance(br
, (list, tuple, range)):
29 for i
, v
in enumerate(br
):
32 self
.br
= br
# map of indices.
35 if isinstance(b
, int):
36 # convert integer to same SelectableInt of same bitlength as range
38 b
= SelectableInt(b
, blen
)
39 for i
in range(b
.bits
):
41 elif isinstance(b
, SelectableInt
):
42 for i
in range(b
.bits
):
58 def __getitem__(self
, key
):
59 log("getitem", key
, self
.br
)
60 if isinstance(key
, SelectableInt
):
62 if isinstance(key
, int):
63 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
65 if isinstance(key
, slice):
67 return selectconcat(*[self
.si
[x
] for x
in key
])
69 def __setitem__(self
, key
, value
):
70 if isinstance(key
, SelectableInt
):
72 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
73 if isinstance(key
, int):
74 return self
.si
.__setitem
__(key
, value
)
76 if not isinstance(value
, SelectableInt
):
77 value
= SelectableInt(value
, bits
=len(key
))
78 for i
, k
in enumerate(key
):
82 return self
._op
1(negate
)
88 return self
._op
(add
, b
)
91 return self
._op
(sub
, b
)
94 return self
._op
(mul
, b
)
97 return self
._op
(truediv
, b
)
100 return self
._op
(mod
, b
)
102 def __and__(self
, b
):
103 return self
._op
(and_
, b
)
106 return self
._op
(or_
, b
)
108 def __xor__(self
, b
):
109 return self
._op
(xor
, b
)
112 vi
= SelectableInt(0, len(self
.br
))
113 for k
, v
in self
.br
.items():
119 for i
, v
in fi
.br
.items():
124 return f
"{self.__class__.__name__}(si={self.si}, br={self.br})"
126 def asint(self
, msb0
=False):
129 for i
, key
in self
.br
.items():
130 bit
= self
.si
[key
].value
131 #log("asint", i, key, bit)
132 res |
= bit
<< ((brlen
-i
-1) if msb0
else i
)
136 class FieldSelectableIntTestCase(unittest
.TestCase
):
137 def test_arith(self
):
138 a
= SelectableInt(0b10101, 5)
139 b
= SelectableInt(0b011, 3)
144 fs
= FieldSelectableInt(a
, br
)
147 #self.assertEqual(c.value, a.value + b.value)
149 def test_select(self
):
150 a
= SelectableInt(0b00001111, 8)
156 fs
= FieldSelectableInt(a
, br
)
158 self
.assertEqual(fs
.get_range(), 0b0011)
160 def test_select_range(self
):
161 a
= SelectableInt(0b00001111, 8)
167 fs
= FieldSelectableInt(a
, br
)
169 self
.assertEqual(fs
[2:4], 0b11)
172 self
.assertEqual(fs
.get_range(), 0b1011)
176 """SelectableInt - a class that behaves exactly like python int
178 this class is designed to mirror precisely the behaviour of python int.
179 the only difference is that it must contain the context of the bitwidth
180 (number of bits) associated with that integer.
182 FieldSelectableInt can then operate on partial bits, and because there
183 is a bit width associated with SelectableInt, slices operate correctly
184 including negative start/end points.
187 def __init__(self
, value
, bits
=None):
188 if isinstance(value
, SelectableInt
):
191 mask
= (1 << bits
) - 1
192 self
.value
= value
& mask
194 self
.overflow
= (value
& ~mask
) != 0
200 def to_signed_int(self
):
201 log ("to signed?", self
.value
& (1<<(self
.bits
-1)), self
.value
)
202 if self
.value
& (1<<(self
.bits
-1)) != 0: # negative
203 res
= self
.value
- (1<<self
.bits
)
204 log (" val -ve:", self
.bits
, res
)
207 log (" val +ve:", res
)
210 def _op(self
, op
, b
):
211 if isinstance(b
, int):
212 b
= SelectableInt(b
, self
.bits
)
213 b
= check_extsign(self
, b
)
214 assert b
.bits
== self
.bits
215 return SelectableInt(op(self
.value
, b
.value
), self
.bits
)
217 def __add__(self
, b
):
218 return self
._op
(add
, b
)
220 def __sub__(self
, b
):
221 return self
._op
(sub
, b
)
223 def __mul__(self
, b
):
224 # different case: mul result needs to fit the total bitsize
225 if isinstance(b
, int):
226 b
= SelectableInt(b
, self
.bits
)
227 log("SelectableInt mul", hex(self
.value
), hex(b
.value
),
229 return SelectableInt(self
.value
* b
.value
, self
.bits
+ b
.bits
)
231 def __floordiv__(self
, b
):
232 return self
._op
(floordiv
, b
)
234 def __truediv__(self
, b
):
235 return self
._op
(truediv
, b
)
237 def __mod__(self
, b
):
238 return self
._op
(mod
, b
)
240 def __and__(self
, b
):
241 return self
._op
(and_
, b
)
244 return self
._op
(or_
, b
)
246 def __xor__(self
, b
):
247 return self
._op
(xor
, b
)
250 log("abs", self
.value
& (1 << (self
.bits
-1)))
251 if self
.value
& (1 << (self
.bits
-1)) != 0:
255 def __rsub__(self
, b
):
256 if isinstance(b
, int):
257 b
= SelectableInt(b
, self
.bits
)
258 b
= check_extsign(self
, b
)
259 assert b
.bits
== self
.bits
260 return SelectableInt(b
.value
- self
.value
, self
.bits
)
262 def __radd__(self
, b
):
263 if isinstance(b
, int):
264 b
= SelectableInt(b
, self
.bits
)
265 b
= check_extsign(self
, b
)
266 assert b
.bits
== self
.bits
267 return SelectableInt(b
.value
+ self
.value
, self
.bits
)
269 def __rxor__(self
, b
):
270 b
= check_extsign(self
, b
)
271 assert b
.bits
== self
.bits
272 return SelectableInt(self
.value ^ b
.value
, self
.bits
)
274 def __invert__(self
):
275 return SelectableInt(~self
.value
, self
.bits
)
278 res
= SelectableInt((~self
.value
) + 1, self
.bits
)
279 log ("neg", hex(self
.value
), hex(res
.value
))
282 def __lshift__(self
, b
):
283 b
= check_extsign(self
, b
)
284 return SelectableInt(self
.value
<< b
.value
, self
.bits
)
286 def __rshift__(self
, b
):
287 b
= check_extsign(self
, b
)
288 return SelectableInt(self
.value
>> b
.value
, self
.bits
)
290 def __getitem__(self
, key
):
291 if isinstance(key
, SelectableInt
):
293 if isinstance(key
, int):
294 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
296 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
297 # MSB is indexed **LOWEST** (sigh)
298 key
= self
.bits
- (key
+ 1)
300 value
= (self
.value
>> key
) & 1
301 log("getitem", key
, self
.bits
, hex(self
.value
), value
)
302 return SelectableInt(value
, 1)
303 elif isinstance(key
, slice):
304 assert key
.step
is None or key
.step
== 1
305 assert key
.start
< key
.stop
306 assert key
.start
>= 0
307 assert key
.stop
<= self
.bits
309 stop
= self
.bits
- key
.start
310 start
= self
.bits
- key
.stop
313 #log ("__getitem__ slice num bits", start, stop, bits)
314 mask
= (1 << bits
) - 1
315 value
= (self
.value
>> start
) & mask
316 log("getitem", stop
, start
, self
.bits
, hex(self
.value
), value
)
317 return SelectableInt(value
, bits
)
319 def __setitem__(self
, key
, value
):
320 if isinstance(key
, SelectableInt
):
322 if isinstance(key
, int):
323 if isinstance(value
, SelectableInt
):
324 assert value
.bits
== 1
326 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
328 assert key
< self
.bits
330 key
= self
.bits
- (key
+ 1)
334 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
335 elif isinstance(key
, slice):
336 assert key
.step
is None or key
.step
== 1
337 assert key
.start
< key
.stop
338 assert key
.start
>= 0
339 assert key
.stop
<= self
.bits
, \
340 "key stop %d bits %d" % (key
.stop
, self
.bits
)
342 stop
= self
.bits
- key
.start
343 start
= self
.bits
- key
.stop
346 #log ("__setitem__ slice num bits", bits)
347 if isinstance(value
, SelectableInt
):
348 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
350 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
351 mask
= ((1 << bits
) - 1) << start
352 value
= value
<< start
353 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
355 def __ge__(self
, other
):
356 if isinstance(other
, FieldSelectableInt
):
357 other
= other
.get_range()
358 if isinstance(other
, SelectableInt
):
359 other
= check_extsign(self
, other
)
360 assert other
.bits
== self
.bits
361 other
= other
.to_signed_int()
362 if isinstance(other
, int):
363 return onebit(self
.to_signed_int() >= other
)
366 def __le__(self
, other
):
367 if isinstance(other
, FieldSelectableInt
):
368 other
= other
.get_range()
369 if isinstance(other
, SelectableInt
):
370 other
= check_extsign(self
, other
)
371 assert other
.bits
== self
.bits
372 other
= other
.to_signed_int()
373 if isinstance(other
, int):
374 return onebit(self
.to_signed_int() <= other
)
377 def __gt__(self
, other
):
378 if isinstance(other
, FieldSelectableInt
):
379 other
= other
.get_range()
380 if isinstance(other
, SelectableInt
):
381 other
= check_extsign(self
, other
)
382 assert other
.bits
== self
.bits
383 other
= other
.to_signed_int()
384 if isinstance(other
, int):
385 return onebit(self
.to_signed_int() > other
)
388 def __lt__(self
, other
):
389 log ("SelectableInt lt", self
, other
)
390 if isinstance(other
, FieldSelectableInt
):
391 other
= other
.get_range()
392 if isinstance(other
, SelectableInt
):
393 other
= check_extsign(self
, other
)
394 assert other
.bits
== self
.bits
395 other
= other
.to_signed_int()
396 if isinstance(other
, int):
397 a
= self
.to_signed_int()
398 res
= onebit(a
< other
)
399 log (" a < b", a
, other
, res
)
403 def __eq__(self
, other
):
404 log("__eq__", self
, other
)
405 if isinstance(other
, FieldSelectableInt
):
406 other
= other
.get_range()
407 if isinstance(other
, SelectableInt
):
408 other
= check_extsign(self
, other
)
409 assert other
.bits
== self
.bits
411 log (" eq", other
, self
.value
, other
== self
.value
)
412 if isinstance(other
, int):
413 return onebit(other
== self
.value
)
416 def narrow(self
, bits
):
417 assert bits
<= self
.bits
418 return SelectableInt(self
.value
, bits
)
421 return self
.value
!= 0
424 value
= f
"value=0x{self.value:x}, bits={self.bits}"
425 return f
"{self.__class__.__name__}({value})"
434 """convert to double-precision float. TODO, properly convert
435 rather than a hack-job: must actually support Power IEEE754 FP
437 assert self
.bits
== 64 # must be 64-bit
438 data
= self
.value
.to_bytes(8, byteorder
='little')
439 return struct
.unpack('<d', data
)[0]
442 class SelectableIntMappingMeta(type):
443 def __new__(metacls
, name
, bases
, attrs
, bits
=0, fields
=None):
449 if isinstance(value
, dict):
450 value
= dict(map(field
, value
.items()))
455 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
457 cls
.__fields
= dict(map(field
, fields
.items()))
462 for (key
, value
) in cls
.__fields
.items():
465 def __getattr__(cls
, attr
):
466 print("SelectableIntMappingMeta", attr
)
468 return cls
.__fields
[attr
]
469 except KeyError as error
:
470 raise AttributeError from error
477 class SelectableIntMapping(SelectableInt
, metaclass
=SelectableIntMappingMeta
):
478 def __init__(self
, value
=0):
479 return super().__init
__(value
, self
.__class
__.bits
)
481 def __getattr__(self
, attr
):
483 if isinstance(value
, dict):
484 return {key
:field(value
) for (key
, value
) in tuple(value
.items())}
485 return FieldSelectableInt(si
=self
, br
=value
)
488 return field(getattr(self
.__class
__, attr
))
489 except KeyError as error
:
490 raise AttributeError from error
494 return SelectableInt(1 if bit
else 0, 1)
497 def selectltu(lhs
, rhs
):
498 """ less-than (unsigned)
500 if isinstance(rhs
, SelectableInt
):
502 return onebit(lhs
.value
< rhs
)
505 def selectgtu(lhs
, rhs
):
506 """ greater-than (unsigned)
508 if isinstance(rhs
, SelectableInt
):
510 return onebit(lhs
.value
> rhs
)
513 # XXX this probably isn't needed...
514 def selectassign(lhs
, idx
, rhs
):
515 if isinstance(idx
, tuple):
520 lower
, upper
, step
= idx
521 toidx
= range(lower
, upper
, step
)
522 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
526 for t
, f
in zip(toidx
, fromidx
):
530 def selectconcat(*args
, repeat
=1):
531 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
532 args
= [SelectableInt(args
[0], 1)]
533 if repeat
!= 1: # multiplies the incoming arguments
535 for i
in range(repeat
):
540 if isinstance(i
, FieldSelectableInt
):
542 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
544 res
.value
= (res
.value
<< i
.bits
) | i
.value
545 log("concat", repeat
, res
)
549 class SelectableIntTestCase(unittest
.TestCase
):
550 def test_arith(self
):
551 a
= SelectableInt(5, 8)
552 b
= SelectableInt(9, 8)
559 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
560 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
561 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
562 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
563 self
.assertEqual(c
.bits
, a
.bits
)
564 self
.assertEqual(d
.bits
, a
.bits
)
565 self
.assertEqual(e
.bits
, a
.bits
)
566 self
.assertEqual(a
.bits
, f
.bits
)
567 self
.assertEqual(a
.bits
, h
.bits
)
569 def test_logic(self
):
570 a
= SelectableInt(0x0F, 8)
571 b
= SelectableInt(0xA5, 8)
576 self
.assertEqual(c
.value
, a
.value
& b
.value
)
577 self
.assertEqual(d
.value
, a
.value | b
.value
)
578 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
579 self
.assertEqual(f
.value
, 0xF0)
582 a
= SelectableInt(0xa2, 8)
583 # These should be big endian
584 self
.assertEqual(a
[7], 0)
585 self
.assertEqual(a
[0:4], 10)
586 self
.assertEqual(a
[4:8], 2)
589 a
= SelectableInt(0x5, 8)
590 a
[7] = SelectableInt(0, 1)
591 self
.assertEqual(a
, 4)
593 self
.assertEqual(a
, 9)
595 self
.assertEqual(a
, 0x39)
597 self
.assertEqual(a
, 0x99)
599 def test_concat(self
):
600 a
= SelectableInt(0x1, 1)
601 c
= selectconcat(a
, repeat
=8)
602 self
.assertEqual(c
, 0xff)
603 self
.assertEqual(c
.bits
, 8)
604 a
= SelectableInt(0x0, 1)
605 c
= selectconcat(a
, repeat
=8)
606 self
.assertEqual(c
, 0x00)
607 self
.assertEqual(c
.bits
, 8)
610 for i
in range(65536):
611 a
= SelectableInt(i
, 16)
613 self
.assertEqual(a
, b
)
616 a
= SelectableInt(10, bits
=8)
617 b
= SelectableInt(5, bits
=8)
618 self
.assertTrue(a
> b
)
619 self
.assertFalse(a
< b
)
620 self
.assertTrue(a
!= b
)
621 self
.assertFalse(a
== b
)
623 def test_unsigned(self
):
624 a
= SelectableInt(0x80, bits
=8)
625 b
= SelectableInt(0x7f, bits
=8)
626 self
.assertTrue(a
> b
)
627 self
.assertFalse(a
< b
)
628 self
.assertTrue(a
!= b
)
629 self
.assertFalse(a
== b
)
631 def test_maxint(self
):
632 a
= SelectableInt(0xffffffffffffffff, bits
=64)
633 b
= SelectableInt(0, bits
=64)
635 self
.assertTrue(result
.value
== 0xffffffffffffffff)
637 def test_double_1(self
):
638 """use http://weitz.de/ieee/,
640 for asint
, asfloat
in [(0x4000000000000000, 2.0),
641 (0x4056C00000000000, 91.0),
642 (0xff80000000000000, -1.4044477616111843e+306),
644 a
= SelectableInt(asint
, bits
=64)
646 log ("test_double_1", asint
, asfloat
, convert
)
647 self
.assertTrue(asfloat
== convert
)
650 if __name__
== "__main__":