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)
+from operator import (add, sub, mul, floordiv, truediv, mod, or_, and_, xor,
+ neg, inv, lshift, rshift)
def check_extsign(a, b):
class FieldSelectableInt:
"""FieldSelectableInt: allows bit-range selection onto another target
"""
+
def __init__(self, si, br):
- self.si = si # target selectable int
+ 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.
+ self.br = br # map of indices.
def eq(self, b):
if isinstance(b, SelectableInt):
return self.merge(vi)
def __getitem__(self, key):
- print ("getitem", key, self.br)
+ 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
+ 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]
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
+ key = self.br[key] # don't do POWER 1.3.4 bit-inversion
if isinstance(key, int):
return self.si.__setitem__(key, value)
else:
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):
br[2] = 3
fs = FieldSelectableInt(a, br)
c = fs + b
- print (c)
+ print(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
+
+ this class is designed to mirror precisely the behaviour of python int.
+ the only difference is that it must contain the context of the bitwidth
+ (number of bits) associated with that integer.
+
+ FieldSelectableInt can then operate on partial bits, and because there
+ is a bit width associated with SelectableInt, slices operate correctly
+ including negative start/end points.
+ """
+
def __init__(self, value, bits):
+ if isinstance(value, SelectableInt):
+ value = value.value
mask = (1 << bits) - 1
self.value = value & mask
self.bits = bits
+ self.overflow = (value & ~mask) != 0
def eq(self, b):
self.value = b.value
self.bits = b.bits
- def __add__(self, b):
+ def to_signed_int(self):
+ print ("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)
+ else:
+ res = self.value
+ print (" val +ve:", res)
+ return res
+
+ def _op(self, op, 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)
+ return SelectableInt(op(self.value, b.value), self.bits)
+
+ def __add__(self, b):
+ return self._op(add, b)
def __sub__(self, b):
+ return self._op(sub, b)
+
+ def __mul__(self, b):
+ # different case: mul result needs to fit the total bitsize
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)
+ print("SelectableInt mul", hex(self.value), hex(b.value),
+ self.bits, b.bits)
+ return SelectableInt(self.value * b.value, self.bits + b.bits)
+
+ def __floordiv__(self, b):
+ return self._op(floordiv, b)
+
+ def __truediv__(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 __abs__(self):
+ print("abs", self.value & (1 << (self.bits-1)))
+ if self.value & (1 << (self.bits-1)) != 0:
+ return -self
+ return self
def __rsub__(self, b):
if isinstance(b, int):
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, self.bits)
def __neg__(self):
- return SelectableInt(~self.value + 1, self.bits)
+ res = SelectableInt((~self.value) + 1, self.bits)
+ print ("neg", hex(self.value), hex(res.value))
+ return res
def __lshift__(self, b):
b = check_extsign(self, b)
return SelectableInt(self.value >> b.value, self.bits)
def __getitem__(self, key):
+ if isinstance(key, SelectableInt):
+ key = key.value
+ print("getitem", key, self.bits, hex(self.value))
if isinstance(key, int):
assert key < self.bits, "key %d accessing %d" % (key, self.bits)
assert key >= 0
start = self.bits - key.stop
bits = stop - start
- #print ("__getitem__ slice num bits", bits)
+ #print ("__getitem__ slice num bits", start, stop, bits)
mask = (1 << bits) - 1
value = (self.value >> start) & mask
return SelectableInt(value, 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
if isinstance(other, SelectableInt):
other = check_extsign(self, other)
assert other.bits == self.bits
- other = other.value
+ other = other.to_signed_int()
if isinstance(other, int):
- return onebit(self.value >= other.value)
+ return onebit(self.to_signed_int() >= other)
assert False
def __le__(self, other):
if isinstance(other, SelectableInt):
other = check_extsign(self, other)
assert other.bits == self.bits
- other = other.value
+ other = other.to_signed_int()
if isinstance(other, int):
- return onebit(self.value <= other)
+ return onebit(self.to_signed_int() <= other)
assert False
def __gt__(self, other):
if isinstance(other, SelectableInt):
other = check_extsign(self, other)
assert other.bits == self.bits
- other = other.value
+ other = other.to_signed_int()
if isinstance(other, int):
- return onebit(self.value > other)
+ return onebit(self.to_signed_int() > other)
assert False
def __lt__(self, other):
+ print ("SelectableInt 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
+ other = other.to_signed_int()
if isinstance(other, int):
- return onebit(self.value < other)
+ a = self.to_signed_int()
+ res = onebit(a < other)
+ print (" a < b", a, other, res)
+ return res
assert False
def __eq__(self, other):
- print ("__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
+ print (" eq", other, self.value, other == self.value)
if isinstance(other, int):
return onebit(other == self.value)
assert False
def __repr__(self):
return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
- self.bits)
+ self.bits)
def __len__(self):
return self.bits
+ def asint(self):
+ return self.value
+
+
def onebit(bit):
return SelectableInt(1 if bit else 0, 1)
+
def selectltu(lhs, rhs):
""" less-than (unsigned)
"""
rhs = rhs.value
return onebit(lhs.value < rhs)
+
def selectgtu(lhs, rhs):
""" greater-than (unsigned)
"""
else:
lower, upper, step = idx
toidx = range(lower, upper, step)
- fromidx = range(0, upper-lower, step) # XXX eurgh...
+ fromidx = range(0, upper-lower, step) # XXX eurgh...
else:
toidx = [idx]
fromidx = [0]
def selectconcat(*args, repeat=1):
if repeat != 1 and len(args) == 1 and isinstance(args[0], int):
args = [SelectableInt(args[0], 1)]
- if repeat != 1: # multiplies the incoming arguments
+ if repeat != 1: # multiplies the incoming arguments
tmp = []
for i in range(repeat):
tmp += args
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)
+ print("concat", repeat, res)
return res
d = a - b
e = a * b
f = -a
+ g = abs(f)
+ h = abs(a)
self.assertEqual(c.value, a.value + b.value)
self.assertEqual(d.value, (a.value - b.value) & 0xFF)
self.assertEqual(e.value, (a.value * b.value) & 0xFF)
self.assertEqual(c.bits, a.bits)
self.assertEqual(d.bits, a.bits)
self.assertEqual(e.bits, a.bits)
+ self.assertEqual(a.bits, f.bits)
+ self.assertEqual(a.bits, h.bits)
def test_logic(self):
a = SelectableInt(0x0F, 8)
self.assertTrue(a != b)
self.assertFalse(a == b)
+
if __name__ == "__main__":
unittest.main()