import unittest
import struct
from copy import copy
+import functools
from openpower.decoder.power_fields import BitRange
from operator import (add, sub, mul, floordiv, truediv, mod, or_, and_, xor,
neg, inv, lshift, rshift)
def __init__(self, si, br):
self.si = si # target selectable int
- if isinstance(br, list) or isinstance(br, tuple):
+ if isinstance(br, (list, tuple, range)):
_br = BitRange()
for i, v in enumerate(br):
_br[i] = v
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:
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 asint(self, msb0=False):
res = 0
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):
+ bits = value.bits
value = value.value
mask = (1 << bits) - 1
self.value = value & mask
def __setitem__(self, key, value):
if isinstance(key, SelectableInt):
key = key.value
- log("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
assert key.step is None or key.step == 1
assert key.start < key.stop
assert key.start >= 0
- assert key.stop <= self.bits
+ assert key.stop <= self.bits, \
+ "key stop %d bits %d" % (key.stop, self.bits)
stop = self.bits - key.start
start = self.bits - key.stop
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)
return self.value != 0
def __repr__(self):
- return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
- self.bits)
+ value = f"value=0x{self.value:x}, bits={self.bits}"
+ return f"{self.__class__.__name__}({value})"
def __len__(self):
return self.bits
return struct.unpack('<d', data)[0]
+class SelectableIntMappingMeta(type):
+ def __new__(metacls, name, bases, attrs, bits=0, fields=None):
+ if fields is None:
+ fields = {}
+
+ def field(item):
+ (key, value) = item
+ if isinstance(value, dict):
+ value = dict(map(field, value.items()))
+ else:
+ value = tuple(value)
+ return (key, value)
+
+ cls = super().__new__(metacls, name, bases, attrs)
+ cls.__bits = bits
+ cls.__fields = dict(map(field, fields.items()))
+
+ return cls
+
+ def __iter__(cls):
+ for (key, value) in cls.__fields.items():
+ yield (key, value)
+
+ def __getattr__(cls, attr):
+ try:
+ return cls.__fields[attr]
+ except KeyError as error:
+ raise AttributeError from error
+
+ @property
+ def bits(cls):
+ return cls.__bits
+
+
+class SelectableIntMapping(SelectableInt, metaclass=SelectableIntMappingMeta):
+ def __init__(self, value=0):
+ return super().__init__(value, self.__class__.bits)
+
+ def __getattr__(self, attr):
+ def field(value):
+ if isinstance(value, dict):
+ return {key:field(value) for (key, value) in tuple(value.items())}
+ return FieldSelectableInt(si=self, br=value)
+
+ try:
+ return field(getattr(self.__class__, attr))
+ except KeyError as error:
+ raise AttributeError from error
+
+
def onebit(bit):
return SelectableInt(1 if bit else 0, 1)