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
):
467 return cls
.__fields
[attr
]
468 except KeyError as error
:
469 raise AttributeError from error
476 class SelectableIntMapping(SelectableInt
, metaclass
=SelectableIntMappingMeta
):
477 def __init__(self
, value
=0):
478 return super().__init
__(value
, self
.__class
__.bits
)
480 def __getattr__(self
, attr
):
482 if isinstance(value
, dict):
483 return {key
:field(value
) for (key
, value
) in tuple(value
.items())}
484 return FieldSelectableInt(si
=self
, br
=value
)
487 return field(getattr(self
.__class
__, attr
))
488 except KeyError as error
:
489 raise AttributeError from error
493 return SelectableInt(1 if bit
else 0, 1)
496 def selectltu(lhs
, rhs
):
497 """ less-than (unsigned)
499 if isinstance(rhs
, SelectableInt
):
501 return onebit(lhs
.value
< rhs
)
504 def selectgtu(lhs
, rhs
):
505 """ greater-than (unsigned)
507 if isinstance(rhs
, SelectableInt
):
509 return onebit(lhs
.value
> rhs
)
512 # XXX this probably isn't needed...
513 def selectassign(lhs
, idx
, rhs
):
514 if isinstance(idx
, tuple):
519 lower
, upper
, step
= idx
520 toidx
= range(lower
, upper
, step
)
521 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
525 for t
, f
in zip(toidx
, fromidx
):
529 def selectconcat(*args
, repeat
=1):
530 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
531 args
= [SelectableInt(args
[0], 1)]
532 if repeat
!= 1: # multiplies the incoming arguments
534 for i
in range(repeat
):
539 if isinstance(i
, FieldSelectableInt
):
541 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
543 res
.value
= (res
.value
<< i
.bits
) | i
.value
544 log("concat", repeat
, res
)
548 class SelectableIntTestCase(unittest
.TestCase
):
549 def test_arith(self
):
550 a
= SelectableInt(5, 8)
551 b
= SelectableInt(9, 8)
558 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
559 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
560 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
561 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
562 self
.assertEqual(c
.bits
, a
.bits
)
563 self
.assertEqual(d
.bits
, a
.bits
)
564 self
.assertEqual(e
.bits
, a
.bits
)
565 self
.assertEqual(a
.bits
, f
.bits
)
566 self
.assertEqual(a
.bits
, h
.bits
)
568 def test_logic(self
):
569 a
= SelectableInt(0x0F, 8)
570 b
= SelectableInt(0xA5, 8)
575 self
.assertEqual(c
.value
, a
.value
& b
.value
)
576 self
.assertEqual(d
.value
, a
.value | b
.value
)
577 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
578 self
.assertEqual(f
.value
, 0xF0)
581 a
= SelectableInt(0xa2, 8)
582 # These should be big endian
583 self
.assertEqual(a
[7], 0)
584 self
.assertEqual(a
[0:4], 10)
585 self
.assertEqual(a
[4:8], 2)
588 a
= SelectableInt(0x5, 8)
589 a
[7] = SelectableInt(0, 1)
590 self
.assertEqual(a
, 4)
592 self
.assertEqual(a
, 9)
594 self
.assertEqual(a
, 0x39)
596 self
.assertEqual(a
, 0x99)
598 def test_concat(self
):
599 a
= SelectableInt(0x1, 1)
600 c
= selectconcat(a
, repeat
=8)
601 self
.assertEqual(c
, 0xff)
602 self
.assertEqual(c
.bits
, 8)
603 a
= SelectableInt(0x0, 1)
604 c
= selectconcat(a
, repeat
=8)
605 self
.assertEqual(c
, 0x00)
606 self
.assertEqual(c
.bits
, 8)
609 for i
in range(65536):
610 a
= SelectableInt(i
, 16)
612 self
.assertEqual(a
, b
)
615 a
= SelectableInt(10, bits
=8)
616 b
= SelectableInt(5, bits
=8)
617 self
.assertTrue(a
> b
)
618 self
.assertFalse(a
< b
)
619 self
.assertTrue(a
!= b
)
620 self
.assertFalse(a
== b
)
622 def test_unsigned(self
):
623 a
= SelectableInt(0x80, bits
=8)
624 b
= SelectableInt(0x7f, bits
=8)
625 self
.assertTrue(a
> b
)
626 self
.assertFalse(a
< b
)
627 self
.assertTrue(a
!= b
)
628 self
.assertFalse(a
== b
)
630 def test_maxint(self
):
631 a
= SelectableInt(0xffffffffffffffff, bits
=64)
632 b
= SelectableInt(0, bits
=64)
634 self
.assertTrue(result
.value
== 0xffffffffffffffff)
636 def test_double_1(self
):
637 """use http://weitz.de/ieee/,
639 for asint
, asfloat
in [(0x4000000000000000, 2.0),
640 (0x4056C00000000000, 91.0),
641 (0xff80000000000000, -1.4044477616111843e+306),
643 a
= SelectableInt(asint
, bits
=64)
645 log ("test_double_1", asint
, asfloat
, convert
)
646 self
.assertTrue(asfloat
== convert
)
649 if __name__
== "__main__":