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
179 def to_signed_int(self
):
180 print ("to signed?", self
.value
& (1<<(self
.bits
-1)), self
.value
)
181 if self
.value
& (1<<(self
.bits
-1)) != 0: # negative
182 res
= self
.value
- (1<<self
.bits
)
183 print (" val -ve:", self
.bits
, res
)
186 print (" val +ve:", res
)
189 def _op(self
, op
, b
):
190 if isinstance(b
, int):
191 b
= SelectableInt(b
, self
.bits
)
192 b
= check_extsign(self
, b
)
193 assert b
.bits
== self
.bits
194 return SelectableInt(op(self
.value
, b
.value
), self
.bits
)
196 def __add__(self
, b
):
197 return self
._op
(add
, b
)
199 def __sub__(self
, b
):
200 return self
._op
(sub
, b
)
202 def __mul__(self
, b
):
203 # different case: mul result needs to fit the total bitsize
204 if isinstance(b
, int):
205 b
= SelectableInt(b
, self
.bits
)
206 print("SelectableInt mul", hex(self
.value
), hex(b
.value
),
208 return SelectableInt(self
.value
* b
.value
, self
.bits
+ b
.bits
)
210 def __floordiv__(self
, b
):
211 return self
._op
(floordiv
, b
)
213 def __truediv__(self
, b
):
214 return self
._op
(truediv
, b
)
216 def __mod__(self
, b
):
217 return self
._op
(mod
, b
)
219 def __and__(self
, b
):
220 return self
._op
(and_
, b
)
223 return self
._op
(or_
, b
)
225 def __xor__(self
, b
):
226 return self
._op
(xor
, b
)
229 print("abs", self
.value
& (1 << (self
.bits
-1)))
230 if self
.value
& (1 << (self
.bits
-1)) != 0:
234 def __rsub__(self
, b
):
235 if isinstance(b
, int):
236 b
= SelectableInt(b
, self
.bits
)
237 b
= check_extsign(self
, b
)
238 assert b
.bits
== self
.bits
239 return SelectableInt(b
.value
- self
.value
, self
.bits
)
241 def __radd__(self
, b
):
242 if isinstance(b
, int):
243 b
= SelectableInt(b
, self
.bits
)
244 b
= check_extsign(self
, b
)
245 assert b
.bits
== self
.bits
246 return SelectableInt(b
.value
+ self
.value
, self
.bits
)
248 def __rxor__(self
, b
):
249 b
= check_extsign(self
, b
)
250 assert b
.bits
== self
.bits
251 return SelectableInt(self
.value ^ b
.value
, self
.bits
)
253 def __invert__(self
):
254 return SelectableInt(~self
.value
, self
.bits
)
257 res
= SelectableInt((~self
.value
) + 1, self
.bits
)
258 print ("neg", hex(self
.value
), hex(res
.value
))
261 def __lshift__(self
, b
):
262 b
= check_extsign(self
, b
)
263 return SelectableInt(self
.value
<< b
.value
, self
.bits
)
265 def __rshift__(self
, b
):
266 b
= check_extsign(self
, b
)
267 return SelectableInt(self
.value
>> b
.value
, self
.bits
)
269 def __getitem__(self
, key
):
270 if isinstance(key
, SelectableInt
):
272 if isinstance(key
, int):
273 assert key
< self
.bits
, "key %d accessing %d" % (key
, self
.bits
)
275 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
276 # MSB is indexed **LOWEST** (sigh)
277 key
= self
.bits
- (key
+ 1)
279 value
= (self
.value
>> key
) & 1
280 return SelectableInt(value
, 1)
281 elif isinstance(key
, slice):
282 assert key
.step
is None or key
.step
== 1
283 assert key
.start
< key
.stop
284 assert key
.start
>= 0
285 assert key
.stop
<= self
.bits
287 stop
= self
.bits
- key
.start
288 start
= self
.bits
- key
.stop
291 #print ("__getitem__ slice num bits", bits)
292 mask
= (1 << bits
) - 1
293 value
= (self
.value
>> start
) & mask
294 return SelectableInt(value
, bits
)
296 def __setitem__(self
, key
, value
):
297 if isinstance(key
, SelectableInt
):
299 if isinstance(key
, int):
300 assert key
< self
.bits
302 key
= self
.bits
- (key
+ 1)
303 if isinstance(value
, SelectableInt
):
304 assert value
.bits
== 1
309 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
310 elif isinstance(key
, slice):
311 assert key
.step
is None or key
.step
== 1
312 assert key
.start
< key
.stop
313 assert key
.start
>= 0
314 assert key
.stop
<= self
.bits
316 stop
= self
.bits
- key
.start
317 start
= self
.bits
- key
.stop
320 #print ("__setitem__ slice num bits", bits)
321 if isinstance(value
, SelectableInt
):
322 assert value
.bits
== bits
, "%d into %d" % (value
.bits
, bits
)
324 mask
= ((1 << bits
) - 1) << start
325 value
= value
<< start
326 self
.value
= (self
.value
& ~mask
) |
(value
& mask
)
328 def __ge__(self
, other
):
329 if isinstance(other
, FieldSelectableInt
):
330 other
= other
.get_range()
331 if isinstance(other
, SelectableInt
):
332 other
= check_extsign(self
, other
)
333 assert other
.bits
== self
.bits
334 other
= other
.to_signed_int()
335 if isinstance(other
, int):
336 return onebit(self
.to_signed_int() >= other
)
339 def __le__(self
, other
):
340 if isinstance(other
, FieldSelectableInt
):
341 other
= other
.get_range()
342 if isinstance(other
, SelectableInt
):
343 other
= check_extsign(self
, other
)
344 assert other
.bits
== self
.bits
345 other
= other
.to_signed_int()
346 if isinstance(other
, int):
347 return onebit(self
.to_signed_int() <= other
)
350 def __gt__(self
, other
):
351 if isinstance(other
, FieldSelectableInt
):
352 other
= other
.get_range()
353 if isinstance(other
, SelectableInt
):
354 other
= check_extsign(self
, other
)
355 assert other
.bits
== self
.bits
356 other
= other
.to_signed_int()
357 if isinstance(other
, int):
358 return onebit(self
.to_signed_int() > other
)
361 def __lt__(self
, other
):
362 print ("SelectableInt lt", self
, other
)
363 if isinstance(other
, FieldSelectableInt
):
364 other
= other
.get_range()
365 if isinstance(other
, SelectableInt
):
366 other
= check_extsign(self
, other
)
367 assert other
.bits
== self
.bits
368 other
= other
.to_signed_int()
369 if isinstance(other
, int):
370 a
= self
.to_signed_int()
371 res
= onebit(a
< other
)
372 print (" a < b", a
, other
, res
)
376 def __eq__(self
, other
):
377 print("__eq__", self
, other
)
378 if isinstance(other
, FieldSelectableInt
):
379 other
= other
.get_range()
380 if isinstance(other
, SelectableInt
):
381 other
= check_extsign(self
, other
)
382 assert other
.bits
== self
.bits
384 print (" eq", other
, self
.value
, other
== self
.value
)
385 if isinstance(other
, int):
386 return onebit(other
== self
.value
)
389 def narrow(self
, bits
):
390 assert bits
<= self
.bits
391 return SelectableInt(self
.value
, bits
)
394 return self
.value
!= 0
397 return "SelectableInt(value=0x{:x}, bits={})".format(self
.value
,
408 return SelectableInt(1 if bit
else 0, 1)
411 def selectltu(lhs
, rhs
):
412 """ less-than (unsigned)
414 if isinstance(rhs
, SelectableInt
):
416 return onebit(lhs
.value
< rhs
)
419 def selectgtu(lhs
, rhs
):
420 """ greater-than (unsigned)
422 if isinstance(rhs
, SelectableInt
):
424 return onebit(lhs
.value
> rhs
)
427 # XXX this probably isn't needed...
428 def selectassign(lhs
, idx
, rhs
):
429 if isinstance(idx
, tuple):
434 lower
, upper
, step
= idx
435 toidx
= range(lower
, upper
, step
)
436 fromidx
= range(0, upper
-lower
, step
) # XXX eurgh...
440 for t
, f
in zip(toidx
, fromidx
):
444 def selectconcat(*args
, repeat
=1):
445 if repeat
!= 1 and len(args
) == 1 and isinstance(args
[0], int):
446 args
= [SelectableInt(args
[0], 1)]
447 if repeat
!= 1: # multiplies the incoming arguments
449 for i
in range(repeat
):
454 if isinstance(i
, FieldSelectableInt
):
456 assert isinstance(i
, SelectableInt
), "can only concat SIs, sorry"
458 res
.value
= (res
.value
<< i
.bits
) | i
.value
459 print("concat", repeat
, res
)
463 class SelectableIntTestCase(unittest
.TestCase
):
464 def test_arith(self
):
465 a
= SelectableInt(5, 8)
466 b
= SelectableInt(9, 8)
473 self
.assertEqual(c
.value
, a
.value
+ b
.value
)
474 self
.assertEqual(d
.value
, (a
.value
- b
.value
) & 0xFF)
475 self
.assertEqual(e
.value
, (a
.value
* b
.value
) & 0xFF)
476 self
.assertEqual(f
.value
, (-a
.value
) & 0xFF)
477 self
.assertEqual(c
.bits
, a
.bits
)
478 self
.assertEqual(d
.bits
, a
.bits
)
479 self
.assertEqual(e
.bits
, a
.bits
)
480 self
.assertEqual(a
.bits
, f
.bits
)
481 self
.assertEqual(a
.bits
, h
.bits
)
483 def test_logic(self
):
484 a
= SelectableInt(0x0F, 8)
485 b
= SelectableInt(0xA5, 8)
490 self
.assertEqual(c
.value
, a
.value
& b
.value
)
491 self
.assertEqual(d
.value
, a
.value | b
.value
)
492 self
.assertEqual(e
.value
, a
.value ^ b
.value
)
493 self
.assertEqual(f
.value
, 0xF0)
496 a
= SelectableInt(0xa2, 8)
497 # These should be big endian
498 self
.assertEqual(a
[7], 0)
499 self
.assertEqual(a
[0:4], 10)
500 self
.assertEqual(a
[4:8], 2)
503 a
= SelectableInt(0x5, 8)
504 a
[7] = SelectableInt(0, 1)
505 self
.assertEqual(a
, 4)
507 self
.assertEqual(a
, 9)
509 self
.assertEqual(a
, 0x39)
511 self
.assertEqual(a
, 0x99)
513 def test_concat(self
):
514 a
= SelectableInt(0x1, 1)
515 c
= selectconcat(a
, repeat
=8)
516 self
.assertEqual(c
, 0xff)
517 self
.assertEqual(c
.bits
, 8)
518 a
= SelectableInt(0x0, 1)
519 c
= selectconcat(a
, repeat
=8)
520 self
.assertEqual(c
, 0x00)
521 self
.assertEqual(c
.bits
, 8)
524 for i
in range(65536):
525 a
= SelectableInt(i
, 16)
527 self
.assertEqual(a
, b
)
530 a
= SelectableInt(10, bits
=8)
531 b
= SelectableInt(5, bits
=8)
532 self
.assertTrue(a
> b
)
533 self
.assertFalse(a
< b
)
534 self
.assertTrue(a
!= b
)
535 self
.assertFalse(a
== b
)
537 def test_unsigned(self
):
538 a
= SelectableInt(0x80, bits
=8)
539 b
= SelectableInt(0x7f, bits
=8)
540 self
.assertTrue(a
> b
)
541 self
.assertFalse(a
< b
)
542 self
.assertTrue(a
!= b
)
543 self
.assertFalse(a
== b
)
546 if __name__
== "__main__":