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 log("rsub", b
, self
.value
)
257 if isinstance(b
, int):
258 b
= SelectableInt(b
, 256) # max extent
259 #b = check_extsign(self, b)
260 #assert b.bits == self.bits
261 return SelectableInt(b
.value
- self
.value
, b
.bits
)
263 def __radd__(self
, b
):
264 if isinstance(b
, int):
265 b
= SelectableInt(b
, self
.bits
)
266 b
= check_extsign(self
, b
)
267 assert b
.bits
== self
.bits
268 return SelectableInt(b
.value
+ self
.value
, self
.bits
)
270 def __rxor__(self
, b
):
271 b
= check_extsign(self
, b
)
272 assert b
.bits
== self
.bits
273 return SelectableInt(self
.value ^ b
.value
, self
.bits
)
275 def __invert__(self
):
276 return SelectableInt(~self
.value
, self
.bits
)
279 res
= SelectableInt((~self
.value
) + 1, self
.bits
)
280 log ("neg", hex(self
.value
), hex(res
.value
))
283 def __lshift__(self
, b
):
284 b
= check_extsign(self
, b
)
285 return SelectableInt(self
.value
<< b
.value
, self
.bits
)
287 def __rshift__(self
, b
):
288 b
= check_extsign(self
, b
)
289 return SelectableInt(self
.value
>> b
.value
, self
.bits
)
291 def __getitem__(self
, key
):
292 if isinstance(key
, SelectableInt
):
294 if isinstance(key
, int):
295 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
297 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
298 # MSB is indexed **LOWEST** (sigh)
299 key
= self
.bits
- (key
+ 1)
301 value
= (self
.value
>> key
) & 1
302 log("getitem", key
, self
.bits
, hex(self
.value
), value
)
303 return SelectableInt(value
, 1)
304 elif isinstance(key
, slice):
305 assert key
.step
is None or key
.step
== 1
306 assert key
.start
< key
.stop
307 assert key
.start
>= 0
308 assert key
.stop
<= self
.bits
310 stop
= self
.bits
- key
.start
311 start
= self
.bits
- key
.stop
314 #log ("__getitem__ slice num bits", start, stop, bits)
315 mask
= (1 << bits
) - 1
316 value
= (self
.value
>> start
) & mask
317 log("getitem", stop
, start
, self
.bits
, hex(self
.value
), value
)
318 return SelectableInt(value
, bits
)
320 def __setitem__(self
, key
, value
):
321 if isinstance(key
, SelectableInt
):
323 if isinstance(key
, int):
324 if isinstance(value
, SelectableInt
):
325 assert value
.bits
== 1
327 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
329 assert key
< self
.bits
331 key
= self
.bits
- (key
+ 1)
335 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
336 elif isinstance(key
, slice):
337 kstart
, kstop
, kstep
= key
.start
, key
.stop
, key
.step
338 if isinstance(kstart
, SelectableInt
): kstart
= kstart
.asint()
339 if isinstance(kstop
, SelectableInt
): kstop
= kstop
.asint()
340 if isinstance(kstep
, SelectableInt
): kstep
= kstep
.asint()
341 log ("__setitem__ slice ", kstart
, kstop
, kstep
)
342 assert kstep
is None or kstep
== 1
343 assert kstart
< kstop
345 assert kstop
<= self
.bits
, \
346 "key stop %d bits %d" % (kstop
, self
.bits
)
348 stop
= self
.bits
- kstart
349 start
= self
.bits
- kstop
352 #log ("__setitem__ slice num bits", bits)
353 if isinstance(value
, SelectableInt
):
354 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
356 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
357 mask
= ((1 << bits
) - 1) << start
358 value
= value
<< start
359 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
361 def __ge__(self
, other
):
362 if isinstance(other
, FieldSelectableInt
):
363 other
= other
.get_range()
364 if isinstance(other
, SelectableInt
):
365 other
= check_extsign(self
, other
)
366 assert other
.bits
== self
.bits
367 other
= other
.to_signed_int()
368 if isinstance(other
, int):
369 return onebit(self
.to_signed_int() >= other
)
372 def __le__(self
, other
):
373 if isinstance(other
, FieldSelectableInt
):
374 other
= other
.get_range()
375 if isinstance(other
, SelectableInt
):
376 other
= check_extsign(self
, other
)
377 assert other
.bits
== self
.bits
378 other
= other
.to_signed_int()
379 if isinstance(other
, int):
380 return onebit(self
.to_signed_int() <= other
)
383 def __gt__(self
, other
):
384 if isinstance(other
, FieldSelectableInt
):
385 other
= other
.get_range()
386 if isinstance(other
, SelectableInt
):
387 other
= check_extsign(self
, other
)
388 assert other
.bits
== self
.bits
389 other
= other
.to_signed_int()
390 if isinstance(other
, int):
391 return onebit(self
.to_signed_int() > other
)
394 def __lt__(self
, other
):
395 log ("SelectableInt lt", 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 a
= self
.to_signed_int()
404 res
= onebit(a
< other
)
405 log (" a < b", a
, other
, res
)
409 def __eq__(self
, other
):
410 log("__eq__", self
, other
)
411 if isinstance(other
, FieldSelectableInt
):
412 other
= other
.get_range()
413 if isinstance(other
, SelectableInt
):
414 other
= check_extsign(self
, other
)
415 assert other
.bits
== self
.bits
417 log (" eq", other
, self
.value
, other
== self
.value
)
418 if isinstance(other
, int):
419 return onebit(other
== self
.value
)
422 def narrow(self
, bits
):
423 assert bits
<= self
.bits
424 return SelectableInt(self
.value
, bits
)
427 return self
.value
!= 0
430 value
= f
"value=0x{self.value:x}, bits={self.bits}"
431 return f
"{self.__class__.__name__}({value})"
440 """convert to double-precision float. TODO, properly convert
441 rather than a hack-job: must actually support Power IEEE754 FP
443 assert self
.bits
== 64 # must be 64-bit
444 data
= self
.value
.to_bytes(8, byteorder
='little')
445 return struct
.unpack('<d', data
)[0]
448 class SelectableIntMappingMeta(type):
449 def __new__(metacls
, name
, bases
, attrs
, bits
=0, fields
=None):
455 if isinstance(value
, dict):
456 value
= dict(map(field
, value
.items()))
461 cls
= super().__new
__(metacls
, name
, bases
, attrs
)
463 cls
.__fields
= dict(map(field
, fields
.items()))
468 for (key
, value
) in cls
.__fields
.items():
471 def __getattr__(cls
, attr
):
473 return cls
.__fields
[attr
]
474 except KeyError as error
:
475 raise AttributeError from error
482 class SelectableIntMapping(SelectableInt
, metaclass
=SelectableIntMappingMeta
):
483 def __init__(self
, value
=0):
484 return super().__init
__(value
, self
.__class
__.bits
)
486 def __getattr__(self
, attr
):
488 if isinstance(value
, dict):
489 return {key
:field(value
) for (key
, value
) in tuple(value
.items())}
490 return FieldSelectableInt(si
=self
, br
=value
)
493 return field(getattr(self
.__class
__, attr
))
494 except KeyError as error
:
495 raise AttributeError from error
499 return SelectableInt(1 if bit
else 0, 1)
502 def selectltu(lhs
, rhs
):
503 """ less-than (unsigned)
505 if isinstance(rhs
, SelectableInt
):
507 return onebit(lhs
.value
< rhs
)
510 def selectgtu(lhs
, rhs
):
511 """ greater-than (unsigned)
513 if isinstance(rhs
, SelectableInt
):
515 return onebit(lhs
.value
> rhs
)
518 # XXX this probably isn't needed...
519 def selectassign(lhs
, idx
, rhs
):
520 if isinstance(idx
, tuple):
525 lower
, upper
, step
= idx
526 toidx
= range(lower
, upper
, step
)
527 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
531 for t
, f
in zip(toidx
, fromidx
):
535 def selectconcat(*args
, repeat
=1):
536 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
537 args
= [SelectableInt(args
[0], 1)]
538 if repeat
!= 1: # multiplies the incoming arguments
540 for i
in range(repeat
):
545 if isinstance(i
, FieldSelectableInt
):
547 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
549 res
.value
= (res
.value
<< i
.bits
) | i
.value
550 log("concat", repeat
, res
)
554 class SelectableIntTestCase(unittest
.TestCase
):
555 def test_arith(self
):
556 a
= SelectableInt(5, 8)
557 b
= SelectableInt(9, 8)
564 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
565 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
566 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
567 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
568 self
.assertEqual(c
.bits
, a
.bits
)
569 self
.assertEqual(d
.bits
, a
.bits
)
570 self
.assertEqual(e
.bits
, a
.bits
)
571 self
.assertEqual(a
.bits
, f
.bits
)
572 self
.assertEqual(a
.bits
, h
.bits
)
574 def test_logic(self
):
575 a
= SelectableInt(0x0F, 8)
576 b
= SelectableInt(0xA5, 8)
581 self
.assertEqual(c
.value
, a
.value
& b
.value
)
582 self
.assertEqual(d
.value
, a
.value | b
.value
)
583 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
584 self
.assertEqual(f
.value
, 0xF0)
587 a
= SelectableInt(0xa2, 8)
588 # These should be big endian
589 self
.assertEqual(a
[7], 0)
590 self
.assertEqual(a
[0:4], 10)
591 self
.assertEqual(a
[4:8], 2)
594 a
= SelectableInt(0x5, 8)
595 a
[7] = SelectableInt(0, 1)
596 self
.assertEqual(a
, 4)
598 self
.assertEqual(a
, 9)
600 self
.assertEqual(a
, 0x39)
602 self
.assertEqual(a
, 0x99)
604 def test_concat(self
):
605 a
= SelectableInt(0x1, 1)
606 c
= selectconcat(a
, repeat
=8)
607 self
.assertEqual(c
, 0xff)
608 self
.assertEqual(c
.bits
, 8)
609 a
= SelectableInt(0x0, 1)
610 c
= selectconcat(a
, repeat
=8)
611 self
.assertEqual(c
, 0x00)
612 self
.assertEqual(c
.bits
, 8)
615 for i
in range(65536):
616 a
= SelectableInt(i
, 16)
618 self
.assertEqual(a
, b
)
621 a
= SelectableInt(10, bits
=8)
622 b
= SelectableInt(5, bits
=8)
623 self
.assertTrue(a
> b
)
624 self
.assertFalse(a
< b
)
625 self
.assertTrue(a
!= b
)
626 self
.assertFalse(a
== b
)
628 def test_unsigned(self
):
629 a
= SelectableInt(0x80, bits
=8)
630 b
= SelectableInt(0x7f, bits
=8)
631 self
.assertTrue(a
> b
)
632 self
.assertFalse(a
< b
)
633 self
.assertTrue(a
!= b
)
634 self
.assertFalse(a
== b
)
636 def test_maxint(self
):
637 a
= SelectableInt(0xffffffffffffffff, bits
=64)
638 b
= SelectableInt(0, bits
=64)
640 self
.assertTrue(result
.value
== 0xffffffffffffffff)
642 def test_double_1(self
):
643 """use http://weitz.de/ieee/,
645 for asint
, asfloat
in [(0x4000000000000000, 2.0),
646 (0x4056C00000000000, 91.0),
647 (0xff80000000000000, -1.4044477616111843e+306),
649 a
= SelectableInt(asint
, bits
=64)
651 log ("test_double_1", asint
, asfloat
, convert
)
652 self
.assertTrue(asfloat
== convert
)
655 if __name__
== "__main__":