from collections import namedtuple
-import operator as _operator
-import functools as _functools
+import operator
+import functools
-from openpower.decoder.power_enums import find_wiki_file as _find_wiki_file
+from openpower.decoder.power_enums import find_wiki_file
from openpower.decoder.selectable_int import (
- SelectableInt as _SelectableInt,
- BitRange as _BitRange,
- selectconcat as _selectconcat,
- selectltu as _selectltu,
+ SelectableInt,
+ BitRange,
+ selectconcat,
+ selectltu,
)
self.__cls(storage=instance.storage).assign(value)
-@_functools.total_ordering
+@functools.total_ordering
class Reference:
def __init__(self, storage, *args, **kwargs):
- if not isinstance(storage, _SelectableInt):
+ if not isinstance(storage, SelectableInt):
raise ValueError(storage)
self.storage = storage
def __binary_operator(self, op, other):
span = dict.fromkeys(self.__class__.span).keys()
- lhs = _selectconcat(*(self.storage[bit] for bit in span))
+ lhs = selectconcat(*(self.storage[bit] for bit in span))
if isinstance(other, Reference):
span = dict.fromkeys(other.__class__.span).keys()
- rhs = _selectconcat(*(other.storage[bit] for bit in span))
+ rhs = selectconcat(*(other.storage[bit] for bit in span))
elif isinstance(other, int):
bits = len(self.__class__)
if other.bit_length() > bits:
raise OverflowError(other)
- rhs = _SelectableInt(value=other, bits=bits)
- elif isinstance(other, _SelectableInt):
+ rhs = SelectableInt(value=other, bits=bits)
+ elif isinstance(other, SelectableInt):
rhs = other
else:
raise ValueError(other)
- return op(int(lhs), int(rhs))
+ return op(lhs, rhs)
def __lt__(self, other):
- return self.__binary_operator(_selectltu, other)
+ return self.__binary_operator(selectltu, other)
def __eq__(self, other):
- return self.__binary_operator(_operator.eq, other)
+ return self.__binary_operator(operator.eq, other)
+
+ def __bool__(self):
+ return bool(int(self))
def __int__(self):
span = dict.fromkeys(self.__class__.span).keys()
- return int(_selectconcat(*(self.storage[bit] for bit in span)))
+ return int(selectconcat(*(self.storage[bit] for bit in span)))
def __index__(self):
return int(self).__index__()
@storage.setter
def storage(self, storage):
- if not isinstance(storage, _SelectableInt):
+ if not isinstance(storage, SelectableInt):
raise ValueError(storage)
self.__storage = storage
- def assign(self, value):
- if isinstance(value, int):
- bits = len(self.__class__)
- value = _SelectableInt(value=value, bits=bits)
- if not isinstance(value, _SelectableInt):
+ def assign(self, value, bits=None):
+ if bits is None:
+ bits = range(len(self.__class__))
+ elif isinstance(bits, int):
+ bits = (bits,)
+ elif isinstance(bits, slice):
+ assert bits.step is None or bits.step == 1
+ bits = range(bits.start, bits.stop)
+ bits = tuple(bits)
+
+ if isinstance(value, (int, self.__class__)):
+ value = int(value)
+ if value.bit_length() > len(bits):
+ raise OverflowError(value)
+ value = SelectableInt(value=value, bits=len(bits))
+ if not isinstance(value, SelectableInt):
raise ValueError(value)
+ if value.bits != len(bits):
+ raise OverflowError(value)
- span = frozenset(self.__class__.span)
- for (src_bit, dst_bit) in enumerate(span):
- self.storage[dst_bit] = value[src_bit]
+ span = tuple(self.__class__.span)
+ mapping = dict(enumerate(span))
+ for (src, bit) in enumerate(bits):
+ if src >= value.bits:
+ raise OverflowError(src)
+ dst = mapping.get(bit)
+ if dst is None:
+ raise OverflowError(bit)
+ self.storage[dst] = value[src]
class FieldMeta(type):
class Field(Reference, metaclass=FieldMeta):
- def __len__(self):
- return self.__class__.__len__()
-
def __repr__(self):
return f"[{len(self.__class__)}]0x{int(self):x}"
def __getitem__(self, key):
if isinstance(key, int):
bit = self.storage[self.__class__.__members__[key]]
- return _SelectableInt(value=bit, bits=1)
+ return SelectableInt(value=bit, bits=1)
if isinstance(key, slice):
assert key.step is None or key.step == 1
key = range(key.start, key.stop)
- return _selectconcat(*(self[bit] for bit in tuple(key)))
+ return selectconcat(*(self[bit] for bit in key))
- def traverse(self, path):
- span = self.__class__.__members__
- yield (path, self.storage[span], span)
+ def __setitem__(self, key, value):
+ return self.assign(value=value, bits=key)
+
+ @classmethod
+ def traverse(cls, path):
+ yield (path, cls.__members__)
class MappingMeta(type):
return length
def __getitem__(cls, selector):
- best_min = 0
- best_max = 0
- for field in cls.__members__.values():
- length = len(field)
- best_min = min(best_min, length)
- best_max = max(best_max, length)
-
- items = tuple(range(best_min, best_max))
- field = FieldMeta(cls.__name__, (Field,), {}, items=items)
-
- return field[selector]
+ return cls.__members__["_"][selector]
def remap(cls, scheme):
ns = {}
def __getitem__(self, key):
if isinstance(key, (int, slice, list, tuple, range)):
- return self["_"][key]
+ return self["_"].__getitem__(key)
+
+ return self.__members.__getitem__(key)
+
+ def __setitem__(self, key, value):
+ if isinstance(key, (int, slice, list, tuple, range)):
+ return self["_"].assign(value=value, bits=key)
+
+ return self.assign(value=value, bits=key)
- return self.__members[key]
+ def __getattr__(self, key):
+ raise AttributeError(key)
- def traverse(self, path=""):
- for (name, member) in self.__members.items():
+ @classmethod
+ def traverse(cls, path):
+ for (name, member) in cls.__members__.items():
if name == "_":
yield from member.traverse(path=path)
elif path == "":
class DecodeFields:
- def __init__(self, bitkls=_BitRange, bitargs=(), fname=None,
+ def __init__(self, bitkls=BitRange, bitargs=(), fname=None,
name_on_wiki=None):
self.bitkls = bitkls
self.bitargs = bitargs
assert name_on_wiki is None
fname = "fields.txt"
name_on_wiki = "fields.text"
- self.fname = _find_wiki_file(name_on_wiki)
+ self.fname = find_wiki_file(name_on_wiki)
@property
def form_names(self):
#print ("decode", txt)
forms = {}
reading_data = False
- for l in txt:
+ for lineno, l in enumerate(txt):
l = l.strip()
if len(l) == 0:
continue
if l[0] == '#':
reading_data = False
else:
- forms[heading].append(l)
+ form = forms[heading]
+ form.append(l)
+ if len(form) <= 1:
+ continue
+ # check separators line up with header
+ for i, ch in enumerate(l):
+ if ch != '|':
+ continue
+ if i >= len(form[0]) or form[0][i] != '|':
+ col = len(txt[lineno]) - len(txt[lineno].lstrip())
+ col += i + 1
+ raise SyntaxError("form line field separator ('|') "
+ "with no corresponding separator in header",
+ (self.fname, lineno + 1, col, txt[lineno]))
if not reading_data:
assert l[0] == '#'
heading = l[1:].strip()