5 from collections
import OrderedDict
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
10 EFFECTIVELY_UNLIMITED
= 1024
12 def check_extsign(a
, b
):
13 if isinstance(b
, FieldSelectableInt
):
15 if isinstance(b
, int):
16 return SelectableInt(b
, a
.bits
)
17 if b
.bits
!= EFFECTIVELY_UNLIMITED
:
19 return SelectableInt(b
.value
, a
.bits
)
22 class BitRange(OrderedDict
):
23 """BitRange: remaps from straight indices (0,1,2..) to bit numbers
26 def __getitem__(self
, subscript
):
27 if isinstance(subscript
, slice):
28 return list(self
.values())[subscript
]
30 return OrderedDict
.__getitem
__(self
, subscript
)
33 @functools.total_ordering
34 class FieldSelectableInt
:
35 """FieldSelectableInt: allows bit-range selection onto another target
38 def __init__(self
, si
, br
):
39 if not isinstance(si
, (FieldSelectableInt
, SelectableInt
)):
42 if isinstance(br
, (list, tuple, range)):
44 for i
, v
in enumerate(br
):
48 if isinstance(si
, FieldSelectableInt
):
50 if len(br
) > len(fsi
.br
):
51 raise OverflowError(br
)
53 for (i
, v
) in br
.items():
58 self
.si
= si
# target selectable int
59 self
.br
= br
# map of indices
62 if not isinstance(b
, SelectableInt
):
63 b
= SelectableInt(b
, len(self
.br
))
64 for i
in range(b
.bits
):
80 def __getitem__(self
, key
):
81 #log("getitem", key, self.br)
82 if isinstance(key
, SelectableInt
):
85 if isinstance(key
, int):
86 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
88 elif isinstance(key
, slice):
90 return selectconcat(*[self
.si
[x
] for x
in key
])
91 elif isinstance(key
, (tuple, list, range)):
92 return FieldSelectableInt(si
=self
, br
=key
)
96 def __setitem__(self
, key
, value
):
97 if isinstance(key
, SelectableInt
):
99 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
100 if isinstance(key
, int):
101 return self
.si
.__setitem
__(key
, value
)
103 if not isinstance(value
, SelectableInt
):
104 value
= SelectableInt(value
, bits
=len(key
))
105 for i
, k
in enumerate(key
):
106 self
.si
[k
] = value
[i
]
108 def __negate__(self
):
109 return self
._op
1(neg
)
111 def __invert__(self
):
112 return self
._op
1(inv
)
114 def __add__(self
, b
):
115 return self
._op
(add
, b
)
117 def __sub__(self
, b
):
118 return self
._op
(sub
, b
)
120 def __mul__(self
, b
):
121 return self
._op
(mul
, b
)
123 def __div__(self
, b
):
124 return self
._op
(truediv
, b
)
126 def __mod__(self
, b
):
127 return self
._op
(mod
, b
)
129 def __and__(self
, b
):
130 return self
._op
(and_
, b
)
133 return self
._op
(or_
, b
)
135 def __xor__(self
, b
):
136 return self
._op
(xor
, b
)
139 vi
= self
.get_range()
140 return onebit(lt(vi
, b
))
143 vi
= self
.get_range()
144 return onebit(eq(vi
, b
))
147 vi
= SelectableInt(0, len(self
.br
))
148 for k
, v
in self
.br
.items():
154 for i
, v
in fi
.br
.items():
159 return f
"{self.__class__.__name__}(si={self.si}, br={self.br})"
162 for key
in self
.br
.values():
163 bit
= self
.si
[key
].value
169 return self
.asint(msb0
=True)
171 def asint(self
, msb0
=False):
174 for i
, key
in self
.br
.items():
175 #log("asint", i, key, self.si[key])
176 bit
= self
.si
[key
].value
177 #log("asint", i, key, bit)
178 res |
= bit
<< ((brlen
-i
-1) if msb0
else i
)
182 class FieldSelectableIntTestCase(unittest
.TestCase
):
183 def test_arith(self
):
184 a
= SelectableInt(0b10101, 5)
185 b
= SelectableInt(0b011, 3)
190 fs
= FieldSelectableInt(a
, br
)
193 #self.assertEqual(c.value, a.value + b.value)
195 def test_select(self
):
196 a
= SelectableInt(0b00001111, 8)
202 fs
= FieldSelectableInt(a
, br
)
204 self
.assertEqual(fs
.get_range(), 0b0011)
206 def test_select_range(self
):
207 a
= SelectableInt(0b00001111, 8)
213 fs
= FieldSelectableInt(a
, br
)
215 self
.assertEqual(fs
[2:4], 0b11)
218 self
.assertEqual(fs
.get_range(), 0b1011)
221 @functools.total_ordering
223 """SelectableInt - a class that behaves exactly like python int
225 this class is designed to mirror precisely the behaviour of python int.
226 the only difference is that it must contain the context of the bitwidth
227 (number of bits) associated with that integer.
229 FieldSelectableInt can then operate on partial bits, and because there
230 is a bit width associated with SelectableInt, slices operate correctly
231 including negative start/end points.
234 the bits contained by `self`
236 the number of bits contained by `self`.
238 a flag to detect if outputs have been written by pseudo-code
240 instruction inputs have `ok` set to `False`, all changed or new
241 SelectableInt instances set `ok` to `True`.
244 def __init__(self
, value
, bits
=None, *, ok
=True):
245 if isinstance(value
, FieldSelectableInt
):
246 value
= value
.get_range()
247 if isinstance(value
, SelectableInt
):
249 # check if the bitlength is different. TODO, allow override?
250 if bits
!= value
.bits
:
251 raise ValueError(value
)
254 # intentionally don't copy ok
256 if not isinstance(value
, int):
257 raise ValueError(value
)
259 raise ValueError(bits
)
260 mask
= (1 << bits
) - 1
261 self
.value
= value
& mask
263 self
.overflow
= (value
& ~mask
) != 0
271 def to_signed_int(self
):
272 log ("to signed?", self
.value
& (1<<(self
.bits
-1)), self
.value
)
273 if self
.value
& (1<<(self
.bits
-1)) != 0: # negative
274 res
= self
.value
- (1<<self
.bits
)
275 log (" val -ve:", self
.bits
, res
)
278 log (" val +ve:", res
)
281 def _op(self
, op
, b
):
282 if isinstance(b
, int):
283 b
= SelectableInt(b
, self
.bits
)
284 b
= check_extsign(self
, b
)
285 assert b
.bits
== self
.bits
286 return SelectableInt(op(self
.value
, b
.value
), self
.bits
)
288 def __add__(self
, b
):
289 return self
._op
(add
, b
)
291 def __sub__(self
, b
):
292 return self
._op
(sub
, b
)
294 def __mul__(self
, b
):
295 # different case: mul result needs to fit the total bitsize
296 if isinstance(b
, int):
297 b
= SelectableInt(b
, self
.bits
)
298 log("SelectableInt mul", hex(self
.value
), hex(b
.value
),
300 return SelectableInt(self
.value
* b
.value
, self
.bits
+ b
.bits
)
302 def __floordiv__(self
, b
):
303 return self
._op
(floordiv
, b
)
305 def __truediv__(self
, b
):
306 return self
._op
(truediv
, b
)
308 def __mod__(self
, b
):
309 return self
._op
(mod
, b
)
311 def __and__(self
, b
):
312 return self
._op
(and_
, b
)
315 return self
._op
(or_
, b
)
317 def __xor__(self
, b
):
318 return self
._op
(xor
, b
)
321 log("abs", self
.value
& (1 << (self
.bits
-1)))
322 if self
.value
& (1 << (self
.bits
-1)) != 0:
326 def __rsub__(self
, b
):
327 log("rsub", b
, self
.value
)
328 if isinstance(b
, int):
329 b
= SelectableInt(b
, EFFECTIVELY_UNLIMITED
) # max extent
330 #b = check_extsign(self, b)
331 #assert b.bits == self.bits
332 return SelectableInt(b
.value
- self
.value
, b
.bits
)
334 def __radd__(self
, b
):
335 if isinstance(b
, int):
336 b
= SelectableInt(b
, self
.bits
)
337 b
= check_extsign(self
, b
)
338 assert b
.bits
== self
.bits
339 return SelectableInt(b
.value
+ self
.value
, self
.bits
)
341 def __rxor__(self
, b
):
342 b
= check_extsign(self
, b
)
343 assert b
.bits
== self
.bits
344 return SelectableInt(self
.value ^ b
.value
, self
.bits
)
346 def __invert__(self
):
347 return SelectableInt(~self
.value
, self
.bits
)
350 res
= SelectableInt((~self
.value
) + 1, self
.bits
)
351 log ("neg", hex(self
.value
), hex(res
.value
))
354 def __lshift__(self
, b
):
355 b
= check_extsign(self
, b
)
356 return SelectableInt(self
.value
<< b
.value
, self
.bits
)
358 def __rshift__(self
, b
):
359 b
= check_extsign(self
, b
)
360 return SelectableInt(self
.value
>> b
.value
, self
.bits
)
362 def __getitem__(self
, key
):
363 #log ("SelectableInt.__getitem__", self, key, type(key))
364 if isinstance(key
, SelectableInt
):
366 if isinstance(key
, int):
367 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
369 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
370 # MSB is indexed **LOWEST** (sigh)
371 key
= self
.bits
- (key
+ 1)
373 value
= (self
.value
>> key
) & 1
374 #log("getitem", key, self.bits, hex(self.value), value)
375 return SelectableInt(value
, 1)
376 elif isinstance(key
, slice):
378 if isinstance(start
, SelectableInt
):
381 if isinstance(stop
, SelectableInt
):
384 if isinstance(step
, SelectableInt
):
387 assert step
is None or step
== 1
390 assert stop
<= self
.bits
397 #log ("__getitem__ slice num bits", start, stop, bits)
398 mask
= (1 << bits
) - 1
399 value
= (self
.value
>> start
) & mask
400 #log("getitem", stop, start, self.bits, hex(self.value), value)
401 return SelectableInt(value
, bits
)
405 if not isinstance(bit
, (int, SelectableInt
)):
406 raise ValueError(key
)
407 bits
.append(self
[bit
])
408 return selectconcat(*bits
)
410 def __setitem__(self
, key
, value
):
412 if isinstance(key
, SelectableInt
):
414 if isinstance(key
, int):
415 if isinstance(value
, SelectableInt
):
416 assert value
.bits
== 1
418 #log("setitem", key, self.bits, hex(self.value), hex(value))
420 assert key
< self
.bits
422 key
= self
.bits
- (key
+ 1)
426 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
427 elif isinstance(key
, slice):
428 kstart
, kstop
, kstep
= key
.start
, key
.stop
, key
.step
429 if isinstance(kstart
, SelectableInt
): kstart
= kstart
.asint()
430 if isinstance(kstop
, SelectableInt
): kstop
= kstop
.asint()
431 if isinstance(kstep
, SelectableInt
): kstep
= kstep
.asint()
432 #log ("__setitem__ slice ", kstart, kstop, kstep)
433 assert kstep
is None or kstep
== 1
434 assert kstart
< kstop
436 assert kstop
<= self
.bits
, \
437 "key stop %d bits %d" % (kstop
, self
.bits
)
439 stop
= self
.bits
- kstart
440 start
= self
.bits
- kstop
443 #log ("__setitem__ slice num bits", bits)
444 if isinstance(value
, SelectableInt
):
445 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
447 #log("setitem", key, self.bits, hex(self.value), hex(value))
448 mask
= ((1 << bits
) - 1) << start
449 value
= value
<< start
450 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
454 if not isinstance(bit
, (int, SelectableInt
)):
455 raise ValueError(key
)
458 if isinstance(value
, int):
459 if value
.bit_length() > len(bits
):
460 raise ValueError(value
)
461 value
= SelectableInt(value
=value
, bits
=len(bits
))
462 if not isinstance(value
, SelectableInt
):
463 raise ValueError(value
)
465 for (src
, dst
) in enumerate(bits
):
466 self
[dst
] = value
[src
]
468 def __lt__(self
, other
):
469 log ("SelectableInt __lt__", self
, other
)
470 if isinstance(other
, FieldSelectableInt
):
471 other
= other
.get_range()
472 if isinstance(other
, SelectableInt
):
473 other
= check_extsign(self
, other
)
474 assert other
.bits
== self
.bits
475 other
= other
.to_signed_int()
476 if isinstance(other
, int):
477 a
= self
.to_signed_int()
478 res
= onebit(a
< other
)
479 log (" a < b", a
, other
, res
)
483 def __eq__(self
, other
):
484 log("SelectableInt __eq__", self
, other
)
485 if isinstance(other
, FieldSelectableInt
):
486 other
= other
.get_range()
487 if isinstance(other
, SelectableInt
):
488 other
= check_extsign(self
, other
)
489 assert other
.bits
== self
.bits
491 log (" eq", other
, self
.value
, other
== self
.value
)
492 if isinstance(other
, int):
493 return onebit(other
== self
.value
)
496 def narrow(self
, bits
):
497 assert bits
<= self
.bits
498 return SelectableInt(self
.value
, bits
)
501 return self
.value
!= 0
504 value
= "value=%#x, bits=%d" % (self
.value
, self
.bits
)
506 value
+= ", ok=False"
507 return "%s(%s)" % (self
.__class
__.__name
__, value
)
519 """convert to double-precision float. TODO, properly convert
520 rather than a hack-job: must actually support Power IEEE754 FP
523 data
= self
.value
.to_bytes(4, byteorder
='little')
524 return struct
.unpack('<f', data
)[0]
525 assert self
.bits
== 64 # must be 64-bit
526 data
= self
.value
.to_bytes(8, byteorder
='little')
527 return struct
.unpack('<d', data
)[0]
531 return SelectableInt(1 if bit
else 0, 1)
534 def selectltu(lhs
, rhs
):
535 """ less-than (unsigned)
537 if isinstance(lhs
, SelectableInt
):
539 if isinstance(rhs
, SelectableInt
):
541 return onebit(lhs
< rhs
)
544 def selectgtu(lhs
, rhs
):
545 """ greater-than (unsigned)
547 if isinstance(lhs
, SelectableInt
):
549 if isinstance(rhs
, SelectableInt
):
551 return onebit(lhs
> rhs
)
554 # XXX this probably isn't needed...
555 def selectassign(lhs
, idx
, rhs
):
556 if isinstance(idx
, tuple):
561 lower
, upper
, step
= idx
562 toidx
= range(lower
, upper
, step
)
563 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
567 for t
, f
in zip(toidx
, fromidx
):
571 def selectconcat(*args
, repeat
=1):
572 if isinstance(repeat
, SelectableInt
):
573 repeat
= repeat
.value
574 if len(args
) == 1 and isinstance(args
[0], int) and args
[0] in (0, 1):
575 args
= [SelectableInt(args
[0], 1)]
576 if repeat
!= 1: # multiplies the incoming arguments
578 for i
in range(repeat
):
581 if isinstance(args
[0], FieldSelectableInt
):
582 res
= args
[0].get_range()
584 assert isinstance(args
[0], SelectableInt
), "can only concat SIs, sorry"
585 res
= SelectableInt(args
[0])
587 if isinstance(i
, FieldSelectableInt
):
589 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
591 res
.value
= (res
.value
<< i
.bits
) | i
.value
592 log("concat", repeat
, res
)
596 class SelectableIntTestCase(unittest
.TestCase
):
597 def test_arith(self
):
598 a
= SelectableInt(5, 8)
599 b
= SelectableInt(9, 8)
606 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
607 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
608 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
609 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
610 self
.assertEqual(c
.bits
, a
.bits
)
611 self
.assertEqual(d
.bits
, a
.bits
)
612 self
.assertEqual(e
.bits
, a
.bits
)
613 self
.assertEqual(a
.bits
, f
.bits
)
614 self
.assertEqual(a
.bits
, h
.bits
)
616 def test_logic(self
):
617 a
= SelectableInt(0x0F, 8)
618 b
= SelectableInt(0xA5, 8)
623 self
.assertEqual(c
.value
, a
.value
& b
.value
)
624 self
.assertEqual(d
.value
, a
.value | b
.value
)
625 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
626 self
.assertEqual(f
.value
, 0xF0)
629 a
= SelectableInt(0xa2, 8)
630 # These should be big endian
631 self
.assertEqual(a
[7], 0)
632 self
.assertEqual(a
[0:4], 10)
633 self
.assertEqual(a
[4:8], 2)
636 a
= SelectableInt(0x5, 8)
637 a
[7] = SelectableInt(0, 1)
638 self
.assertEqual(a
, 4)
640 self
.assertEqual(a
, 9)
642 self
.assertEqual(a
, 0x39)
644 self
.assertEqual(a
, 0x99)
646 def test_concat(self
):
647 a
= SelectableInt(0x1, 1)
648 c
= selectconcat(a
, repeat
=8)
649 self
.assertEqual(c
, 0xff)
650 self
.assertEqual(c
.bits
, 8)
651 a
= SelectableInt(0x0, 1)
652 c
= selectconcat(a
, repeat
=8)
653 self
.assertEqual(c
, 0x00)
654 self
.assertEqual(c
.bits
, 8)
657 for i
in range(65536):
658 a
= SelectableInt(i
, 16)
660 self
.assertEqual(a
, b
)
663 a
= SelectableInt(10, bits
=8)
664 b
= SelectableInt(5, bits
=8)
665 self
.assertTrue(a
> b
)
666 self
.assertFalse(a
< b
)
667 self
.assertTrue(a
!= b
)
668 self
.assertFalse(a
== b
)
670 def test_unsigned(self
):
671 a
= SelectableInt(0x80, bits
=8)
672 b
= SelectableInt(0x7f, bits
=8)
673 self
.assertTrue(a
> b
)
674 self
.assertFalse(a
< b
)
675 self
.assertTrue(a
!= b
)
676 self
.assertFalse(a
== b
)
678 def test_maxint(self
):
679 a
= SelectableInt(0xffffffffffffffff, bits
=64)
680 b
= SelectableInt(0, bits
=64)
682 self
.assertTrue(result
.value
== 0xffffffffffffffff)
684 def test_double_1(self
):
685 """use http://weitz.de/ieee/,
687 for asint
, asfloat
in [(0x4000000000000000, 2.0),
688 (0x4056C00000000000, 91.0),
689 (0xff80000000000000, -1.4044477616111843e+306),
691 a
= SelectableInt(asint
, bits
=64)
693 log ("test_double_1", asint
, asfloat
, convert
)
694 self
.assertTrue(asfloat
== convert
)
697 if __name__
== "__main__":