4 from openpower
.decoder
.power_fields
import BitRange
5 from operator
import (add
, sub
, mul
, floordiv
, truediv
, mod
, or_
, and_
, xor
,
6 neg
, inv
, lshift
, rshift
)
7 from openpower
.util
import log
10 def check_extsign(a
, b
):
11 if isinstance(b
, FieldSelectableInt
):
13 if isinstance(b
, int):
14 return SelectableInt(b
, a
.bits
)
17 return SelectableInt(b
.value
, a
.bits
)
20 class FieldSelectableInt
:
21 """FieldSelectableInt: allows bit-range selection onto another target
24 def __init__(self
, si
, br
):
25 self
.si
= si
# target selectable int
26 if isinstance(br
, (list, tuple, range)):
28 for i
, v
in enumerate(br
):
31 self
.br
= br
# map of indices.
34 if isinstance(b
, int):
35 # convert integer to same SelectableInt of same bitlength as range
37 b
= SelectableInt(b
, blen
)
38 for i
in range(b
.bits
):
40 elif isinstance(b
, SelectableInt
):
41 for i
in range(b
.bits
):
57 def __getitem__(self
, key
):
58 log("getitem", key
, self
.br
)
59 if isinstance(key
, SelectableInt
):
61 if isinstance(key
, int):
62 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
64 if isinstance(key
, slice):
66 return selectconcat(*[self
.si
[x
] for x
in key
])
68 def __setitem__(self
, key
, value
):
69 if isinstance(key
, SelectableInt
):
71 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
72 if isinstance(key
, int):
73 return self
.si
.__setitem
__(key
, value
)
75 if not isinstance(value
, SelectableInt
):
76 value
= SelectableInt(value
, bits
=len(key
))
77 for i
, k
in enumerate(key
):
81 return self
._op
1(negate
)
87 return self
._op
(add
, b
)
90 return self
._op
(sub
, b
)
93 return self
._op
(mul
, b
)
96 return self
._op
(truediv
, b
)
99 return self
._op
(mod
, b
)
101 def __and__(self
, b
):
102 return self
._op
(and_
, b
)
105 return self
._op
(or_
, b
)
107 def __xor__(self
, b
):
108 return self
._op
(xor
, b
)
111 vi
= SelectableInt(0, len(self
.br
))
112 for k
, v
in self
.br
.items():
118 for i
, v
in fi
.br
.items():
123 return f
"{self.__class__.__name__}(si={self.si}, br={self.br})"
125 def asint(self
, msb0
=False):
128 for i
, key
in self
.br
.items():
129 bit
= self
.si
[key
].value
130 #log("asint", i, key, bit)
131 res |
= bit
<< ((brlen
-i
-1) if msb0
else i
)
135 class FieldSelectableIntTestCase(unittest
.TestCase
):
136 def test_arith(self
):
137 a
= SelectableInt(0b10101, 5)
138 b
= SelectableInt(0b011, 3)
143 fs
= FieldSelectableInt(a
, br
)
146 #self.assertEqual(c.value, a.value + b.value)
148 def test_select(self
):
149 a
= SelectableInt(0b00001111, 8)
155 fs
= FieldSelectableInt(a
, br
)
157 self
.assertEqual(fs
.get_range(), 0b0011)
159 def test_select_range(self
):
160 a
= SelectableInt(0b00001111, 8)
166 fs
= FieldSelectableInt(a
, br
)
168 self
.assertEqual(fs
[2:4], 0b11)
171 self
.assertEqual(fs
.get_range(), 0b1011)
175 """SelectableInt - a class that behaves exactly like python int
177 this class is designed to mirror precisely the behaviour of python int.
178 the only difference is that it must contain the context of the bitwidth
179 (number of bits) associated with that integer.
181 FieldSelectableInt can then operate on partial bits, and because there
182 is a bit width associated with SelectableInt, slices operate correctly
183 including negative start/end points.
186 def __init__(self
, value
, bits
=None):
187 if isinstance(value
, SelectableInt
):
190 mask
= (1 << bits
) - 1
191 self
.value
= value
& mask
193 self
.overflow
= (value
& ~mask
) != 0
199 def to_signed_int(self
):
200 log ("to signed?", self
.value
& (1<<(self
.bits
-1)), self
.value
)
201 if self
.value
& (1<<(self
.bits
-1)) != 0: # negative
202 res
= self
.value
- (1<<self
.bits
)
203 log (" val -ve:", self
.bits
, res
)
206 log (" val +ve:", res
)
209 def _op(self
, op
, b
):
210 if isinstance(b
, int):
211 b
= SelectableInt(b
, self
.bits
)
212 b
= check_extsign(self
, b
)
213 assert b
.bits
== self
.bits
214 return SelectableInt(op(self
.value
, b
.value
), self
.bits
)
216 def __add__(self
, b
):
217 return self
._op
(add
, b
)
219 def __sub__(self
, b
):
220 return self
._op
(sub
, b
)
222 def __mul__(self
, b
):
223 # different case: mul result needs to fit the total bitsize
224 if isinstance(b
, int):
225 b
= SelectableInt(b
, self
.bits
)
226 log("SelectableInt mul", hex(self
.value
), hex(b
.value
),
228 return SelectableInt(self
.value
* b
.value
, self
.bits
+ b
.bits
)
230 def __floordiv__(self
, b
):
231 return self
._op
(floordiv
, b
)
233 def __truediv__(self
, b
):
234 return self
._op
(truediv
, b
)
236 def __mod__(self
, b
):
237 return self
._op
(mod
, b
)
239 def __and__(self
, b
):
240 return self
._op
(and_
, b
)
243 return self
._op
(or_
, b
)
245 def __xor__(self
, b
):
246 return self
._op
(xor
, b
)
249 log("abs", self
.value
& (1 << (self
.bits
-1)))
250 if self
.value
& (1 << (self
.bits
-1)) != 0:
254 def __rsub__(self
, b
):
255 if isinstance(b
, int):
256 b
= SelectableInt(b
, self
.bits
)
257 b
= check_extsign(self
, b
)
258 assert b
.bits
== self
.bits
259 return SelectableInt(b
.value
- self
.value
, self
.bits
)
261 def __radd__(self
, b
):
262 if isinstance(b
, int):
263 b
= SelectableInt(b
, self
.bits
)
264 b
= check_extsign(self
, b
)
265 assert b
.bits
== self
.bits
266 return SelectableInt(b
.value
+ self
.value
, self
.bits
)
268 def __rxor__(self
, b
):
269 b
= check_extsign(self
, b
)
270 assert b
.bits
== self
.bits
271 return SelectableInt(self
.value ^ b
.value
, self
.bits
)
273 def __invert__(self
):
274 return SelectableInt(~self
.value
, self
.bits
)
277 res
= SelectableInt((~self
.value
) + 1, self
.bits
)
278 log ("neg", hex(self
.value
), hex(res
.value
))
281 def __lshift__(self
, b
):
282 b
= check_extsign(self
, b
)
283 return SelectableInt(self
.value
<< b
.value
, self
.bits
)
285 def __rshift__(self
, b
):
286 b
= check_extsign(self
, b
)
287 return SelectableInt(self
.value
>> b
.value
, self
.bits
)
289 def __getitem__(self
, key
):
290 if isinstance(key
, SelectableInt
):
292 if isinstance(key
, int):
293 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
295 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
296 # MSB is indexed **LOWEST** (sigh)
297 key
= self
.bits
- (key
+ 1)
299 value
= (self
.value
>> key
) & 1
300 log("getitem", key
, self
.bits
, hex(self
.value
), value
)
301 return SelectableInt(value
, 1)
302 elif isinstance(key
, slice):
303 assert key
.step
is None or key
.step
== 1
304 assert key
.start
< key
.stop
305 assert key
.start
>= 0
306 assert key
.stop
<= self
.bits
308 stop
= self
.bits
- key
.start
309 start
= self
.bits
- key
.stop
312 #log ("__getitem__ slice num bits", start, stop, bits)
313 mask
= (1 << bits
) - 1
314 value
= (self
.value
>> start
) & mask
315 log("getitem", stop
, start
, self
.bits
, hex(self
.value
), value
)
316 return SelectableInt(value
, bits
)
318 def __setitem__(self
, key
, value
):
319 if isinstance(key
, SelectableInt
):
321 if isinstance(key
, int):
322 if isinstance(value
, SelectableInt
):
323 assert value
.bits
== 1
325 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
327 assert key
< self
.bits
329 key
= self
.bits
- (key
+ 1)
333 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
334 elif isinstance(key
, slice):
335 assert key
.step
is None or key
.step
== 1
336 assert key
.start
< key
.stop
337 assert key
.start
>= 0
338 assert key
.stop
<= self
.bits
, \
339 "key stop %d bits %d" % (key
.stop
, self
.bits
)
341 stop
= self
.bits
- key
.start
342 start
= self
.bits
- key
.stop
345 #log ("__setitem__ slice num bits", bits)
346 if isinstance(value
, SelectableInt
):
347 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
349 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
350 mask
= ((1 << bits
) - 1) << start
351 value
= value
<< start
352 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
354 def __ge__(self
, other
):
355 if isinstance(other
, FieldSelectableInt
):
356 other
= other
.get_range()
357 if isinstance(other
, SelectableInt
):
358 other
= check_extsign(self
, other
)
359 assert other
.bits
== self
.bits
360 other
= other
.to_signed_int()
361 if isinstance(other
, int):
362 return onebit(self
.to_signed_int() >= other
)
365 def __le__(self
, other
):
366 if isinstance(other
, FieldSelectableInt
):
367 other
= other
.get_range()
368 if isinstance(other
, SelectableInt
):
369 other
= check_extsign(self
, other
)
370 assert other
.bits
== self
.bits
371 other
= other
.to_signed_int()
372 if isinstance(other
, int):
373 return onebit(self
.to_signed_int() <= other
)
376 def __gt__(self
, other
):
377 if isinstance(other
, FieldSelectableInt
):
378 other
= other
.get_range()
379 if isinstance(other
, SelectableInt
):
380 other
= check_extsign(self
, other
)
381 assert other
.bits
== self
.bits
382 other
= other
.to_signed_int()
383 if isinstance(other
, int):
384 return onebit(self
.to_signed_int() > other
)
387 def __lt__(self
, other
):
388 log ("SelectableInt lt", self
, other
)
389 if isinstance(other
, FieldSelectableInt
):
390 other
= other
.get_range()
391 if isinstance(other
, SelectableInt
):
392 other
= check_extsign(self
, other
)
393 assert other
.bits
== self
.bits
394 other
= other
.to_signed_int()
395 if isinstance(other
, int):
396 a
= self
.to_signed_int()
397 res
= onebit(a
< other
)
398 log (" a < b", a
, other
, res
)
402 def __eq__(self
, other
):
403 log("__eq__", self
, other
)
404 if isinstance(other
, FieldSelectableInt
):
405 other
= other
.get_range()
406 if isinstance(other
, SelectableInt
):
407 other
= check_extsign(self
, other
)
408 assert other
.bits
== self
.bits
410 log (" eq", other
, self
.value
, other
== self
.value
)
411 if isinstance(other
, int):
412 return onebit(other
== self
.value
)
415 def narrow(self
, bits
):
416 assert bits
<= self
.bits
417 return SelectableInt(self
.value
, bits
)
420 return self
.value
!= 0
423 value
= f
"value=0x{self.value:x}, bits={self.bits}"
424 return f
"{self.__class__.__name__}({value})"
433 """convert to double-precision float. TODO, properly convert
434 rather than a hack-job: must actually support Power IEEE754 FP
436 assert self
.bits
== 64 # must be 64-bit
437 data
= self
.value
.to_bytes(8, byteorder
='little')
438 return struct
.unpack('<d', data
)[0]
442 return SelectableInt(1 if bit
else 0, 1)
445 def selectltu(lhs
, rhs
):
446 """ less-than (unsigned)
448 if isinstance(rhs
, SelectableInt
):
450 return onebit(lhs
.value
< rhs
)
453 def selectgtu(lhs
, rhs
):
454 """ greater-than (unsigned)
456 if isinstance(rhs
, SelectableInt
):
458 return onebit(lhs
.value
> rhs
)
461 # XXX this probably isn't needed...
462 def selectassign(lhs
, idx
, rhs
):
463 if isinstance(idx
, tuple):
468 lower
, upper
, step
= idx
469 toidx
= range(lower
, upper
, step
)
470 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
474 for t
, f
in zip(toidx
, fromidx
):
478 def selectconcat(*args
, repeat
=1):
479 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
480 args
= [SelectableInt(args
[0], 1)]
481 if repeat
!= 1: # multiplies the incoming arguments
483 for i
in range(repeat
):
488 if isinstance(i
, FieldSelectableInt
):
490 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
492 res
.value
= (res
.value
<< i
.bits
) | i
.value
493 log("concat", repeat
, res
)
497 class SelectableIntTestCase(unittest
.TestCase
):
498 def test_arith(self
):
499 a
= SelectableInt(5, 8)
500 b
= SelectableInt(9, 8)
507 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
508 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
509 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
510 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
511 self
.assertEqual(c
.bits
, a
.bits
)
512 self
.assertEqual(d
.bits
, a
.bits
)
513 self
.assertEqual(e
.bits
, a
.bits
)
514 self
.assertEqual(a
.bits
, f
.bits
)
515 self
.assertEqual(a
.bits
, h
.bits
)
517 def test_logic(self
):
518 a
= SelectableInt(0x0F, 8)
519 b
= SelectableInt(0xA5, 8)
524 self
.assertEqual(c
.value
, a
.value
& b
.value
)
525 self
.assertEqual(d
.value
, a
.value | b
.value
)
526 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
527 self
.assertEqual(f
.value
, 0xF0)
530 a
= SelectableInt(0xa2, 8)
531 # These should be big endian
532 self
.assertEqual(a
[7], 0)
533 self
.assertEqual(a
[0:4], 10)
534 self
.assertEqual(a
[4:8], 2)
537 a
= SelectableInt(0x5, 8)
538 a
[7] = SelectableInt(0, 1)
539 self
.assertEqual(a
, 4)
541 self
.assertEqual(a
, 9)
543 self
.assertEqual(a
, 0x39)
545 self
.assertEqual(a
, 0x99)
547 def test_concat(self
):
548 a
= SelectableInt(0x1, 1)
549 c
= selectconcat(a
, repeat
=8)
550 self
.assertEqual(c
, 0xff)
551 self
.assertEqual(c
.bits
, 8)
552 a
= SelectableInt(0x0, 1)
553 c
= selectconcat(a
, repeat
=8)
554 self
.assertEqual(c
, 0x00)
555 self
.assertEqual(c
.bits
, 8)
558 for i
in range(65536):
559 a
= SelectableInt(i
, 16)
561 self
.assertEqual(a
, b
)
564 a
= SelectableInt(10, bits
=8)
565 b
= SelectableInt(5, bits
=8)
566 self
.assertTrue(a
> b
)
567 self
.assertFalse(a
< b
)
568 self
.assertTrue(a
!= b
)
569 self
.assertFalse(a
== b
)
571 def test_unsigned(self
):
572 a
= SelectableInt(0x80, bits
=8)
573 b
= SelectableInt(0x7f, bits
=8)
574 self
.assertTrue(a
> b
)
575 self
.assertFalse(a
< b
)
576 self
.assertTrue(a
!= b
)
577 self
.assertFalse(a
== b
)
579 def test_maxint(self
):
580 a
= SelectableInt(0xffffffffffffffff, bits
=64)
581 b
= SelectableInt(0, bits
=64)
583 self
.assertTrue(result
.value
== 0xffffffffffffffff)
585 def test_double_1(self
):
586 """use http://weitz.de/ieee/,
588 for asint
, asfloat
in [(0x4000000000000000, 2.0),
589 (0x4056C00000000000, 91.0),
590 (0xff80000000000000, -1.4044477616111843e+306),
592 a
= SelectableInt(asint
, bits
=64)
594 log ("test_double_1", asint
, asfloat
, convert
)
595 self
.assertTrue(asfloat
== convert
)
598 if __name__
== "__main__":