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) or isinstance(br
, tuple):
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 "FieldSelectableInt(si=%s, br=%s)" % (self
.si
, 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)
174 """SelectableInt - a class that behaves exactly like python int
176 this class is designed to mirror precisely the behaviour of python int.
177 the only difference is that it must contain the context of the bitwidth
178 (number of bits) associated with that integer.
180 FieldSelectableInt can then operate on partial bits, and because there
181 is a bit width associated with SelectableInt, slices operate correctly
182 including negative start/end points.
185 def __init__(self
, value
, bits
):
186 if isinstance(value
, SelectableInt
):
188 mask
= (1 << bits
) - 1
189 self
.value
= value
& mask
191 self
.overflow
= (value
& ~mask
) != 0
197 def to_signed_int(self
):
198 log ("to signed?", self
.value
& (1<<(self
.bits
-1)), self
.value
)
199 if self
.value
& (1<<(self
.bits
-1)) != 0: # negative
200 res
= self
.value
- (1<<self
.bits
)
201 log (" val -ve:", self
.bits
, res
)
204 log (" val +ve:", res
)
207 def _op(self
, op
, b
):
208 if isinstance(b
, int):
209 b
= SelectableInt(b
, self
.bits
)
210 b
= check_extsign(self
, b
)
211 assert b
.bits
== self
.bits
212 return SelectableInt(op(self
.value
, b
.value
), self
.bits
)
214 def __add__(self
, b
):
215 return self
._op
(add
, b
)
217 def __sub__(self
, b
):
218 return self
._op
(sub
, b
)
220 def __mul__(self
, b
):
221 # different case: mul result needs to fit the total bitsize
222 if isinstance(b
, int):
223 b
= SelectableInt(b
, self
.bits
)
224 log("SelectableInt mul", hex(self
.value
), hex(b
.value
),
226 return SelectableInt(self
.value
* b
.value
, self
.bits
+ b
.bits
)
228 def __floordiv__(self
, b
):
229 return self
._op
(floordiv
, b
)
231 def __truediv__(self
, b
):
232 return self
._op
(truediv
, b
)
234 def __mod__(self
, b
):
235 return self
._op
(mod
, b
)
237 def __and__(self
, b
):
238 return self
._op
(and_
, b
)
241 return self
._op
(or_
, b
)
243 def __xor__(self
, b
):
244 return self
._op
(xor
, b
)
247 log("abs", self
.value
& (1 << (self
.bits
-1)))
248 if self
.value
& (1 << (self
.bits
-1)) != 0:
252 def __rsub__(self
, b
):
253 if isinstance(b
, int):
254 b
= SelectableInt(b
, self
.bits
)
255 b
= check_extsign(self
, b
)
256 assert b
.bits
== self
.bits
257 return SelectableInt(b
.value
- self
.value
, self
.bits
)
259 def __radd__(self
, b
):
260 if isinstance(b
, int):
261 b
= SelectableInt(b
, self
.bits
)
262 b
= check_extsign(self
, b
)
263 assert b
.bits
== self
.bits
264 return SelectableInt(b
.value
+ self
.value
, self
.bits
)
266 def __rxor__(self
, b
):
267 b
= check_extsign(self
, b
)
268 assert b
.bits
== self
.bits
269 return SelectableInt(self
.value ^ b
.value
, self
.bits
)
271 def __invert__(self
):
272 return SelectableInt(~self
.value
, self
.bits
)
275 res
= SelectableInt((~self
.value
) + 1, self
.bits
)
276 log ("neg", hex(self
.value
), hex(res
.value
))
279 def __lshift__(self
, b
):
280 b
= check_extsign(self
, b
)
281 return SelectableInt(self
.value
<< b
.value
, self
.bits
)
283 def __rshift__(self
, b
):
284 b
= check_extsign(self
, b
)
285 return SelectableInt(self
.value
>> b
.value
, self
.bits
)
287 def __getitem__(self
, key
):
288 if isinstance(key
, SelectableInt
):
290 if isinstance(key
, int):
291 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
293 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
294 # MSB is indexed **LOWEST** (sigh)
295 key
= self
.bits
- (key
+ 1)
297 value
= (self
.value
>> key
) & 1
298 log("getitem", key
, self
.bits
, hex(self
.value
), value
)
299 return SelectableInt(value
, 1)
300 elif isinstance(key
, slice):
301 assert key
.step
is None or key
.step
== 1
302 assert key
.start
< key
.stop
303 assert key
.start
>= 0
304 assert key
.stop
<= self
.bits
306 stop
= self
.bits
- key
.start
307 start
= self
.bits
- key
.stop
310 #log ("__getitem__ slice num bits", start, stop, bits)
311 mask
= (1 << bits
) - 1
312 value
= (self
.value
>> start
) & mask
313 log("getitem", stop
, start
, self
.bits
, hex(self
.value
), value
)
314 return SelectableInt(value
, bits
)
316 def __setitem__(self
, key
, value
):
317 if isinstance(key
, SelectableInt
):
319 if isinstance(key
, int):
320 if isinstance(value
, SelectableInt
):
321 assert value
.bits
== 1
323 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
325 assert key
< self
.bits
327 key
= self
.bits
- (key
+ 1)
331 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
332 elif isinstance(key
, slice):
333 assert key
.step
is None or key
.step
== 1
334 assert key
.start
< key
.stop
335 assert key
.start
>= 0
336 assert key
.stop
<= self
.bits
, \
337 "key stop %d bits %d" % (key
.stop
, self
.bits
)
339 stop
= self
.bits
- key
.start
340 start
= self
.bits
- key
.stop
343 #log ("__setitem__ slice num bits", bits)
344 if isinstance(value
, SelectableInt
):
345 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
347 log("setitem", key
, self
.bits
, hex(self
.value
), hex(value
))
348 mask
= ((1 << bits
) - 1) << start
349 value
= value
<< start
350 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
352 def __ge__(self
, other
):
353 if isinstance(other
, FieldSelectableInt
):
354 other
= other
.get_range()
355 if isinstance(other
, SelectableInt
):
356 other
= check_extsign(self
, other
)
357 assert other
.bits
== self
.bits
358 other
= other
.to_signed_int()
359 if isinstance(other
, int):
360 return onebit(self
.to_signed_int() >= other
)
363 def __le__(self
, other
):
364 if isinstance(other
, FieldSelectableInt
):
365 other
= other
.get_range()
366 if isinstance(other
, SelectableInt
):
367 other
= check_extsign(self
, other
)
368 assert other
.bits
== self
.bits
369 other
= other
.to_signed_int()
370 if isinstance(other
, int):
371 return onebit(self
.to_signed_int() <= other
)
374 def __gt__(self
, other
):
375 if isinstance(other
, FieldSelectableInt
):
376 other
= other
.get_range()
377 if isinstance(other
, SelectableInt
):
378 other
= check_extsign(self
, other
)
379 assert other
.bits
== self
.bits
380 other
= other
.to_signed_int()
381 if isinstance(other
, int):
382 return onebit(self
.to_signed_int() > other
)
385 def __lt__(self
, other
):
386 log ("SelectableInt lt", self
, other
)
387 if isinstance(other
, FieldSelectableInt
):
388 other
= other
.get_range()
389 if isinstance(other
, SelectableInt
):
390 other
= check_extsign(self
, other
)
391 assert other
.bits
== self
.bits
392 other
= other
.to_signed_int()
393 if isinstance(other
, int):
394 a
= self
.to_signed_int()
395 res
= onebit(a
< other
)
396 log (" a < b", a
, other
, res
)
400 def __eq__(self
, other
):
401 log("__eq__", self
, other
)
402 if isinstance(other
, FieldSelectableInt
):
403 other
= other
.get_range()
404 if isinstance(other
, SelectableInt
):
405 other
= check_extsign(self
, other
)
406 assert other
.bits
== self
.bits
408 log (" eq", other
, self
.value
, other
== self
.value
)
409 if isinstance(other
, int):
410 return onebit(other
== self
.value
)
413 def narrow(self
, bits
):
414 assert bits
<= self
.bits
415 return SelectableInt(self
.value
, bits
)
418 return self
.value
!= 0
421 return "SelectableInt(value=0x{:x}, bits={})".format(self
.value
,
431 """convert to double-precision float. TODO, properly convert
432 rather than a hack-job: must actually support Power IEEE754 FP
434 assert self
.bits
== 64 # must be 64-bit
435 data
= self
.value
.to_bytes(8, byteorder
='little')
436 return struct
.unpack('<d', data
)[0]
440 return SelectableInt(1 if bit
else 0, 1)
443 def selectltu(lhs
, rhs
):
444 """ less-than (unsigned)
446 if isinstance(rhs
, SelectableInt
):
448 return onebit(lhs
.value
< rhs
)
451 def selectgtu(lhs
, rhs
):
452 """ greater-than (unsigned)
454 if isinstance(rhs
, SelectableInt
):
456 return onebit(lhs
.value
> rhs
)
459 # XXX this probably isn't needed...
460 def selectassign(lhs
, idx
, rhs
):
461 if isinstance(idx
, tuple):
466 lower
, upper
, step
= idx
467 toidx
= range(lower
, upper
, step
)
468 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
472 for t
, f
in zip(toidx
, fromidx
):
476 def selectconcat(*args
, repeat
=1):
477 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
478 args
= [SelectableInt(args
[0], 1)]
479 if repeat
!= 1: # multiplies the incoming arguments
481 for i
in range(repeat
):
486 if isinstance(i
, FieldSelectableInt
):
488 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
490 res
.value
= (res
.value
<< i
.bits
) | i
.value
491 log("concat", repeat
, res
)
495 class SelectableIntTestCase(unittest
.TestCase
):
496 def test_arith(self
):
497 a
= SelectableInt(5, 8)
498 b
= SelectableInt(9, 8)
505 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
506 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
507 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
508 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
509 self
.assertEqual(c
.bits
, a
.bits
)
510 self
.assertEqual(d
.bits
, a
.bits
)
511 self
.assertEqual(e
.bits
, a
.bits
)
512 self
.assertEqual(a
.bits
, f
.bits
)
513 self
.assertEqual(a
.bits
, h
.bits
)
515 def test_logic(self
):
516 a
= SelectableInt(0x0F, 8)
517 b
= SelectableInt(0xA5, 8)
522 self
.assertEqual(c
.value
, a
.value
& b
.value
)
523 self
.assertEqual(d
.value
, a
.value | b
.value
)
524 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
525 self
.assertEqual(f
.value
, 0xF0)
528 a
= SelectableInt(0xa2, 8)
529 # These should be big endian
530 self
.assertEqual(a
[7], 0)
531 self
.assertEqual(a
[0:4], 10)
532 self
.assertEqual(a
[4:8], 2)
535 a
= SelectableInt(0x5, 8)
536 a
[7] = SelectableInt(0, 1)
537 self
.assertEqual(a
, 4)
539 self
.assertEqual(a
, 9)
541 self
.assertEqual(a
, 0x39)
543 self
.assertEqual(a
, 0x99)
545 def test_concat(self
):
546 a
= SelectableInt(0x1, 1)
547 c
= selectconcat(a
, repeat
=8)
548 self
.assertEqual(c
, 0xff)
549 self
.assertEqual(c
.bits
, 8)
550 a
= SelectableInt(0x0, 1)
551 c
= selectconcat(a
, repeat
=8)
552 self
.assertEqual(c
, 0x00)
553 self
.assertEqual(c
.bits
, 8)
556 for i
in range(65536):
557 a
= SelectableInt(i
, 16)
559 self
.assertEqual(a
, b
)
562 a
= SelectableInt(10, bits
=8)
563 b
= SelectableInt(5, bits
=8)
564 self
.assertTrue(a
> b
)
565 self
.assertFalse(a
< b
)
566 self
.assertTrue(a
!= b
)
567 self
.assertFalse(a
== b
)
569 def test_unsigned(self
):
570 a
= SelectableInt(0x80, bits
=8)
571 b
= SelectableInt(0x7f, bits
=8)
572 self
.assertTrue(a
> b
)
573 self
.assertFalse(a
< b
)
574 self
.assertTrue(a
!= b
)
575 self
.assertFalse(a
== b
)
577 def test_maxint(self
):
578 a
= SelectableInt(0xffffffffffffffff, bits
=64)
579 b
= SelectableInt(0, bits
=64)
581 self
.assertTrue(result
.value
== 0xffffffffffffffff)
583 def test_double_1(self
):
584 """use http://weitz.de/ieee/,
586 for asint
, asfloat
in [(0x4000000000000000, 2.0),
587 (0x4056C00000000000, 91.0),
588 (0xff80000000000000, -1.4044477616111843e+306),
590 a
= SelectableInt(asint
, bits
=64)
592 log ("test_double_1", asint
, asfloat
, convert
)
593 self
.assertTrue(asfloat
== convert
)
596 if __name__
== "__main__":