3 from openpower
.decoder
.power_fields
import BitRange
4 from operator
import (add
, sub
, mul
, floordiv
, truediv
, mod
, or_
, and_
, xor
,
5 neg
, inv
, lshift
, rshift
)
8 def check_extsign(a
, b
):
9 if isinstance(b
, FieldSelectableInt
):
11 if isinstance(b
, int):
12 return SelectableInt(b
, a
.bits
)
15 return SelectableInt(b
.value
, a
.bits
)
18 class FieldSelectableInt
:
19 """FieldSelectableInt: allows bit-range selection onto another target
22 def __init__(self
, si
, br
):
23 self
.si
= si
# target selectable int
24 if isinstance(br
, list) or isinstance(br
, tuple):
26 for i
, v
in enumerate(br
):
29 self
.br
= br
# map of indices.
32 if isinstance(b
, SelectableInt
):
33 for i
in range(b
.bits
):
49 def __getitem__(self
, key
):
50 print("getitem", key
, self
.br
)
51 if isinstance(key
, SelectableInt
):
53 if isinstance(key
, int):
54 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
56 if isinstance(key
, slice):
58 return selectconcat(*[self
.si
[x
] for x
in key
])
60 def __setitem__(self
, key
, value
):
61 if isinstance(key
, SelectableInt
):
63 key
= self
.br
[key
] # don't do POWER 1.3.4 bit-inversion
64 if isinstance(key
, int):
65 return self
.si
.__setitem
__(key
, value
)
67 if not isinstance(value
, SelectableInt
):
68 value
= SelectableInt(value
, bits
=len(key
))
69 for i
, k
in enumerate(key
):
73 return self
._op
1(negate
)
79 return self
._op
(add
, b
)
82 return self
._op
(sub
, b
)
85 return self
._op
(mul
, b
)
88 return self
._op
(truediv
, b
)
91 return self
._op
(mod
, b
)
94 return self
._op
(and_
, b
)
97 return self
._op
(or_
, b
)
100 return self
._op
(xor
, b
)
103 vi
= SelectableInt(0, len(self
.br
))
104 for k
, v
in self
.br
.items():
110 for i
, v
in fi
.br
.items():
115 return "FieldSelectableInt(si=%s, br=%s)" % (self
.si
, self
.br
)
117 def asint(self
, msb0
=False):
120 for i
, key
in self
.br
.items():
121 bit
= self
.si
[key
].value
122 #print("asint", i, key, bit)
123 res |
= bit
<< ((brlen
-i
-1) if msb0
else i
)
127 class FieldSelectableIntTestCase(unittest
.TestCase
):
128 def test_arith(self
):
129 a
= SelectableInt(0b10101, 5)
130 b
= SelectableInt(0b011, 3)
135 fs
= FieldSelectableInt(a
, br
)
138 #self.assertEqual(c.value, a.value + b.value)
140 def test_select(self
):
141 a
= SelectableInt(0b00001111, 8)
147 fs
= FieldSelectableInt(a
, br
)
149 self
.assertEqual(fs
.get_range(), 0b0011)
151 def test_select_range(self
):
152 a
= SelectableInt(0b00001111, 8)
158 fs
= FieldSelectableInt(a
, br
)
160 self
.assertEqual(fs
[2:4], 0b11)
163 self
.assertEqual(fs
.get_range(), 0b1011)
166 """SelectableInt - a class that behaves exactly like python int
168 this class is designed to mirror precisely the behaviour of python int.
169 the only difference is that it must contain the context of the bitwidth
170 (number of bits) associated with that integer.
172 FieldSelectableInt can then operate on partial bits, and because there
173 is a bit width associated with SelectableInt, slices operate correctly
174 including negative start/end points.
177 def __init__(self
, value
, bits
):
178 if isinstance(value
, SelectableInt
):
180 mask
= (1 << bits
) - 1
181 self
.value
= value
& mask
183 self
.overflow
= (value
& ~mask
) != 0
189 def to_signed_int(self
):
190 print ("to signed?", self
.value
& (1<<(self
.bits
-1)), self
.value
)
191 if self
.value
& (1<<(self
.bits
-1)) != 0: # negative
192 res
= self
.value
- (1<<self
.bits
)
193 print (" val -ve:", self
.bits
, res
)
196 print (" val +ve:", res
)
199 def _op(self
, op
, b
):
200 if isinstance(b
, int):
201 b
= SelectableInt(b
, self
.bits
)
202 b
= check_extsign(self
, b
)
203 assert b
.bits
== self
.bits
204 return SelectableInt(op(self
.value
, b
.value
), self
.bits
)
206 def __add__(self
, b
):
207 return self
._op
(add
, b
)
209 def __sub__(self
, b
):
210 return self
._op
(sub
, b
)
212 def __mul__(self
, b
):
213 # different case: mul result needs to fit the total bitsize
214 if isinstance(b
, int):
215 b
= SelectableInt(b
, self
.bits
)
216 print("SelectableInt mul", hex(self
.value
), hex(b
.value
),
218 return SelectableInt(self
.value
* b
.value
, self
.bits
+ b
.bits
)
220 def __floordiv__(self
, b
):
221 return self
._op
(floordiv
, b
)
223 def __truediv__(self
, b
):
224 return self
._op
(truediv
, b
)
226 def __mod__(self
, b
):
227 return self
._op
(mod
, b
)
229 def __and__(self
, b
):
230 return self
._op
(and_
, b
)
233 return self
._op
(or_
, b
)
235 def __xor__(self
, b
):
236 return self
._op
(xor
, b
)
239 print("abs", self
.value
& (1 << (self
.bits
-1)))
240 if self
.value
& (1 << (self
.bits
-1)) != 0:
244 def __rsub__(self
, b
):
245 if isinstance(b
, int):
246 b
= SelectableInt(b
, self
.bits
)
247 b
= check_extsign(self
, b
)
248 assert b
.bits
== self
.bits
249 return SelectableInt(b
.value
- self
.value
, self
.bits
)
251 def __radd__(self
, b
):
252 if isinstance(b
, int):
253 b
= SelectableInt(b
, self
.bits
)
254 b
= check_extsign(self
, b
)
255 assert b
.bits
== self
.bits
256 return SelectableInt(b
.value
+ self
.value
, self
.bits
)
258 def __rxor__(self
, b
):
259 b
= check_extsign(self
, b
)
260 assert b
.bits
== self
.bits
261 return SelectableInt(self
.value ^ b
.value
, self
.bits
)
263 def __invert__(self
):
264 return SelectableInt(~self
.value
, self
.bits
)
267 res
= SelectableInt((~self
.value
) + 1, self
.bits
)
268 print ("neg", hex(self
.value
), hex(res
.value
))
271 def __lshift__(self
, b
):
272 b
= check_extsign(self
, b
)
273 return SelectableInt(self
.value
<< b
.value
, self
.bits
)
275 def __rshift__(self
, b
):
276 b
= check_extsign(self
, b
)
277 return SelectableInt(self
.value
>> b
.value
, self
.bits
)
279 def __getitem__(self
, key
):
280 if isinstance(key
, SelectableInt
):
282 if isinstance(key
, int):
283 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
285 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
286 # MSB is indexed **LOWEST** (sigh)
287 key
= self
.bits
- (key
+ 1)
289 value
= (self
.value
>> key
) & 1
290 print("getitem", key
, self
.bits
, hex(self
.value
), value
)
291 return SelectableInt(value
, 1)
292 elif isinstance(key
, slice):
293 assert key
.step
is None or key
.step
== 1
294 assert key
.start
< key
.stop
295 assert key
.start
>= 0
296 assert key
.stop
<= self
.bits
298 stop
= self
.bits
- key
.start
299 start
= self
.bits
- key
.stop
302 #print ("__getitem__ slice num bits", start, stop, bits)
303 mask
= (1 << bits
) - 1
304 value
= (self
.value
>> start
) & mask
305 print("getitem", stop
, start
, self
.bits
, hex(self
.value
), value
)
306 return SelectableInt(value
, bits
)
308 def __setitem__(self
, key
, value
):
309 if isinstance(key
, SelectableInt
):
311 print("setitem", key
, self
.bits
, hex(self
.value
))
312 if isinstance(key
, int):
313 assert key
< self
.bits
315 key
= self
.bits
- (key
+ 1)
316 if isinstance(value
, SelectableInt
):
317 assert value
.bits
== 1
322 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
323 elif isinstance(key
, slice):
324 assert key
.step
is None or key
.step
== 1
325 assert key
.start
< key
.stop
326 assert key
.start
>= 0
327 assert key
.stop
<= self
.bits
329 stop
= self
.bits
- key
.start
330 start
= self
.bits
- key
.stop
333 #print ("__setitem__ slice num bits", bits)
334 if isinstance(value
, SelectableInt
):
335 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
337 mask
= ((1 << bits
) - 1) << start
338 value
= value
<< start
339 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
341 def __ge__(self
, other
):
342 if isinstance(other
, FieldSelectableInt
):
343 other
= other
.get_range()
344 if isinstance(other
, SelectableInt
):
345 other
= check_extsign(self
, other
)
346 assert other
.bits
== self
.bits
347 other
= other
.to_signed_int()
348 if isinstance(other
, int):
349 return onebit(self
.to_signed_int() >= other
)
352 def __le__(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 __gt__(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 __lt__(self
, other
):
375 print ("SelectableInt lt", self
, other
)
376 if isinstance(other
, FieldSelectableInt
):
377 other
= other
.get_range()
378 if isinstance(other
, SelectableInt
):
379 other
= check_extsign(self
, other
)
380 assert other
.bits
== self
.bits
381 other
= other
.to_signed_int()
382 if isinstance(other
, int):
383 a
= self
.to_signed_int()
384 res
= onebit(a
< other
)
385 print (" a < b", a
, other
, res
)
389 def __eq__(self
, other
):
390 print("__eq__", self
, other
)
391 if isinstance(other
, FieldSelectableInt
):
392 other
= other
.get_range()
393 if isinstance(other
, SelectableInt
):
394 other
= check_extsign(self
, other
)
395 assert other
.bits
== self
.bits
397 print (" eq", other
, self
.value
, other
== self
.value
)
398 if isinstance(other
, int):
399 return onebit(other
== self
.value
)
402 def narrow(self
, bits
):
403 assert bits
<= self
.bits
404 return SelectableInt(self
.value
, bits
)
407 return self
.value
!= 0
410 return "SelectableInt(value=0x{:x}, bits={})".format(self
.value
,
421 return SelectableInt(1 if bit
else 0, 1)
424 def selectltu(lhs
, rhs
):
425 """ less-than (unsigned)
427 if isinstance(rhs
, SelectableInt
):
429 return onebit(lhs
.value
< rhs
)
432 def selectgtu(lhs
, rhs
):
433 """ greater-than (unsigned)
435 if isinstance(rhs
, SelectableInt
):
437 return onebit(lhs
.value
> rhs
)
440 # XXX this probably isn't needed...
441 def selectassign(lhs
, idx
, rhs
):
442 if isinstance(idx
, tuple):
447 lower
, upper
, step
= idx
448 toidx
= range(lower
, upper
, step
)
449 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
453 for t
, f
in zip(toidx
, fromidx
):
457 def selectconcat(*args
, repeat
=1):
458 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
459 args
= [SelectableInt(args
[0], 1)]
460 if repeat
!= 1: # multiplies the incoming arguments
462 for i
in range(repeat
):
467 if isinstance(i
, FieldSelectableInt
):
469 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
471 res
.value
= (res
.value
<< i
.bits
) | i
.value
472 print("concat", repeat
, res
)
476 class SelectableIntTestCase(unittest
.TestCase
):
477 def test_arith(self
):
478 a
= SelectableInt(5, 8)
479 b
= SelectableInt(9, 8)
486 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
487 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
488 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
489 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
490 self
.assertEqual(c
.bits
, a
.bits
)
491 self
.assertEqual(d
.bits
, a
.bits
)
492 self
.assertEqual(e
.bits
, a
.bits
)
493 self
.assertEqual(a
.bits
, f
.bits
)
494 self
.assertEqual(a
.bits
, h
.bits
)
496 def test_logic(self
):
497 a
= SelectableInt(0x0F, 8)
498 b
= SelectableInt(0xA5, 8)
503 self
.assertEqual(c
.value
, a
.value
& b
.value
)
504 self
.assertEqual(d
.value
, a
.value | b
.value
)
505 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
506 self
.assertEqual(f
.value
, 0xF0)
509 a
= SelectableInt(0xa2, 8)
510 # These should be big endian
511 self
.assertEqual(a
[7], 0)
512 self
.assertEqual(a
[0:4], 10)
513 self
.assertEqual(a
[4:8], 2)
516 a
= SelectableInt(0x5, 8)
517 a
[7] = SelectableInt(0, 1)
518 self
.assertEqual(a
, 4)
520 self
.assertEqual(a
, 9)
522 self
.assertEqual(a
, 0x39)
524 self
.assertEqual(a
, 0x99)
526 def test_concat(self
):
527 a
= SelectableInt(0x1, 1)
528 c
= selectconcat(a
, repeat
=8)
529 self
.assertEqual(c
, 0xff)
530 self
.assertEqual(c
.bits
, 8)
531 a
= SelectableInt(0x0, 1)
532 c
= selectconcat(a
, repeat
=8)
533 self
.assertEqual(c
, 0x00)
534 self
.assertEqual(c
.bits
, 8)
537 for i
in range(65536):
538 a
= SelectableInt(i
, 16)
540 self
.assertEqual(a
, b
)
543 a
= SelectableInt(10, bits
=8)
544 b
= SelectableInt(5, bits
=8)
545 self
.assertTrue(a
> b
)
546 self
.assertFalse(a
< b
)
547 self
.assertTrue(a
!= b
)
548 self
.assertFalse(a
== b
)
550 def test_unsigned(self
):
551 a
= SelectableInt(0x80, bits
=8)
552 b
= SelectableInt(0x7f, bits
=8)
553 self
.assertTrue(a
> b
)
554 self
.assertFalse(a
< b
)
555 self
.assertTrue(a
!= b
)
556 self
.assertFalse(a
== b
)
559 if __name__
== "__main__":