add SVSHAPE class, starting to add to ISACaller
[openpower-isa.git] / src / openpower / decoder / selectable_int.py
1 import unittest
2 import struct
3 from copy import copy
4 from openpower.decoder.power_fields import BitRange
5 from operator import (add, sub, mul, floordiv, truediv, mod, or_, and_, xor,
6 neg, inv, lshift, rshift)
7 from openpower.util import log
8
9
10 def check_extsign(a, b):
11 if isinstance(b, FieldSelectableInt):
12 b = b.get_range()
13 if isinstance(b, int):
14 return SelectableInt(b, a.bits)
15 if b.bits != 256:
16 return b
17 return SelectableInt(b.value, a.bits)
18
19
20 class FieldSelectableInt:
21 """FieldSelectableInt: allows bit-range selection onto another target
22 """
23
24 def __init__(self, si, br):
25 self.si = si # target selectable int
26 if isinstance(br, list) or isinstance(br, tuple):
27 _br = BitRange()
28 for i, v in enumerate(br):
29 _br[i] = v
30 br = _br
31 self.br = br # map of indices.
32
33 def eq(self, b):
34 if isinstance(b, int):
35 # convert integer to same SelectableInt of same bitlength as range
36 blen = len(self.br)
37 b = SelectableInt(b, blen)
38 for i in range(b.bits):
39 self[i] = b[i]
40 elif isinstance(b, SelectableInt):
41 for i in range(b.bits):
42 self[i] = b[i]
43 else:
44 self.si = copy(b.si)
45 self.br = copy(b.br)
46
47 def _op(self, op, b):
48 vi = self.get_range()
49 vi = op(vi, b)
50 return self.merge(vi)
51
52 def _op1(self, op):
53 vi = self.get_range()
54 vi = op(vi)
55 return self.merge(vi)
56
57 def __getitem__(self, key):
58 log("getitem", key, self.br)
59 if isinstance(key, SelectableInt):
60 key = key.value
61 if isinstance(key, int):
62 key = self.br[key] # don't do POWER 1.3.4 bit-inversion
63 return self.si[key]
64 if isinstance(key, slice):
65 key = self.br[key]
66 return selectconcat(*[self.si[x] for x in key])
67
68 def __setitem__(self, key, value):
69 if isinstance(key, SelectableInt):
70 key = key.value
71 key = self.br[key] # don't do POWER 1.3.4 bit-inversion
72 if isinstance(key, int):
73 return self.si.__setitem__(key, value)
74 else:
75 if not isinstance(value, SelectableInt):
76 value = SelectableInt(value, bits=len(key))
77 for i, k in enumerate(key):
78 self.si[k] = value[i]
79
80 def __negate__(self):
81 return self._op1(negate)
82
83 def __invert__(self):
84 return self._op1(inv)
85
86 def __add__(self, b):
87 return self._op(add, b)
88
89 def __sub__(self, b):
90 return self._op(sub, b)
91
92 def __mul__(self, b):
93 return self._op(mul, b)
94
95 def __div__(self, b):
96 return self._op(truediv, b)
97
98 def __mod__(self, b):
99 return self._op(mod, b)
100
101 def __and__(self, b):
102 return self._op(and_, b)
103
104 def __or__(self, b):
105 return self._op(or_, b)
106
107 def __xor__(self, b):
108 return self._op(xor, b)
109
110 def get_range(self):
111 vi = SelectableInt(0, len(self.br))
112 for k, v in self.br.items():
113 vi[k] = self.si[v]
114 return vi
115
116 def merge(self, vi):
117 fi = copy(self)
118 for i, v in fi.br.items():
119 fi.si[v] = vi[i]
120 return fi
121
122 def __repr__(self):
123 return "FieldSelectableInt(si=%s, br=%s)" % (self.si, self.br)
124
125 def asint(self, msb0=False):
126 res = 0
127 brlen = len(self.br)
128 for i, key in self.br.items():
129 bit = self.si[key].value
130 #log("asint", i, key, bit)
131 res |= bit << ((brlen-i-1) if msb0 else i)
132 return res
133
134
135 class FieldSelectableIntTestCase(unittest.TestCase):
136 def test_arith(self):
137 a = SelectableInt(0b10101, 5)
138 b = SelectableInt(0b011, 3)
139 br = BitRange()
140 br[0] = 0
141 br[1] = 2
142 br[2] = 3
143 fs = FieldSelectableInt(a, br)
144 c = fs + b
145 log(c)
146 #self.assertEqual(c.value, a.value + b.value)
147
148 def test_select(self):
149 a = SelectableInt(0b00001111, 8)
150 br = BitRange()
151 br[0] = 0
152 br[1] = 1
153 br[2] = 4
154 br[3] = 5
155 fs = FieldSelectableInt(a, br)
156
157 self.assertEqual(fs.get_range(), 0b0011)
158
159 def test_select_range(self):
160 a = SelectableInt(0b00001111, 8)
161 br = BitRange()
162 br[0] = 0
163 br[1] = 1
164 br[2] = 4
165 br[3] = 5
166 fs = FieldSelectableInt(a, br)
167
168 self.assertEqual(fs[2:4], 0b11)
169
170 fs[0:2] = 0b10
171 self.assertEqual(fs.get_range(), 0b1011)
172
173 class SelectableInt:
174 """SelectableInt - a class that behaves exactly like python int
175
176 this class is designed to mirror precisely the behaviour of python int.
177 the only difference is that it must contain the context of the bitwidth
178 (number of bits) associated with that integer.
179
180 FieldSelectableInt can then operate on partial bits, and because there
181 is a bit width associated with SelectableInt, slices operate correctly
182 including negative start/end points.
183 """
184
185 def __init__(self, value, bits):
186 if isinstance(value, SelectableInt):
187 value = value.value
188 mask = (1 << bits) - 1
189 self.value = value & mask
190 self.bits = bits
191 self.overflow = (value & ~mask) != 0
192
193 def eq(self, b):
194 self.value = b.value
195 self.bits = b.bits
196
197 def to_signed_int(self):
198 log ("to signed?", self.value & (1<<(self.bits-1)), self.value)
199 if self.value & (1<<(self.bits-1)) != 0: # negative
200 res = self.value - (1<<self.bits)
201 log (" val -ve:", self.bits, res)
202 else:
203 res = self.value
204 log (" val +ve:", res)
205 return res
206
207 def _op(self, op, b):
208 if isinstance(b, int):
209 b = SelectableInt(b, self.bits)
210 b = check_extsign(self, b)
211 assert b.bits == self.bits
212 return SelectableInt(op(self.value, b.value), self.bits)
213
214 def __add__(self, b):
215 return self._op(add, b)
216
217 def __sub__(self, b):
218 return self._op(sub, b)
219
220 def __mul__(self, b):
221 # different case: mul result needs to fit the total bitsize
222 if isinstance(b, int):
223 b = SelectableInt(b, self.bits)
224 log("SelectableInt mul", hex(self.value), hex(b.value),
225 self.bits, b.bits)
226 return SelectableInt(self.value * b.value, self.bits + b.bits)
227
228 def __floordiv__(self, b):
229 return self._op(floordiv, b)
230
231 def __truediv__(self, b):
232 return self._op(truediv, b)
233
234 def __mod__(self, b):
235 return self._op(mod, b)
236
237 def __and__(self, b):
238 return self._op(and_, b)
239
240 def __or__(self, b):
241 return self._op(or_, b)
242
243 def __xor__(self, b):
244 return self._op(xor, b)
245
246 def __abs__(self):
247 log("abs", self.value & (1 << (self.bits-1)))
248 if self.value & (1 << (self.bits-1)) != 0:
249 return -self
250 return self
251
252 def __rsub__(self, b):
253 if isinstance(b, int):
254 b = SelectableInt(b, self.bits)
255 b = check_extsign(self, b)
256 assert b.bits == self.bits
257 return SelectableInt(b.value - self.value, self.bits)
258
259 def __radd__(self, b):
260 if isinstance(b, int):
261 b = SelectableInt(b, self.bits)
262 b = check_extsign(self, b)
263 assert b.bits == self.bits
264 return SelectableInt(b.value + self.value, self.bits)
265
266 def __rxor__(self, b):
267 b = check_extsign(self, b)
268 assert b.bits == self.bits
269 return SelectableInt(self.value ^ b.value, self.bits)
270
271 def __invert__(self):
272 return SelectableInt(~self.value, self.bits)
273
274 def __neg__(self):
275 res = SelectableInt((~self.value) + 1, self.bits)
276 log ("neg", hex(self.value), hex(res.value))
277 return res
278
279 def __lshift__(self, b):
280 b = check_extsign(self, b)
281 return SelectableInt(self.value << b.value, self.bits)
282
283 def __rshift__(self, b):
284 b = check_extsign(self, b)
285 return SelectableInt(self.value >> b.value, self.bits)
286
287 def __getitem__(self, key):
288 if isinstance(key, SelectableInt):
289 key = key.value
290 if isinstance(key, int):
291 assert key < self.bits, "key %d accessing %d" % (key, self.bits)
292 assert key >= 0
293 # NOTE: POWER 3.0B annotation order! see p4 1.3.2
294 # MSB is indexed **LOWEST** (sigh)
295 key = self.bits - (key + 1)
296
297 value = (self.value >> key) & 1
298 log("getitem", key, self.bits, hex(self.value), value)
299 return SelectableInt(value, 1)
300 elif isinstance(key, slice):
301 assert key.step is None or key.step == 1
302 assert key.start < key.stop
303 assert key.start >= 0
304 assert key.stop <= self.bits
305
306 stop = self.bits - key.start
307 start = self.bits - key.stop
308
309 bits = stop - start
310 #log ("__getitem__ slice num bits", start, stop, bits)
311 mask = (1 << bits) - 1
312 value = (self.value >> start) & mask
313 log("getitem", stop, start, self.bits, hex(self.value), value)
314 return SelectableInt(value, bits)
315
316 def __setitem__(self, key, value):
317 if isinstance(key, SelectableInt):
318 key = key.value
319 if isinstance(key, int):
320 if isinstance(value, SelectableInt):
321 assert value.bits == 1
322 value = value.value
323 log("setitem", key, self.bits, hex(self.value), hex(value))
324
325 assert key < self.bits
326 assert key >= 0
327 key = self.bits - (key + 1)
328
329 value = value << key
330 mask = 1 << key
331 self.value = (self.value & ~mask) | (value & mask)
332 elif isinstance(key, slice):
333 assert key.step is None or key.step == 1
334 assert key.start < key.stop
335 assert key.start >= 0
336 assert key.stop <= self.bits, \
337 "key stop %d bits %d" % (key.stop, self.bits)
338
339 stop = self.bits - key.start
340 start = self.bits - key.stop
341
342 bits = stop - start
343 #log ("__setitem__ slice num bits", bits)
344 if isinstance(value, SelectableInt):
345 assert value.bits == bits, "%d into %d" % (value.bits, bits)
346 value = value.value
347 log("setitem", key, self.bits, hex(self.value), hex(value))
348 mask = ((1 << bits) - 1) << start
349 value = value << start
350 self.value = (self.value & ~mask) | (value & mask)
351
352 def __ge__(self, other):
353 if isinstance(other, FieldSelectableInt):
354 other = other.get_range()
355 if isinstance(other, SelectableInt):
356 other = check_extsign(self, other)
357 assert other.bits == self.bits
358 other = other.to_signed_int()
359 if isinstance(other, int):
360 return onebit(self.to_signed_int() >= other)
361 assert False
362
363 def __le__(self, other):
364 if isinstance(other, FieldSelectableInt):
365 other = other.get_range()
366 if isinstance(other, SelectableInt):
367 other = check_extsign(self, other)
368 assert other.bits == self.bits
369 other = other.to_signed_int()
370 if isinstance(other, int):
371 return onebit(self.to_signed_int() <= other)
372 assert False
373
374 def __gt__(self, other):
375 if isinstance(other, FieldSelectableInt):
376 other = other.get_range()
377 if isinstance(other, SelectableInt):
378 other = check_extsign(self, other)
379 assert other.bits == self.bits
380 other = other.to_signed_int()
381 if isinstance(other, int):
382 return onebit(self.to_signed_int() > other)
383 assert False
384
385 def __lt__(self, other):
386 log ("SelectableInt lt", self, other)
387 if isinstance(other, FieldSelectableInt):
388 other = other.get_range()
389 if isinstance(other, SelectableInt):
390 other = check_extsign(self, other)
391 assert other.bits == self.bits
392 other = other.to_signed_int()
393 if isinstance(other, int):
394 a = self.to_signed_int()
395 res = onebit(a < other)
396 log (" a < b", a, other, res)
397 return res
398 assert False
399
400 def __eq__(self, other):
401 log("__eq__", self, other)
402 if isinstance(other, FieldSelectableInt):
403 other = other.get_range()
404 if isinstance(other, SelectableInt):
405 other = check_extsign(self, other)
406 assert other.bits == self.bits
407 other = other.value
408 log (" eq", other, self.value, other == self.value)
409 if isinstance(other, int):
410 return onebit(other == self.value)
411 assert False
412
413 def narrow(self, bits):
414 assert bits <= self.bits
415 return SelectableInt(self.value, bits)
416
417 def __bool__(self):
418 return self.value != 0
419
420 def __repr__(self):
421 return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
422 self.bits)
423
424 def __len__(self):
425 return self.bits
426
427 def asint(self):
428 return self.value
429
430 def __float__(self):
431 """convert to double-precision float. TODO, properly convert
432 rather than a hack-job: must actually support Power IEEE754 FP
433 """
434 assert self.bits == 64 # must be 64-bit
435 data = self.value.to_bytes(8, byteorder='little')
436 return struct.unpack('<d', data)[0]
437
438
439 def onebit(bit):
440 return SelectableInt(1 if bit else 0, 1)
441
442
443 def selectltu(lhs, rhs):
444 """ less-than (unsigned)
445 """
446 if isinstance(rhs, SelectableInt):
447 rhs = rhs.value
448 return onebit(lhs.value < rhs)
449
450
451 def selectgtu(lhs, rhs):
452 """ greater-than (unsigned)
453 """
454 if isinstance(rhs, SelectableInt):
455 rhs = rhs.value
456 return onebit(lhs.value > rhs)
457
458
459 # XXX this probably isn't needed...
460 def selectassign(lhs, idx, rhs):
461 if isinstance(idx, tuple):
462 if len(idx) == 2:
463 lower, upper = idx
464 step = None
465 else:
466 lower, upper, step = idx
467 toidx = range(lower, upper, step)
468 fromidx = range(0, upper-lower, step) # XXX eurgh...
469 else:
470 toidx = [idx]
471 fromidx = [0]
472 for t, f in zip(toidx, fromidx):
473 lhs[t] = rhs[f]
474
475
476 def selectconcat(*args, repeat=1):
477 if repeat != 1 and len(args) == 1 and isinstance(args[0], int):
478 args = [SelectableInt(args[0], 1)]
479 if repeat != 1: # multiplies the incoming arguments
480 tmp = []
481 for i in range(repeat):
482 tmp += args
483 args = tmp
484 res = copy(args[0])
485 for i in args[1:]:
486 if isinstance(i, FieldSelectableInt):
487 i = i.si
488 assert isinstance(i, SelectableInt), "can only concat SIs, sorry"
489 res.bits += i.bits
490 res.value = (res.value << i.bits) | i.value
491 log("concat", repeat, res)
492 return res
493
494
495 class SelectableIntTestCase(unittest.TestCase):
496 def test_arith(self):
497 a = SelectableInt(5, 8)
498 b = SelectableInt(9, 8)
499 c = a + b
500 d = a - b
501 e = a * b
502 f = -a
503 g = abs(f)
504 h = abs(a)
505 self.assertEqual(c.value, a.value + b.value)
506 self.assertEqual(d.value, (a.value - b.value) & 0xFF)
507 self.assertEqual(e.value, (a.value * b.value) & 0xFF)
508 self.assertEqual(f.value, (-a.value) & 0xFF)
509 self.assertEqual(c.bits, a.bits)
510 self.assertEqual(d.bits, a.bits)
511 self.assertEqual(e.bits, a.bits)
512 self.assertEqual(a.bits, f.bits)
513 self.assertEqual(a.bits, h.bits)
514
515 def test_logic(self):
516 a = SelectableInt(0x0F, 8)
517 b = SelectableInt(0xA5, 8)
518 c = a & b
519 d = a | b
520 e = a ^ b
521 f = ~a
522 self.assertEqual(c.value, a.value & b.value)
523 self.assertEqual(d.value, a.value | b.value)
524 self.assertEqual(e.value, a.value ^ b.value)
525 self.assertEqual(f.value, 0xF0)
526
527 def test_get(self):
528 a = SelectableInt(0xa2, 8)
529 # These should be big endian
530 self.assertEqual(a[7], 0)
531 self.assertEqual(a[0:4], 10)
532 self.assertEqual(a[4:8], 2)
533
534 def test_set(self):
535 a = SelectableInt(0x5, 8)
536 a[7] = SelectableInt(0, 1)
537 self.assertEqual(a, 4)
538 a[4:8] = 9
539 self.assertEqual(a, 9)
540 a[0:4] = 3
541 self.assertEqual(a, 0x39)
542 a[0:4] = a[4:8]
543 self.assertEqual(a, 0x99)
544
545 def test_concat(self):
546 a = SelectableInt(0x1, 1)
547 c = selectconcat(a, repeat=8)
548 self.assertEqual(c, 0xff)
549 self.assertEqual(c.bits, 8)
550 a = SelectableInt(0x0, 1)
551 c = selectconcat(a, repeat=8)
552 self.assertEqual(c, 0x00)
553 self.assertEqual(c.bits, 8)
554
555 def test_repr(self):
556 for i in range(65536):
557 a = SelectableInt(i, 16)
558 b = eval(repr(a))
559 self.assertEqual(a, b)
560
561 def test_cmp(self):
562 a = SelectableInt(10, bits=8)
563 b = SelectableInt(5, bits=8)
564 self.assertTrue(a > b)
565 self.assertFalse(a < b)
566 self.assertTrue(a != b)
567 self.assertFalse(a == b)
568
569 def test_unsigned(self):
570 a = SelectableInt(0x80, bits=8)
571 b = SelectableInt(0x7f, bits=8)
572 self.assertTrue(a > b)
573 self.assertFalse(a < b)
574 self.assertTrue(a != b)
575 self.assertFalse(a == b)
576
577 def test_maxint(self):
578 a = SelectableInt(0xffffffffffffffff, bits=64)
579 b = SelectableInt(0, bits=64)
580 result = a + b
581 self.assertTrue(result.value == 0xffffffffffffffff)
582
583 def test_double_1(self):
584 """use http://weitz.de/ieee/,
585 """
586 for asint, asfloat in [(0x4000000000000000, 2.0),
587 (0x4056C00000000000, 91.0),
588 (0xff80000000000000, -1.4044477616111843e+306),
589 ]:
590 a = SelectableInt(asint, bits=64)
591 convert = float(a)
592 log ("test_double_1", asint, asfloat, convert)
593 self.assertTrue(asfloat == convert)
594
595
596 if __name__ == "__main__":
597 unittest.main()