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
)
118 class FieldSelectableIntTestCase(unittest
.TestCase
):
119 def test_arith(self
):
120 a
= SelectableInt(0b10101, 5)
121 b
= SelectableInt(0b011, 3)
126 fs
= FieldSelectableInt(a
, br
)
129 #self.assertEqual(c.value, a.value + b.value)
131 def test_select(self
):
132 a
= SelectableInt(0b00001111, 8)
138 fs
= FieldSelectableInt(a
, br
)
140 self
.assertEqual(fs
.get_range(), 0b0011)
142 def test_select_range(self
):
143 a
= SelectableInt(0b00001111, 8)
149 fs
= FieldSelectableInt(a
, br
)
151 self
.assertEqual(fs
[2:4], 0b11)
154 self
.assertEqual(fs
.get_range(), 0b1011)
157 """SelectableInt - a class that behaves exactly like python int
159 this class is designed to mirror precisely the behaviour of python int.
160 the only difference is that it must contain the context of the bitwidth
161 (number of bits) associated with that integer.
163 FieldSelectableInt can then operate on partial bits, and because there
164 is a bit width associated with SelectableInt, slices operate correctly
165 including negative start/end points.
168 def __init__(self
, value
, bits
):
169 if isinstance(value
, SelectableInt
):
171 mask
= (1 << bits
) - 1
172 self
.value
= value
& mask
174 self
.overflow
= (value
& ~mask
) != 0
180 def to_signed_int(self
):
181 print ("to signed?", self
.value
& (1<<(self
.bits
-1)), self
.value
)
182 if self
.value
& (1<<(self
.bits
-1)) != 0: # negative
183 res
= self
.value
- (1<<self
.bits
)
184 print (" val -ve:", self
.bits
, res
)
187 print (" val +ve:", res
)
190 def _op(self
, op
, b
):
191 if isinstance(b
, int):
192 b
= SelectableInt(b
, self
.bits
)
193 b
= check_extsign(self
, b
)
194 assert b
.bits
== self
.bits
195 return SelectableInt(op(self
.value
, b
.value
), self
.bits
)
197 def __add__(self
, b
):
198 return self
._op
(add
, b
)
200 def __sub__(self
, b
):
201 return self
._op
(sub
, b
)
203 def __mul__(self
, b
):
204 # different case: mul result needs to fit the total bitsize
205 if isinstance(b
, int):
206 b
= SelectableInt(b
, self
.bits
)
207 print("SelectableInt mul", hex(self
.value
), hex(b
.value
),
209 return SelectableInt(self
.value
* b
.value
, self
.bits
+ b
.bits
)
211 def __floordiv__(self
, b
):
212 return self
._op
(floordiv
, b
)
214 def __truediv__(self
, b
):
215 return self
._op
(truediv
, b
)
217 def __mod__(self
, b
):
218 return self
._op
(mod
, b
)
220 def __and__(self
, b
):
221 return self
._op
(and_
, b
)
224 return self
._op
(or_
, b
)
226 def __xor__(self
, b
):
227 return self
._op
(xor
, b
)
230 print("abs", self
.value
& (1 << (self
.bits
-1)))
231 if self
.value
& (1 << (self
.bits
-1)) != 0:
235 def __rsub__(self
, b
):
236 if isinstance(b
, int):
237 b
= SelectableInt(b
, self
.bits
)
238 b
= check_extsign(self
, b
)
239 assert b
.bits
== self
.bits
240 return SelectableInt(b
.value
- self
.value
, self
.bits
)
242 def __radd__(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 __rxor__(self
, b
):
250 b
= check_extsign(self
, b
)
251 assert b
.bits
== self
.bits
252 return SelectableInt(self
.value ^ b
.value
, self
.bits
)
254 def __invert__(self
):
255 return SelectableInt(~self
.value
, self
.bits
)
258 res
= SelectableInt((~self
.value
) + 1, self
.bits
)
259 print ("neg", hex(self
.value
), hex(res
.value
))
262 def __lshift__(self
, b
):
263 b
= check_extsign(self
, b
)
264 return SelectableInt(self
.value
<< b
.value
, self
.bits
)
266 def __rshift__(self
, b
):
267 b
= check_extsign(self
, b
)
268 return SelectableInt(self
.value
>> b
.value
, self
.bits
)
270 def __getitem__(self
, key
):
271 if isinstance(key
, SelectableInt
):
273 print("getitem", key
, self
.bits
, hex(self
.value
))
274 if isinstance(key
, int):
275 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
277 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
278 # MSB is indexed **LOWEST** (sigh)
279 key
= self
.bits
- (key
+ 1)
281 value
= (self
.value
>> key
) & 1
282 return SelectableInt(value
, 1)
283 elif isinstance(key
, slice):
284 assert key
.step
is None or key
.step
== 1
285 assert key
.start
< key
.stop
286 assert key
.start
>= 0
287 assert key
.stop
<= self
.bits
289 stop
= self
.bits
- key
.start
290 start
= self
.bits
- key
.stop
293 #print ("__getitem__ slice num bits", start, stop, bits)
294 mask
= (1 << bits
) - 1
295 value
= (self
.value
>> start
) & mask
296 return SelectableInt(value
, bits
)
298 def __setitem__(self
, key
, value
):
299 if isinstance(key
, SelectableInt
):
301 print("setitem", key
, self
.bits
, hex(self
.value
))
302 if isinstance(key
, int):
303 assert key
< self
.bits
305 key
= self
.bits
- (key
+ 1)
306 if isinstance(value
, SelectableInt
):
307 assert value
.bits
== 1
312 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
313 elif isinstance(key
, slice):
314 assert key
.step
is None or key
.step
== 1
315 assert key
.start
< key
.stop
316 assert key
.start
>= 0
317 assert key
.stop
<= self
.bits
319 stop
= self
.bits
- key
.start
320 start
= self
.bits
- key
.stop
323 #print ("__setitem__ slice num bits", bits)
324 if isinstance(value
, SelectableInt
):
325 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
327 mask
= ((1 << bits
) - 1) << start
328 value
= value
<< start
329 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
331 def __ge__(self
, other
):
332 if isinstance(other
, FieldSelectableInt
):
333 other
= other
.get_range()
334 if isinstance(other
, SelectableInt
):
335 other
= check_extsign(self
, other
)
336 assert other
.bits
== self
.bits
337 other
= other
.to_signed_int()
338 if isinstance(other
, int):
339 return onebit(self
.to_signed_int() >= other
)
342 def __le__(self
, other
):
343 if isinstance(other
, FieldSelectableInt
):
344 other
= other
.get_range()
345 if isinstance(other
, SelectableInt
):
346 other
= check_extsign(self
, other
)
347 assert other
.bits
== self
.bits
348 other
= other
.to_signed_int()
349 if isinstance(other
, int):
350 return onebit(self
.to_signed_int() <= other
)
353 def __gt__(self
, other
):
354 if isinstance(other
, FieldSelectableInt
):
355 other
= other
.get_range()
356 if isinstance(other
, SelectableInt
):
357 other
= check_extsign(self
, other
)
358 assert other
.bits
== self
.bits
359 other
= other
.to_signed_int()
360 if isinstance(other
, int):
361 return onebit(self
.to_signed_int() > other
)
364 def __lt__(self
, other
):
365 print ("SelectableInt lt", 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 a
= self
.to_signed_int()
374 res
= onebit(a
< other
)
375 print (" a < b", a
, other
, res
)
379 def __eq__(self
, other
):
380 print("__eq__", self
, other
)
381 if isinstance(other
, FieldSelectableInt
):
382 other
= other
.get_range()
383 if isinstance(other
, SelectableInt
):
384 other
= check_extsign(self
, other
)
385 assert other
.bits
== self
.bits
387 print (" eq", other
, self
.value
, other
== self
.value
)
388 if isinstance(other
, int):
389 return onebit(other
== self
.value
)
392 def narrow(self
, bits
):
393 assert bits
<= self
.bits
394 return SelectableInt(self
.value
, bits
)
397 return self
.value
!= 0
400 return "SelectableInt(value=0x{:x}, bits={})".format(self
.value
,
411 return SelectableInt(1 if bit
else 0, 1)
414 def selectltu(lhs
, rhs
):
415 """ less-than (unsigned)
417 if isinstance(rhs
, SelectableInt
):
419 return onebit(lhs
.value
< rhs
)
422 def selectgtu(lhs
, rhs
):
423 """ greater-than (unsigned)
425 if isinstance(rhs
, SelectableInt
):
427 return onebit(lhs
.value
> rhs
)
430 # XXX this probably isn't needed...
431 def selectassign(lhs
, idx
, rhs
):
432 if isinstance(idx
, tuple):
437 lower
, upper
, step
= idx
438 toidx
= range(lower
, upper
, step
)
439 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
443 for t
, f
in zip(toidx
, fromidx
):
447 def selectconcat(*args
, repeat
=1):
448 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
449 args
= [SelectableInt(args
[0], 1)]
450 if repeat
!= 1: # multiplies the incoming arguments
452 for i
in range(repeat
):
457 if isinstance(i
, FieldSelectableInt
):
459 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
461 res
.value
= (res
.value
<< i
.bits
) | i
.value
462 print("concat", repeat
, res
)
466 class SelectableIntTestCase(unittest
.TestCase
):
467 def test_arith(self
):
468 a
= SelectableInt(5, 8)
469 b
= SelectableInt(9, 8)
476 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
477 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
478 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
479 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
480 self
.assertEqual(c
.bits
, a
.bits
)
481 self
.assertEqual(d
.bits
, a
.bits
)
482 self
.assertEqual(e
.bits
, a
.bits
)
483 self
.assertEqual(a
.bits
, f
.bits
)
484 self
.assertEqual(a
.bits
, h
.bits
)
486 def test_logic(self
):
487 a
= SelectableInt(0x0F, 8)
488 b
= SelectableInt(0xA5, 8)
493 self
.assertEqual(c
.value
, a
.value
& b
.value
)
494 self
.assertEqual(d
.value
, a
.value | b
.value
)
495 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
496 self
.assertEqual(f
.value
, 0xF0)
499 a
= SelectableInt(0xa2, 8)
500 # These should be big endian
501 self
.assertEqual(a
[7], 0)
502 self
.assertEqual(a
[0:4], 10)
503 self
.assertEqual(a
[4:8], 2)
506 a
= SelectableInt(0x5, 8)
507 a
[7] = SelectableInt(0, 1)
508 self
.assertEqual(a
, 4)
510 self
.assertEqual(a
, 9)
512 self
.assertEqual(a
, 0x39)
514 self
.assertEqual(a
, 0x99)
516 def test_concat(self
):
517 a
= SelectableInt(0x1, 1)
518 c
= selectconcat(a
, repeat
=8)
519 self
.assertEqual(c
, 0xff)
520 self
.assertEqual(c
.bits
, 8)
521 a
= SelectableInt(0x0, 1)
522 c
= selectconcat(a
, repeat
=8)
523 self
.assertEqual(c
, 0x00)
524 self
.assertEqual(c
.bits
, 8)
527 for i
in range(65536):
528 a
= SelectableInt(i
, 16)
530 self
.assertEqual(a
, b
)
533 a
= SelectableInt(10, bits
=8)
534 b
= SelectableInt(5, bits
=8)
535 self
.assertTrue(a
> b
)
536 self
.assertFalse(a
< b
)
537 self
.assertTrue(a
!= b
)
538 self
.assertFalse(a
== b
)
540 def test_unsigned(self
):
541 a
= SelectableInt(0x80, bits
=8)
542 b
= SelectableInt(0x7f, bits
=8)
543 self
.assertTrue(a
> b
)
544 self
.assertFalse(a
< b
)
545 self
.assertTrue(a
!= b
)
546 self
.assertFalse(a
== b
)
549 if __name__
== "__main__":