+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):
+ vi = SelectableInt(0, len(self.br))
+ for k, v in self.br.items():
+ vi[k] = self.si[v]
+ 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)
+
+ def asint(self, msb0=False):
+ res = 0
+ brlen = len(self.br)
+ for i, key in self.br.items():
+ bit = self.si[key].value
+ #print("asint", i, key, bit)
+ res |= bit << ((brlen-i-1) if msb0 else i)
+ return res
+
+
+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)
+