import unittest
from copy import copy
+from soc.decoder.power_fields import BitRange
+from operator import (add, sub, mul, truediv, mod, or_, and_, xor, neg, inv)
+
+
+def check_extsign(a, b):
+ if isinstance(b, FieldSelectableInt):
+ b = b.get_range()
+ if isinstance(b, int):
+ return SelectableInt(b, a.bits)
+ if b.bits != 256:
+ return b
+ return SelectableInt(b.value, a.bits)
+
+
+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):
+ _br = BitRange()
+ for i, v in enumerate(br):
+ _br[i] = v
+ br = _br
+ self.br = br # map of indices.
+
+ def eq(self, b):
+ if isinstance(b, SelectableInt):
+ for i in range(b.bits):
+ self[i] = b[i]
+ else:
+ self.si = copy(b.si)
+ self.br = copy(b.br)
+
+ def _op(self, op, b):
+ vi = self.get_range()
+ vi = op(vi, b)
+ return self.merge(vi)
+
+ def _op1(self, op):
+ vi = self.get_range()
+ vi = op(vi)
+ return self.merge(vi)
+
+ def __getitem__(self, key):
+ print ("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):
+ key = self.br[key]
+ return selectconcat(*[self.si[x] for x in key])
+
+ def __setitem__(self, key, value):
+ if isinstance(key, SelectableInt):
+ key = key.value
+ key = self.br[key] # don't do POWER 1.3.4 bit-inversion
+ if isinstance(key, int):
+ return self.si.__setitem__(key, value)
+ else:
+ if not isinstance(value, SelectableInt):
+ value = SelectableInt(value, bits=len(key))
+ for i, k in enumerate(key):
+ self.si[k] = value[i]
+
+ def __negate__(self):
+ return self._op1(negate)
+ def __invert__(self):
+ return self._op1(inv)
+ def __add__(self, b):
+ return self._op(add, b)
+ def __sub__(self, b):
+ return self._op(sub, b)
+ def __mul__(self, b):
+ return self._op(mul, b)
+ def __div__(self, b):
+ return self._op(truediv, b)
+ def __mod__(self, b):
+ return self._op(mod, b)
+ def __and__(self, b):
+ return self._op(and_, b)
+ def __or__(self, b):
+ return self._op(or_, b)
+ def __xor__(self, b):
+ return self._op(xor, b)
+
+ def get_range(self):
+ print ("get_range", self.si)
+ vi = SelectableInt(0, len(self.br))
+ for k, v in self.br.items():
+ print ("get_range", k, v, self.si[v])
+ vi[k] = self.si[v]
+ print ("get_range", vi)
+ return vi
+
+ def merge(self, vi):
+ fi = copy(self)
+ for i, v in fi.br.items():
+ fi.si[v] = vi[i]
+ return fi
+
+ def __repr__(self):
+ return "FieldSelectableInt(si=%s, br=%s)" % (self.si, self.br)
+
+
+class FieldSelectableIntTestCase(unittest.TestCase):
+ def test_arith(self):
+ a = SelectableInt(0b10101, 5)
+ b = SelectableInt(0b011, 3)
+ br = BitRange()
+ br[0] = 0
+ br[1] = 2
+ br[2] = 3
+ fs = FieldSelectableInt(a, br)
+ c = fs + b
+ print (c)
+ #self.assertEqual(c.value, a.value + b.value)
+
+ def test_select(self):
+ a = SelectableInt(0b00001111, 8)
+ br = BitRange()
+ br[0] = 0
+ br[1] = 1
+ br[2] = 4
+ br[3] = 5
+ fs = FieldSelectableInt(a, br)
+
+ self.assertEqual(fs.get_range(), 0b0011)
+
+ def test_select_range(self):
+ a = SelectableInt(0b00001111, 8)
+ br = BitRange()
+ br[0] = 0
+ br[1] = 1
+ br[2] = 4
+ br[3] = 5
+ fs = FieldSelectableInt(a, br)
+
+ self.assertEqual(fs[2:4], 0b11)
+
+ fs[0:2] = 0b10
+ self.assertEqual(fs.get_range(), 0b1011)
+
class SelectableInt:
def __init__(self, value, bits):
+ if isinstance(value, SelectableInt):
+ value = value.value
mask = (1 << bits) - 1
self.value = value & mask
self.bits = bits
+ def eq(self, b):
+ self.value = b.value
+ self.bits = b.bits
+
def __add__(self, b):
+ if isinstance(b, int):
+ b = SelectableInt(b, self.bits)
+ b = check_extsign(self, b)
assert b.bits == self.bits
return SelectableInt(self.value + b.value, self.bits)
def __sub__(self, b):
+ if isinstance(b, int):
+ b = SelectableInt(b, self.bits)
+ b = check_extsign(self, b)
assert b.bits == self.bits
return SelectableInt(self.value - b.value, self.bits)
+ def __rsub__(self, b):
+ 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)
+
+ def __radd__(self, b):
+ 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)
+
def __mul__(self, b):
+ b = check_extsign(self, b)
assert b.bits == self.bits
return SelectableInt(self.value * b.value, self.bits)
def __div__(self, b):
+ b = check_extsign(self, b)
assert b.bits == self.bits
return SelectableInt(self.value / b.value, self.bits)
def __mod__(self, b):
+ b = check_extsign(self, b)
assert b.bits == self.bits
return SelectableInt(self.value % b.value, self.bits)
def __or__(self, b):
+ b = check_extsign(self, b)
assert b.bits == self.bits
return SelectableInt(self.value | b.value, self.bits)
def __and__(self, b):
+ print ("__and__", self, b)
+ b = check_extsign(self, b)
assert b.bits == self.bits
return SelectableInt(self.value & b.value, self.bits)
def __xor__(self, b):
+ b = check_extsign(self, b)
+ assert b.bits == self.bits
+ return SelectableInt(self.value ^ b.value, self.bits)
+
+ def __rxor__(self, b):
+ b = check_extsign(self, b)
assert b.bits == self.bits
return SelectableInt(self.value ^ b.value, self.bits)
def __neg__(self):
return SelectableInt(~self.value + 1, self.bits)
+ def __lshift__(self, b):
+ b = check_extsign(self, b)
+ return SelectableInt(self.value << b.value, self.bits)
+
+ def __rshift__(self, b):
+ b = check_extsign(self, b)
+ return SelectableInt(self.value >> b.value, self.bits)
+
def __getitem__(self, key):
if isinstance(key, int):
assert key < self.bits, "key %d accessing %d" % (key, self.bits)
assert key >= 0
+ # NOTE: POWER 3.0B annotation order! see p4 1.3.2
+ # MSB is indexed **LOWEST** (sigh)
key = self.bits - (key + 1)
value = (self.value >> key) & 1
stop = self.bits - key.start
start = self.bits - key.stop
- bits = stop - start + 1
+ bits = stop - start
+ #print ("__getitem__ slice num bits", bits)
mask = (1 << bits) - 1
value = (self.value >> start) & mask
return SelectableInt(value, bits)
stop = self.bits - key.start
start = self.bits - key.stop
- bits = stop - start + 1
+ bits = stop - start
+ #print ("__setitem__ slice num bits", bits)
if isinstance(value, SelectableInt):
assert value.bits == bits, "%d into %d" % (value.bits, bits)
value = value.value
self.value = (self.value & ~mask) | (value & mask)
def __ge__(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
if isinstance(other, int):
- return other >= self.value
+ return onebit(self.value >= other.value)
assert False
def __le__(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
if isinstance(other, int):
- return onebit(other <= self.value)
+ return onebit(self.value <= other)
assert False
def __gt__(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
if isinstance(other, int):
- return onebit(other > self.value)
+ return onebit(self.value > other)
assert False
def __lt__(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
if isinstance(other, int):
- return onebit(other < self.value)
+ return onebit(self.value < other)
assert False
def __eq__(self, other):
+ print ("__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
if isinstance(other, int):
return onebit(other == self.value)
assert False
+ def narrow(self, bits):
+ assert bits <= self.bits
+ return SelectableInt(self.value, bits)
+
def __bool__(self):
return self.value != 0
def __repr__(self):
- return "SelectableInt(value={:x}, bits={})".format(self.value,
+ return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
self.bits)
+ def __len__(self):
+ return self.bits
+
def onebit(bit):
return SelectableInt(1 if bit else 0, 1)
args = tmp
res = copy(args[0])
for i in args[1:]:
+ if isinstance(i, FieldSelectableInt):
+ i = i.si
assert isinstance(i, SelectableInt), "can only concat SIs, sorry"
res.bits += i.bits
res.value = (res.value << i.bits) | i.value
a[0:4] = 3
self.assertEqual(a, 0x39)
a[0:4] = a[4:8]
- self.assertEqual(a, 0x199)
+ self.assertEqual(a, 0x99)
+
+ def test_concat(self):
+ a = SelectableInt(0x1, 1)
+ c = selectconcat(a, repeat=8)
+ self.assertEqual(c, 0xff)
+ self.assertEqual(c.bits, 8)
+ a = SelectableInt(0x0, 1)
+ c = selectconcat(a, repeat=8)
+ self.assertEqual(c, 0x00)
+ self.assertEqual(c.bits, 8)
+
+ def test_repr(self):
+ for i in range(65536):
+ a = SelectableInt(i, 16)
+ b = eval(repr(a))
+ self.assertEqual(a, b)
+
+ def test_cmp(self):
+ a = SelectableInt(10, bits=8)
+ b = SelectableInt(5, bits=8)
+ self.assertTrue(a > b)
+ self.assertFalse(a < b)
+ self.assertTrue(a != b)
+ self.assertFalse(a == b)
+
+ def test_unsigned(self):
+ a = SelectableInt(0x80, bits=8)
+ b = SelectableInt(0x7f, bits=8)
+ self.assertTrue(a > b)
+ self.assertFalse(a < b)
+ self.assertTrue(a != b)
+ self.assertFalse(a == b)
if __name__ == "__main__":
unittest.main()