import struct
from copy import copy
import functools
-from openpower.decoder.power_fields import BitRange
+from collections import OrderedDict
from operator import (add, sub, mul, floordiv, truediv, mod, or_, and_, xor,
neg, inv, lshift, rshift, lt, eq)
from openpower.util import log
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
vi = op(vi)
return self.merge(vi)
+ def __len__(self):
+ return len(self.br)
+
def __getitem__(self, key):
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)
return self._op(xor, b)
def __lt__(self, b):
- return self._op(lt, b)
+ vi = self.get_range()
+ return onebit(lt(vi, b))
def __eq__(self, b):
- return self._op(eq, b)
+ vi = self.get_range()
+ return onebit(eq(vi, b))
def get_range(self):
vi = SelectableInt(0, len(self.br))
return True
return False
+ def __int__(self):
+ return self.asint(msb0=True)
+
def asint(self, msb0=False):
res = 0
brlen = len(self.br)
def __init__(self, value, bits=None):
if isinstance(value, SelectableInt):
if bits is not None:
- raise ValueError(value)
+ # 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):
value = (self.value >> start) & mask
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):
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):
return struct.unpack('<d', data)[0]
-class SelectableIntMappingMeta(type):
- @functools.total_ordering
- class Field(FieldSelectableInt):
- def __int__(self):
- return self.asint(msb0=True)
-
- def __lt__(self, b):
- return int(self).__lt__(b)
-
- def __eq__(self, b):
- return int(self).__eq__(b)
-
- class FieldProperty:
- def __init__(self, field):
- self.__field = field
-
- def __repr__(self):
- return self.__field.__repr__()
-
- def __get__(self, instance, owner):
- if instance is None:
- return self.__field
-
- cls = SelectableIntMappingMeta.Field
- factory = lambda br: cls(si=instance, br=br)
- if isinstance(self.__field, dict):
- return {k:factory(br=v) for (k, v) in self.__field.items()}
- else:
- return factory(br=self.__field)
-
- class BitsProperty:
- def __init__(self, bits):
- self.__bits = bits
-
- def __get__(self, instance, owner):
- if instance is None:
- return self.__bits
- return instance.bits
-
- def __repr__(self):
- return self.__bits.__repr__()
-
- def __new__(metacls, name, bases, attrs, bits=None, 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)
-
- fields = dict(map(field, fields.items()))
- for (key, value) in fields.items():
- attrs.setdefault(key, metacls.FieldProperty(value))
-
- if bits is None:
- for base in bases:
- bits = getattr(base, "bits", None)
- if bits is not None:
- break
-
- if not isinstance(bits, int):
- raise ValueError(bits)
- attrs.setdefault("bits", metacls.BitsProperty(bits))
-
- cls = super().__new__(metacls, name, bases, attrs)
- cls.__fields = fields
- return cls
-
- def __iter__(cls):
- for (key, value) in cls.__fields.items():
- yield (key, value)
-
-
-class SelectableIntMapping(SelectableInt, metaclass=SelectableIntMappingMeta,
- bits=0):
- def __init__(self, value=0, bits=None):
- if isinstance(value, int) and bits is None:
- bits = self.__class__.bits
- return super().__init__(value, bits)
-
-
def onebit(bit):
return SelectableInt(1 if bit else 0, 1)