investigating div fsm and simulator bug
[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
118 class FieldSelectableIntTestCase(unittest.TestCase):
119 def test_arith(self):
120 a = SelectableInt(0b10101, 5)
121 b = SelectableInt(0b011, 3)
122 br = BitRange()
123 br[0] = 0
124 br[1] = 2
125 br[2] = 3
126 fs = FieldSelectableInt(a, br)
127 c = fs + b
128 print(c)
129 #self.assertEqual(c.value, a.value + b.value)
130
131 def test_select(self):
132 a = SelectableInt(0b00001111, 8)
133 br = BitRange()
134 br[0] = 0
135 br[1] = 1
136 br[2] = 4
137 br[3] = 5
138 fs = FieldSelectableInt(a, br)
139
140 self.assertEqual(fs.get_range(), 0b0011)
141
142 def test_select_range(self):
143 a = SelectableInt(0b00001111, 8)
144 br = BitRange()
145 br[0] = 0
146 br[1] = 1
147 br[2] = 4
148 br[3] = 5
149 fs = FieldSelectableInt(a, br)
150
151 self.assertEqual(fs[2:4], 0b11)
152
153 fs[0:2] = 0b10
154 self.assertEqual(fs.get_range(), 0b1011)
155
156 class SelectableInt:
157 """SelectableInt - a class that behaves exactly like python int
158
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.
162
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.
166 """
167
168 def __init__(self, value, bits):
169 if isinstance(value, SelectableInt):
170 value = value.value
171 mask = (1 << bits) - 1
172 self.value = value & mask
173 self.bits = bits
174
175 def eq(self, b):
176 self.value = b.value
177 self.bits = b.bits
178
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)
184 else:
185 res = self.value
186 print (" val +ve:", res)
187 return res
188
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)
195
196 def __add__(self, b):
197 return self._op(add, b)
198
199 def __sub__(self, b):
200 return self._op(sub, b)
201
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),
207 self.bits, b.bits)
208 return SelectableInt(self.value * b.value, self.bits + b.bits)
209
210 def __floordiv__(self, b):
211 return self._op(floordiv, b)
212
213 def __truediv__(self, b):
214 return self._op(truediv, b)
215
216 def __mod__(self, b):
217 return self._op(mod, b)
218
219 def __and__(self, b):
220 return self._op(and_, b)
221
222 def __or__(self, b):
223 return self._op(or_, b)
224
225 def __xor__(self, b):
226 return self._op(xor, b)
227
228 def __abs__(self):
229 print("abs", self.value & (1 << (self.bits-1)))
230 if self.value & (1 << (self.bits-1)) != 0:
231 return -self
232 return self
233
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)
240
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)
247
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)
252
253 def __invert__(self):
254 return SelectableInt(~self.value, self.bits)
255
256 def __neg__(self):
257 res = SelectableInt((~self.value) + 1, self.bits)
258 print ("neg", hex(self.value), hex(res.value))
259 return res
260
261 def __lshift__(self, b):
262 b = check_extsign(self, b)
263 return SelectableInt(self.value << b.value, self.bits)
264
265 def __rshift__(self, b):
266 b = check_extsign(self, b)
267 return SelectableInt(self.value >> b.value, self.bits)
268
269 def __getitem__(self, key):
270 if isinstance(key, SelectableInt):
271 key = key.value
272 if isinstance(key, int):
273 assert key < self.bits, "key %d accessing %d" % (key, self.bits)
274 assert key >= 0
275 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
276 # MSB is indexed **LOWEST** (sigh)
277 key = self.bits - (key + 1)
278
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
286
287 stop = self.bits - key.start
288 start = self.bits - key.stop
289
290 bits = stop - start
291 #print ("__getitem__ slice num bits", bits)
292 mask = (1 << bits) - 1
293 value = (self.value >> start) & mask
294 return SelectableInt(value, bits)
295
296 def __setitem__(self, key, value):
297 if isinstance(key, SelectableInt):
298 key = key.value
299 if isinstance(key, int):
300 assert key < self.bits
301 assert key >= 0
302 key = self.bits - (key + 1)
303 if isinstance(value, SelectableInt):
304 assert value.bits == 1
305 value = value.value
306
307 value = value << key
308 mask = 1 << key
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
315
316 stop = self.bits - key.start
317 start = self.bits - key.stop
318
319 bits = stop - start
320 #print ("__setitem__ slice num bits", bits)
321 if isinstance(value, SelectableInt):
322 assert value.bits == bits, "%d into %d" % (value.bits, bits)
323 value = value.value
324 mask = ((1 << bits) - 1) << start
325 value = value << start
326 self.value = (self.value & ~mask) | (value & mask)
327
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)
337 assert False
338
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)
348 assert False
349
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)
359 assert False
360
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)
373 return res
374 assert False
375
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
383 other = other.value
384 print (" eq", other, self.value, other == self.value)
385 if isinstance(other, int):
386 return onebit(other == self.value)
387 assert False
388
389 def narrow(self, bits):
390 assert bits <= self.bits
391 return SelectableInt(self.value, bits)
392
393 def __bool__(self):
394 return self.value != 0
395
396 def __repr__(self):
397 return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
398 self.bits)
399
400 def __len__(self):
401 return self.bits
402
403 def asint(self):
404 return self.value
405
406
407 def onebit(bit):
408 return SelectableInt(1 if bit else 0, 1)
409
410
411 def selectltu(lhs, rhs):
412 """ less-than (unsigned)
413 """
414 if isinstance(rhs, SelectableInt):
415 rhs = rhs.value
416 return onebit(lhs.value < rhs)
417
418
419 def selectgtu(lhs, rhs):
420 """ greater-than (unsigned)
421 """
422 if isinstance(rhs, SelectableInt):
423 rhs = rhs.value
424 return onebit(lhs.value > rhs)
425
426
427 # XXX this probably isn't needed...
428 def selectassign(lhs, idx, rhs):
429 if isinstance(idx, tuple):
430 if len(idx) == 2:
431 lower, upper = idx
432 step = None
433 else:
434 lower, upper, step = idx
435 toidx = range(lower, upper, step)
436 fromidx = range(0, upper-lower, step) # XXX eurgh...
437 else:
438 toidx = [idx]
439 fromidx = [0]
440 for t, f in zip(toidx, fromidx):
441 lhs[t] = rhs[f]
442
443
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
448 tmp = []
449 for i in range(repeat):
450 tmp += args
451 args = tmp
452 res = copy(args[0])
453 for i in args[1:]:
454 if isinstance(i, FieldSelectableInt):
455 i = i.si
456 assert isinstance(i, SelectableInt), "can only concat SIs, sorry"
457 res.bits += i.bits
458 res.value = (res.value << i.bits) | i.value
459 print("concat", repeat, res)
460 return res
461
462
463 class SelectableIntTestCase(unittest.TestCase):
464 def test_arith(self):
465 a = SelectableInt(5, 8)
466 b = SelectableInt(9, 8)
467 c = a + b
468 d = a - b
469 e = a * b
470 f = -a
471 g = abs(f)
472 h = abs(a)
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)
482
483 def test_logic(self):
484 a = SelectableInt(0x0F, 8)
485 b = SelectableInt(0xA5, 8)
486 c = a & b
487 d = a | b
488 e = a ^ b
489 f = ~a
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)
494
495 def test_get(self):
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)
501
502 def test_set(self):
503 a = SelectableInt(0x5, 8)
504 a[7] = SelectableInt(0, 1)
505 self.assertEqual(a, 4)
506 a[4:8] = 9
507 self.assertEqual(a, 9)
508 a[0:4] = 3
509 self.assertEqual(a, 0x39)
510 a[0:4] = a[4:8]
511 self.assertEqual(a, 0x99)
512
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)
522
523 def test_repr(self):
524 for i in range(65536):
525 a = SelectableInt(i, 16)
526 b = eval(repr(a))
527 self.assertEqual(a, b)
528
529 def test_cmp(self):
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)
536
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)
544
545
546 if __name__ == "__main__":
547 unittest.main()