3 from soc
.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 enumerate(self
.br
):
121 res |
= self
.si
[key
].value
<< ((brlen
-i
-1) if msb0
else i
)
125 class FieldSelectableIntTestCase(unittest
.TestCase
):
126 def test_arith(self
):
127 a
= SelectableInt(0b10101, 5)
128 b
= SelectableInt(0b011, 3)
133 fs
= FieldSelectableInt(a
, br
)
136 #self.assertEqual(c.value, a.value + b.value)
138 def test_select(self
):
139 a
= SelectableInt(0b00001111, 8)
145 fs
= FieldSelectableInt(a
, br
)
147 self
.assertEqual(fs
.get_range(), 0b0011)
149 def test_select_range(self
):
150 a
= SelectableInt(0b00001111, 8)
156 fs
= FieldSelectableInt(a
, br
)
158 self
.assertEqual(fs
[2:4], 0b11)
161 self
.assertEqual(fs
.get_range(), 0b1011)
164 """SelectableInt - a class that behaves exactly like python int
166 this class is designed to mirror precisely the behaviour of python int.
167 the only difference is that it must contain the context of the bitwidth
168 (number of bits) associated with that integer.
170 FieldSelectableInt can then operate on partial bits, and because there
171 is a bit width associated with SelectableInt, slices operate correctly
172 including negative start/end points.
175 def __init__(self
, value
, bits
):
176 if isinstance(value
, SelectableInt
):
178 mask
= (1 << bits
) - 1
179 self
.value
= value
& mask
181 self
.overflow
= (value
& ~mask
) != 0
187 def to_signed_int(self
):
188 print ("to signed?", self
.value
& (1<<(self
.bits
-1)), self
.value
)
189 if self
.value
& (1<<(self
.bits
-1)) != 0: # negative
190 res
= self
.value
- (1<<self
.bits
)
191 print (" val -ve:", self
.bits
, res
)
194 print (" val +ve:", res
)
197 def _op(self
, op
, b
):
198 if isinstance(b
, int):
199 b
= SelectableInt(b
, self
.bits
)
200 b
= check_extsign(self
, b
)
201 assert b
.bits
== self
.bits
202 return SelectableInt(op(self
.value
, b
.value
), self
.bits
)
204 def __add__(self
, b
):
205 return self
._op
(add
, b
)
207 def __sub__(self
, b
):
208 return self
._op
(sub
, b
)
210 def __mul__(self
, b
):
211 # different case: mul result needs to fit the total bitsize
212 if isinstance(b
, int):
213 b
= SelectableInt(b
, self
.bits
)
214 print("SelectableInt mul", hex(self
.value
), hex(b
.value
),
216 return SelectableInt(self
.value
* b
.value
, self
.bits
+ b
.bits
)
218 def __floordiv__(self
, b
):
219 return self
._op
(floordiv
, b
)
221 def __truediv__(self
, b
):
222 return self
._op
(truediv
, b
)
224 def __mod__(self
, b
):
225 return self
._op
(mod
, b
)
227 def __and__(self
, b
):
228 return self
._op
(and_
, b
)
231 return self
._op
(or_
, b
)
233 def __xor__(self
, b
):
234 return self
._op
(xor
, b
)
237 print("abs", self
.value
& (1 << (self
.bits
-1)))
238 if self
.value
& (1 << (self
.bits
-1)) != 0:
242 def __rsub__(self
, b
):
243 if isinstance(b
, int):
244 b
= SelectableInt(b
, self
.bits
)
245 b
= check_extsign(self
, b
)
246 assert b
.bits
== self
.bits
247 return SelectableInt(b
.value
- self
.value
, self
.bits
)
249 def __radd__(self
, b
):
250 if isinstance(b
, int):
251 b
= SelectableInt(b
, self
.bits
)
252 b
= check_extsign(self
, b
)
253 assert b
.bits
== self
.bits
254 return SelectableInt(b
.value
+ self
.value
, self
.bits
)
256 def __rxor__(self
, b
):
257 b
= check_extsign(self
, b
)
258 assert b
.bits
== self
.bits
259 return SelectableInt(self
.value ^ b
.value
, self
.bits
)
261 def __invert__(self
):
262 return SelectableInt(~self
.value
, self
.bits
)
265 res
= SelectableInt((~self
.value
) + 1, self
.bits
)
266 print ("neg", hex(self
.value
), hex(res
.value
))
269 def __lshift__(self
, b
):
270 b
= check_extsign(self
, b
)
271 return SelectableInt(self
.value
<< b
.value
, self
.bits
)
273 def __rshift__(self
, b
):
274 b
= check_extsign(self
, b
)
275 return SelectableInt(self
.value
>> b
.value
, self
.bits
)
277 def __getitem__(self
, key
):
278 if isinstance(key
, SelectableInt
):
280 print("getitem", key
, self
.bits
, hex(self
.value
))
281 if isinstance(key
, int):
282 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
284 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
285 # MSB is indexed **LOWEST** (sigh)
286 key
= self
.bits
- (key
+ 1)
288 value
= (self
.value
>> key
) & 1
289 return SelectableInt(value
, 1)
290 elif isinstance(key
, slice):
291 assert key
.step
is None or key
.step
== 1
292 assert key
.start
< key
.stop
293 assert key
.start
>= 0
294 assert key
.stop
<= self
.bits
296 stop
= self
.bits
- key
.start
297 start
= self
.bits
- key
.stop
300 #print ("__getitem__ slice num bits", start, stop, bits)
301 mask
= (1 << bits
) - 1
302 value
= (self
.value
>> start
) & mask
303 return SelectableInt(value
, bits
)
305 def __setitem__(self
, key
, value
):
306 if isinstance(key
, SelectableInt
):
308 print("setitem", key
, self
.bits
, hex(self
.value
))
309 if isinstance(key
, int):
310 assert key
< self
.bits
312 key
= self
.bits
- (key
+ 1)
313 if isinstance(value
, SelectableInt
):
314 assert value
.bits
== 1
319 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
320 elif isinstance(key
, slice):
321 assert key
.step
is None or key
.step
== 1
322 assert key
.start
< key
.stop
323 assert key
.start
>= 0
324 assert key
.stop
<= self
.bits
326 stop
= self
.bits
- key
.start
327 start
= self
.bits
- key
.stop
330 #print ("__setitem__ slice num bits", bits)
331 if isinstance(value
, SelectableInt
):
332 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
334 mask
= ((1 << bits
) - 1) << start
335 value
= value
<< start
336 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
338 def __ge__(self
, other
):
339 if isinstance(other
, FieldSelectableInt
):
340 other
= other
.get_range()
341 if isinstance(other
, SelectableInt
):
342 other
= check_extsign(self
, other
)
343 assert other
.bits
== self
.bits
344 other
= other
.to_signed_int()
345 if isinstance(other
, int):
346 return onebit(self
.to_signed_int() >= other
)
349 def __le__(self
, other
):
350 if isinstance(other
, FieldSelectableInt
):
351 other
= other
.get_range()
352 if isinstance(other
, SelectableInt
):
353 other
= check_extsign(self
, other
)
354 assert other
.bits
== self
.bits
355 other
= other
.to_signed_int()
356 if isinstance(other
, int):
357 return onebit(self
.to_signed_int() <= other
)
360 def __gt__(self
, other
):
361 if isinstance(other
, FieldSelectableInt
):
362 other
= other
.get_range()
363 if isinstance(other
, SelectableInt
):
364 other
= check_extsign(self
, other
)
365 assert other
.bits
== self
.bits
366 other
= other
.to_signed_int()
367 if isinstance(other
, int):
368 return onebit(self
.to_signed_int() > other
)
371 def __lt__(self
, other
):
372 print ("SelectableInt lt", 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 a
= self
.to_signed_int()
381 res
= onebit(a
< other
)
382 print (" a < b", a
, other
, res
)
386 def __eq__(self
, other
):
387 print("__eq__", self
, other
)
388 if isinstance(other
, FieldSelectableInt
):
389 other
= other
.get_range()
390 if isinstance(other
, SelectableInt
):
391 other
= check_extsign(self
, other
)
392 assert other
.bits
== self
.bits
394 print (" eq", other
, self
.value
, other
== self
.value
)
395 if isinstance(other
, int):
396 return onebit(other
== self
.value
)
399 def narrow(self
, bits
):
400 assert bits
<= self
.bits
401 return SelectableInt(self
.value
, bits
)
404 return self
.value
!= 0
407 return "SelectableInt(value=0x{:x}, bits={})".format(self
.value
,
418 return SelectableInt(1 if bit
else 0, 1)
421 def selectltu(lhs
, rhs
):
422 """ less-than (unsigned)
424 if isinstance(rhs
, SelectableInt
):
426 return onebit(lhs
.value
< rhs
)
429 def selectgtu(lhs
, rhs
):
430 """ greater-than (unsigned)
432 if isinstance(rhs
, SelectableInt
):
434 return onebit(lhs
.value
> rhs
)
437 # XXX this probably isn't needed...
438 def selectassign(lhs
, idx
, rhs
):
439 if isinstance(idx
, tuple):
444 lower
, upper
, step
= idx
445 toidx
= range(lower
, upper
, step
)
446 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
450 for t
, f
in zip(toidx
, fromidx
):
454 def selectconcat(*args
, repeat
=1):
455 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
456 args
= [SelectableInt(args
[0], 1)]
457 if repeat
!= 1: # multiplies the incoming arguments
459 for i
in range(repeat
):
464 if isinstance(i
, FieldSelectableInt
):
466 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
468 res
.value
= (res
.value
<< i
.bits
) | i
.value
469 print("concat", repeat
, res
)
473 class SelectableIntTestCase(unittest
.TestCase
):
474 def test_arith(self
):
475 a
= SelectableInt(5, 8)
476 b
= SelectableInt(9, 8)
483 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
484 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
485 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
486 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
487 self
.assertEqual(c
.bits
, a
.bits
)
488 self
.assertEqual(d
.bits
, a
.bits
)
489 self
.assertEqual(e
.bits
, a
.bits
)
490 self
.assertEqual(a
.bits
, f
.bits
)
491 self
.assertEqual(a
.bits
, h
.bits
)
493 def test_logic(self
):
494 a
= SelectableInt(0x0F, 8)
495 b
= SelectableInt(0xA5, 8)
500 self
.assertEqual(c
.value
, a
.value
& b
.value
)
501 self
.assertEqual(d
.value
, a
.value | b
.value
)
502 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
503 self
.assertEqual(f
.value
, 0xF0)
506 a
= SelectableInt(0xa2, 8)
507 # These should be big endian
508 self
.assertEqual(a
[7], 0)
509 self
.assertEqual(a
[0:4], 10)
510 self
.assertEqual(a
[4:8], 2)
513 a
= SelectableInt(0x5, 8)
514 a
[7] = SelectableInt(0, 1)
515 self
.assertEqual(a
, 4)
517 self
.assertEqual(a
, 9)
519 self
.assertEqual(a
, 0x39)
521 self
.assertEqual(a
, 0x99)
523 def test_concat(self
):
524 a
= SelectableInt(0x1, 1)
525 c
= selectconcat(a
, repeat
=8)
526 self
.assertEqual(c
, 0xff)
527 self
.assertEqual(c
.bits
, 8)
528 a
= SelectableInt(0x0, 1)
529 c
= selectconcat(a
, repeat
=8)
530 self
.assertEqual(c
, 0x00)
531 self
.assertEqual(c
.bits
, 8)
534 for i
in range(65536):
535 a
= SelectableInt(i
, 16)
537 self
.assertEqual(a
, b
)
540 a
= SelectableInt(10, bits
=8)
541 b
= SelectableInt(5, bits
=8)
542 self
.assertTrue(a
> b
)
543 self
.assertFalse(a
< b
)
544 self
.assertTrue(a
!= b
)
545 self
.assertFalse(a
== b
)
547 def test_unsigned(self
):
548 a
= SelectableInt(0x80, bits
=8)
549 b
= SelectableInt(0x7f, bits
=8)
550 self
.assertTrue(a
> b
)
551 self
.assertFalse(a
< b
)
552 self
.assertTrue(a
!= b
)
553 self
.assertFalse(a
== b
)
556 if __name__
== "__main__":