test SVP64 major opcode, start checking if it is EXT001 soon
[soc.git] / src / soc / decoder / selectable_int.py
1 import unittest
2 from copy import copy
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)
6
7
8 def check_extsign(a, b):
9 if isinstance(b, FieldSelectableInt):
10 b = b.get_range()
11 if isinstance(b, int):
12 return SelectableInt(b, a.bits)
13 if b.bits != 256:
14 return b
15 return SelectableInt(b.value, a.bits)
16
17
18 class FieldSelectableInt:
19 """FieldSelectableInt: allows bit-range selection onto another target
20 """
21
22 def __init__(self, si, br):
23 self.si = si # target selectable int
24 if isinstance(br, list) or isinstance(br, tuple):
25 _br = BitRange()
26 for i, v in enumerate(br):
27 _br[i] = v
28 br = _br
29 self.br = br # map of indices.
30
31 def eq(self, b):
32 if isinstance(b, SelectableInt):
33 for i in range(b.bits):
34 self[i] = b[i]
35 else:
36 self.si = copy(b.si)
37 self.br = copy(b.br)
38
39 def _op(self, op, b):
40 vi = self.get_range()
41 vi = op(vi, b)
42 return self.merge(vi)
43
44 def _op1(self, op):
45 vi = self.get_range()
46 vi = op(vi)
47 return self.merge(vi)
48
49 def __getitem__(self, key):
50 print("getitem", key, self.br)
51 if isinstance(key, SelectableInt):
52 key = key.value
53 if isinstance(key, int):
54 key = self.br[key] # don't do POWER 1.3.4 bit-inversion
55 return self.si[key]
56 if isinstance(key, slice):
57 key = self.br[key]
58 return selectconcat(*[self.si[x] for x in key])
59
60 def __setitem__(self, key, value):
61 if isinstance(key, SelectableInt):
62 key = key.value
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)
66 else:
67 if not isinstance(value, SelectableInt):
68 value = SelectableInt(value, bits=len(key))
69 for i, k in enumerate(key):
70 self.si[k] = value[i]
71
72 def __negate__(self):
73 return self._op1(negate)
74
75 def __invert__(self):
76 return self._op1(inv)
77
78 def __add__(self, b):
79 return self._op(add, b)
80
81 def __sub__(self, b):
82 return self._op(sub, b)
83
84 def __mul__(self, b):
85 return self._op(mul, b)
86
87 def __div__(self, b):
88 return self._op(truediv, b)
89
90 def __mod__(self, b):
91 return self._op(mod, b)
92
93 def __and__(self, b):
94 return self._op(and_, b)
95
96 def __or__(self, b):
97 return self._op(or_, b)
98
99 def __xor__(self, b):
100 return self._op(xor, b)
101
102 def get_range(self):
103 vi = SelectableInt(0, len(self.br))
104 for k, v in self.br.items():
105 vi[k] = self.si[v]
106 return vi
107
108 def merge(self, vi):
109 fi = copy(self)
110 for i, v in fi.br.items():
111 fi.si[v] = vi[i]
112 return fi
113
114 def __repr__(self):
115 return "FieldSelectableInt(si=%s, br=%s)" % (self.si, self.br)
116
117 def asint(self, msb0=False):
118 res = 0
119 brlen = len(self.br)
120 for i, key in enumerate(self.br):
121 res |= self.si[key].value << ((brlen-i-1) if msb0 else i)
122 return res
123
124
125 class FieldSelectableIntTestCase(unittest.TestCase):
126 def test_arith(self):
127 a = SelectableInt(0b10101, 5)
128 b = SelectableInt(0b011, 3)
129 br = BitRange()
130 br[0] = 0
131 br[1] = 2
132 br[2] = 3
133 fs = FieldSelectableInt(a, br)
134 c = fs + b
135 print(c)
136 #self.assertEqual(c.value, a.value + b.value)
137
138 def test_select(self):
139 a = SelectableInt(0b00001111, 8)
140 br = BitRange()
141 br[0] = 0
142 br[1] = 1
143 br[2] = 4
144 br[3] = 5
145 fs = FieldSelectableInt(a, br)
146
147 self.assertEqual(fs.get_range(), 0b0011)
148
149 def test_select_range(self):
150 a = SelectableInt(0b00001111, 8)
151 br = BitRange()
152 br[0] = 0
153 br[1] = 1
154 br[2] = 4
155 br[3] = 5
156 fs = FieldSelectableInt(a, br)
157
158 self.assertEqual(fs[2:4], 0b11)
159
160 fs[0:2] = 0b10
161 self.assertEqual(fs.get_range(), 0b1011)
162
163 class SelectableInt:
164 """SelectableInt - a class that behaves exactly like python int
165
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.
169
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.
173 """
174
175 def __init__(self, value, bits):
176 if isinstance(value, SelectableInt):
177 value = value.value
178 mask = (1 << bits) - 1
179 self.value = value & mask
180 self.bits = bits
181 self.overflow = (value & ~mask) != 0
182
183 def eq(self, b):
184 self.value = b.value
185 self.bits = b.bits
186
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)
192 else:
193 res = self.value
194 print (" val +ve:", res)
195 return res
196
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)
203
204 def __add__(self, b):
205 return self._op(add, b)
206
207 def __sub__(self, b):
208 return self._op(sub, b)
209
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),
215 self.bits, b.bits)
216 return SelectableInt(self.value * b.value, self.bits + b.bits)
217
218 def __floordiv__(self, b):
219 return self._op(floordiv, b)
220
221 def __truediv__(self, b):
222 return self._op(truediv, b)
223
224 def __mod__(self, b):
225 return self._op(mod, b)
226
227 def __and__(self, b):
228 return self._op(and_, b)
229
230 def __or__(self, b):
231 return self._op(or_, b)
232
233 def __xor__(self, b):
234 return self._op(xor, b)
235
236 def __abs__(self):
237 print("abs", self.value & (1 << (self.bits-1)))
238 if self.value & (1 << (self.bits-1)) != 0:
239 return -self
240 return self
241
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)
248
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)
255
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)
260
261 def __invert__(self):
262 return SelectableInt(~self.value, self.bits)
263
264 def __neg__(self):
265 res = SelectableInt((~self.value) + 1, self.bits)
266 print ("neg", hex(self.value), hex(res.value))
267 return res
268
269 def __lshift__(self, b):
270 b = check_extsign(self, b)
271 return SelectableInt(self.value << b.value, self.bits)
272
273 def __rshift__(self, b):
274 b = check_extsign(self, b)
275 return SelectableInt(self.value >> b.value, self.bits)
276
277 def __getitem__(self, key):
278 if isinstance(key, SelectableInt):
279 key = key.value
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)
283 assert key >= 0
284 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
285 # MSB is indexed **LOWEST** (sigh)
286 key = self.bits - (key + 1)
287
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
295
296 stop = self.bits - key.start
297 start = self.bits - key.stop
298
299 bits = stop - start
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)
304
305 def __setitem__(self, key, value):
306 if isinstance(key, SelectableInt):
307 key = key.value
308 print("setitem", key, self.bits, hex(self.value))
309 if isinstance(key, int):
310 assert key < self.bits
311 assert key >= 0
312 key = self.bits - (key + 1)
313 if isinstance(value, SelectableInt):
314 assert value.bits == 1
315 value = value.value
316
317 value = value << key
318 mask = 1 << key
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
325
326 stop = self.bits - key.start
327 start = self.bits - key.stop
328
329 bits = stop - start
330 #print ("__setitem__ slice num bits", bits)
331 if isinstance(value, SelectableInt):
332 assert value.bits == bits, "%d into %d" % (value.bits, bits)
333 value = value.value
334 mask = ((1 << bits) - 1) << start
335 value = value << start
336 self.value = (self.value & ~mask) | (value & mask)
337
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)
347 assert False
348
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)
358 assert False
359
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)
369 assert False
370
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)
383 return res
384 assert False
385
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
393 other = other.value
394 print (" eq", other, self.value, other == self.value)
395 if isinstance(other, int):
396 return onebit(other == self.value)
397 assert False
398
399 def narrow(self, bits):
400 assert bits <= self.bits
401 return SelectableInt(self.value, bits)
402
403 def __bool__(self):
404 return self.value != 0
405
406 def __repr__(self):
407 return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
408 self.bits)
409
410 def __len__(self):
411 return self.bits
412
413 def asint(self):
414 return self.value
415
416
417 def onebit(bit):
418 return SelectableInt(1 if bit else 0, 1)
419
420
421 def selectltu(lhs, rhs):
422 """ less-than (unsigned)
423 """
424 if isinstance(rhs, SelectableInt):
425 rhs = rhs.value
426 return onebit(lhs.value < rhs)
427
428
429 def selectgtu(lhs, rhs):
430 """ greater-than (unsigned)
431 """
432 if isinstance(rhs, SelectableInt):
433 rhs = rhs.value
434 return onebit(lhs.value > rhs)
435
436
437 # XXX this probably isn't needed...
438 def selectassign(lhs, idx, rhs):
439 if isinstance(idx, tuple):
440 if len(idx) == 2:
441 lower, upper = idx
442 step = None
443 else:
444 lower, upper, step = idx
445 toidx = range(lower, upper, step)
446 fromidx = range(0, upper-lower, step) # XXX eurgh...
447 else:
448 toidx = [idx]
449 fromidx = [0]
450 for t, f in zip(toidx, fromidx):
451 lhs[t] = rhs[f]
452
453
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
458 tmp = []
459 for i in range(repeat):
460 tmp += args
461 args = tmp
462 res = copy(args[0])
463 for i in args[1:]:
464 if isinstance(i, FieldSelectableInt):
465 i = i.si
466 assert isinstance(i, SelectableInt), "can only concat SIs, sorry"
467 res.bits += i.bits
468 res.value = (res.value << i.bits) | i.value
469 print("concat", repeat, res)
470 return res
471
472
473 class SelectableIntTestCase(unittest.TestCase):
474 def test_arith(self):
475 a = SelectableInt(5, 8)
476 b = SelectableInt(9, 8)
477 c = a + b
478 d = a - b
479 e = a * b
480 f = -a
481 g = abs(f)
482 h = abs(a)
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)
492
493 def test_logic(self):
494 a = SelectableInt(0x0F, 8)
495 b = SelectableInt(0xA5, 8)
496 c = a & b
497 d = a | b
498 e = a ^ b
499 f = ~a
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)
504
505 def test_get(self):
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)
511
512 def test_set(self):
513 a = SelectableInt(0x5, 8)
514 a[7] = SelectableInt(0, 1)
515 self.assertEqual(a, 4)
516 a[4:8] = 9
517 self.assertEqual(a, 9)
518 a[0:4] = 3
519 self.assertEqual(a, 0x39)
520 a[0:4] = a[4:8]
521 self.assertEqual(a, 0x99)
522
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)
532
533 def test_repr(self):
534 for i in range(65536):
535 a = SelectableInt(i, 16)
536 b = eval(repr(a))
537 self.assertEqual(a, b)
538
539 def test_cmp(self):
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)
546
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)
554
555
556 if __name__ == "__main__":
557 unittest.main()