import unittest
import struct
from copy import copy
-from openpower.decoder.power_fields import BitRange
+import functools
+from collections import OrderedDict
from operator import (add, sub, mul, floordiv, truediv, mod, or_, and_, xor,
- neg, inv, lshift, rshift)
+ neg, inv, lshift, rshift, lt, eq)
+from openpower.util import log
def check_extsign(a, b):
return SelectableInt(b.value, a.bits)
+class BitRange(OrderedDict):
+ """BitRange: remaps from straight indices (0,1,2..) to bit numbers
+ """
+
+ def __getitem__(self, subscript):
+ if isinstance(subscript, slice):
+ return list(self.values())[subscript]
+ else:
+ return OrderedDict.__getitem__(self, subscript)
+
+
+@functools.total_ordering
class FieldSelectableInt:
"""FieldSelectableInt: allows bit-range selection onto another target
"""
def __init__(self, si, br):
- self.si = si # target selectable int
- if isinstance(br, list) or isinstance(br, tuple):
+ if not isinstance(si, (FieldSelectableInt, SelectableInt)):
+ raise ValueError(si)
+
+ if isinstance(br, (list, tuple, range)):
_br = BitRange()
for i, v in enumerate(br):
_br[i] = v
br = _br
- self.br = br # map of indices.
+
+ if isinstance(si, FieldSelectableInt):
+ fsi = si
+ if len(br) > len(fsi.br):
+ raise OverflowError(br)
+ _br = BitRange()
+ for (i, v) in br.items():
+ _br[i] = fsi.br[v]
+ br = _br
+ si = fsi.si
+
+ self.si = si # target selectable int
+ self.br = br # map of indices
def eq(self, b):
- if isinstance(b, SelectableInt):
+ if isinstance(b, int):
+ # convert integer to same SelectableInt of same bitlength as range
+ blen = len(self.br)
+ b = SelectableInt(b, blen)
+ for i in range(b.bits):
+ self[i] = b[i]
+ elif isinstance(b, SelectableInt):
for i in range(b.bits):
self[i] = b[i]
else:
vi = op(vi)
return self.merge(vi)
+ def __len__(self):
+ return len(self.br)
+
def __getitem__(self, key):
- print("getitem", key, self.br)
+ log("getitem", key, self.br)
if isinstance(key, SelectableInt):
key = key.value
+
if isinstance(key, int):
key = self.br[key] # don't do POWER 1.3.4 bit-inversion
return self.si[key]
- if isinstance(key, slice):
+ elif isinstance(key, slice):
key = self.br[key]
return selectconcat(*[self.si[x] for x in key])
+ elif isinstance(key, (tuple, list, range)):
+ return FieldSelectableInt(si=self, br=key)
+ else:
+ raise ValueError(key)
def __setitem__(self, key, value):
if isinstance(key, SelectableInt):
self.si[k] = value[i]
def __negate__(self):
- return self._op1(negate)
+ return self._op1(neg)
def __invert__(self):
return self._op1(inv)
def __xor__(self, b):
return self._op(xor, b)
+ def __lt__(self, b):
+ vi = self.get_range()
+ return onebit(lt(vi, b))
+
+ def __eq__(self, b):
+ vi = self.get_range()
+ return onebit(eq(vi, b))
+
def get_range(self):
vi = SelectableInt(0, len(self.br))
for k, v in self.br.items():
return fi
def __repr__(self):
- return "FieldSelectableInt(si=%s, br=%s)" % (self.si, self.br)
+ return f"{self.__class__.__name__}(si={self.si}, br={self.br})"
+
+ def __bool__(self):
+ for key in self.br.values():
+ bit = self.si[key].value
+ if bit:
+ return True
+ return False
+
+ def __int__(self):
+ return self.asint(msb0=True)
def asint(self, msb0=False):
res = 0
brlen = len(self.br)
for i, key in self.br.items():
+ log("asint", i, key, self.si[key])
bit = self.si[key].value
- #print("asint", i, key, bit)
+ #log("asint", i, key, bit)
res |= bit << ((brlen-i-1) if msb0 else i)
return res
br[2] = 3
fs = FieldSelectableInt(a, br)
c = fs + b
- print(c)
+ log(c)
#self.assertEqual(c.value, a.value + b.value)
def test_select(self):
fs[0:2] = 0b10
self.assertEqual(fs.get_range(), 0b1011)
+
class SelectableInt:
"""SelectableInt - a class that behaves exactly like python int
including negative start/end points.
"""
- def __init__(self, value, bits):
+ def __init__(self, value, bits=None):
if isinstance(value, SelectableInt):
+ if bits is not None:
+ # check if the bitlength is different. TODO, allow override?
+ if bits != value.bits:
+ raise ValueError(value)
+ bits = value.bits
value = value.value
+ elif isinstance(value, FieldSelectableInt):
+ if bits is not None:
+ raise ValueError(value)
+ bits = len(value.br)
+ value = value.si.value
+ else:
+ if not isinstance(value, int):
+ raise ValueError(value)
+ if bits is None:
+ raise ValueError(bits)
mask = (1 << bits) - 1
self.value = value & mask
self.bits = bits
self.bits = b.bits
def to_signed_int(self):
- print ("to signed?", self.value & (1<<(self.bits-1)), self.value)
+ log ("to signed?", self.value & (1<<(self.bits-1)), self.value)
if self.value & (1<<(self.bits-1)) != 0: # negative
res = self.value - (1<<self.bits)
- print (" val -ve:", self.bits, res)
+ log (" val -ve:", self.bits, res)
else:
res = self.value
- print (" val +ve:", res)
+ log (" val +ve:", res)
return res
def _op(self, op, b):
# different case: mul result needs to fit the total bitsize
if isinstance(b, int):
b = SelectableInt(b, self.bits)
- print("SelectableInt mul", hex(self.value), hex(b.value),
+ log("SelectableInt mul", hex(self.value), hex(b.value),
self.bits, b.bits)
return SelectableInt(self.value * b.value, self.bits + b.bits)
return self._op(xor, b)
def __abs__(self):
- print("abs", self.value & (1 << (self.bits-1)))
+ log("abs", self.value & (1 << (self.bits-1)))
if self.value & (1 << (self.bits-1)) != 0:
return -self
return self
def __rsub__(self, b):
+ log("rsub", b, self.value)
if isinstance(b, int):
- b = SelectableInt(b, self.bits)
- b = check_extsign(self, b)
- assert b.bits == self.bits
- return SelectableInt(b.value - self.value, self.bits)
+ b = SelectableInt(b, 256) # max extent
+ #b = check_extsign(self, b)
+ #assert b.bits == self.bits
+ return SelectableInt(b.value - self.value, b.bits)
def __radd__(self, b):
if isinstance(b, int):
def __neg__(self):
res = SelectableInt((~self.value) + 1, self.bits)
- print ("neg", hex(self.value), hex(res.value))
+ log ("neg", hex(self.value), hex(res.value))
return res
def __lshift__(self, b):
return SelectableInt(self.value >> b.value, self.bits)
def __getitem__(self, key):
+ log ("SelectableInt.__getitem__", self, key, type(key))
if isinstance(key, SelectableInt):
key = key.value
if isinstance(key, int):
key = self.bits - (key + 1)
value = (self.value >> key) & 1
- print("getitem", key, self.bits, hex(self.value), value)
+ log("getitem", key, self.bits, hex(self.value), value)
return SelectableInt(value, 1)
elif isinstance(key, slice):
assert key.step is None or key.step == 1
start = self.bits - key.stop
bits = stop - start
- #print ("__getitem__ slice num bits", start, stop, bits)
+ log ("__getitem__ slice num bits", start, stop, bits)
mask = (1 << bits) - 1
value = (self.value >> start) & mask
- print("getitem", stop, start, self.bits, hex(self.value), value)
+ log("getitem", stop, start, self.bits, hex(self.value), value)
return SelectableInt(value, bits)
+ else:
+ bits = []
+ key = tuple(key)
+ for bit in key:
+ if not isinstance(bit, (int, SelectableInt)):
+ raise ValueError(key)
+ bits.append(self[bit])
+ return selectconcat(*bits)
def __setitem__(self, key, value):
if isinstance(key, SelectableInt):
key = key.value
- print("setitem", key, self.bits, hex(self.value))
if isinstance(key, int):
- assert key < self.bits
- assert key >= 0
- key = self.bits - (key + 1)
if isinstance(value, SelectableInt):
assert value.bits == 1
value = value.value
+ log("setitem", key, self.bits, hex(self.value), hex(value))
+
+ assert key < self.bits
+ assert key >= 0
+ key = self.bits - (key + 1)
value = value << key
mask = 1 << key
self.value = (self.value & ~mask) | (value & mask)
elif isinstance(key, slice):
- assert key.step is None or key.step == 1
- assert key.start < key.stop
- assert key.start >= 0
- assert key.stop <= self.bits
-
- stop = self.bits - key.start
- start = self.bits - key.stop
+ kstart, kstop, kstep = key.start, key.stop, key.step
+ if isinstance(kstart, SelectableInt): kstart = kstart.asint()
+ if isinstance(kstop, SelectableInt): kstop = kstop.asint()
+ if isinstance(kstep, SelectableInt): kstep = kstep.asint()
+ log ("__setitem__ slice ", kstart, kstop, kstep)
+ assert kstep is None or kstep == 1
+ assert kstart < kstop
+ assert kstart >= 0
+ assert kstop <= self.bits, \
+ "key stop %d bits %d" % (kstop, self.bits)
+
+ stop = self.bits - kstart
+ start = self.bits - kstop
bits = stop - start
- #print ("__setitem__ slice num bits", bits)
+ #log ("__setitem__ slice num bits", bits)
if isinstance(value, SelectableInt):
assert value.bits == bits, "%d into %d" % (value.bits, bits)
value = value.value
+ log("setitem", key, self.bits, hex(self.value), hex(value))
mask = ((1 << bits) - 1) << start
value = value << start
self.value = (self.value & ~mask) | (value & mask)
+ else:
+ raise ValueError(key)
def __ge__(self, other):
if isinstance(other, FieldSelectableInt):
assert False
def __lt__(self, other):
- print ("SelectableInt lt", self, other)
+ log ("SelectableInt lt", self, other)
if isinstance(other, FieldSelectableInt):
other = other.get_range()
if isinstance(other, SelectableInt):
if isinstance(other, int):
a = self.to_signed_int()
res = onebit(a < other)
- print (" a < b", a, other, res)
+ log (" a < b", a, other, res)
return res
assert False
def __eq__(self, other):
- print("__eq__", self, other)
+ log("__eq__", self, other)
if isinstance(other, FieldSelectableInt):
other = other.get_range()
if isinstance(other, SelectableInt):
other = check_extsign(self, other)
assert other.bits == self.bits
other = other.value
- print (" eq", other, self.value, other == self.value)
+ log (" eq", other, self.value, other == self.value)
if isinstance(other, int):
return onebit(other == self.value)
assert False
return self.value != 0
def __repr__(self):
- return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
- self.bits)
+ value = f"value={hex(self.value)}, bits={self.bits}"
+ return f"{self.__class__.__name__}({value})"
def __len__(self):
return self.bits
def asint(self):
return self.value
+ def __int__(self):
+ return self.asint()
+
def __float__(self):
"""convert to double-precision float. TODO, properly convert
rather than a hack-job: must actually support Power IEEE754 FP
assert isinstance(i, SelectableInt), "can only concat SIs, sorry"
res.bits += i.bits
res.value = (res.value << i.bits) | i.value
- print("concat", repeat, res)
+ log("concat", repeat, res)
return res
]:
a = SelectableInt(asint, bits=64)
convert = float(a)
- print ("test_double_1", asint, asfloat, convert)
+ log ("test_double_1", asint, asfloat, convert)
self.assertTrue(asfloat == convert)