selectable_int: derive SelectableIntMapping on per-class basis
authorDmitry Selyutin <dmitry.selyutin@3mdeb.com>
Wed, 20 Apr 2022 18:49:20 +0000 (18:49 +0000)
committerDmitry Selyutin <dmitry.selyutin@3mdeb.com>
Wed, 20 Apr 2022 18:49:24 +0000 (18:49 +0000)
src/openpower/decoder/isa/caller.py
src/openpower/decoder/selectable_int.py
src/openpower/sv/sv_binutils.py

index 524d393c56b563a48994f68352aeefb8084df46b..bfcb7b982df2e6f9e7062cbf3828408a93ce010b 100644 (file)
@@ -259,10 +259,7 @@ class PC:
 
 
 # SVP64 ReMap field
-class SVP64RMFields(SelectableIntMapping):
-    def __init__(self, value=0):
-        self.spr = SelectableInt(value=value, bits=24)
-        return super().__init__(si=self.spr, fields={
+class SVP64RMFields(SelectableIntMapping, bits=24, fields={
             "spr": range(24),
             # SVP64 RM fields: see https://libre-soc.org/openpower/sv/svp64/
             "mmode": (0,),
@@ -286,37 +283,42 @@ class SVP64RMFields(SelectableIntMapping):
                 range(13, 16),
                 range(16, 19),
             ])),
-        })
+        }):
+
+    def __init__(self, value=0):
+        super().__init__(value=value)
+        self.spr = self
 
 
-SVP64RM_MMODE_SIZE = len(SVP64RMFields().mmode.br)
-SVP64RM_MASK_SIZE = len(SVP64RMFields().mask.br)
-SVP64RM_ELWIDTH_SIZE = len(SVP64RMFields().elwidth.br)
-SVP64RM_EWSRC_SIZE = len(SVP64RMFields().ewsrc.br)
-SVP64RM_SUBVL_SIZE = len(SVP64RMFields().subvl.br)
-SVP64RM_EXTRA2_SPEC_SIZE = len(SVP64RMFields().extra2[0].br)
-SVP64RM_EXTRA3_SPEC_SIZE = len(SVP64RMFields().extra3[0].br)
-SVP64RM_SMASK_SIZE = len(SVP64RMFields().smask.br)
-SVP64RM_MODE_SIZE = len(SVP64RMFields().mode.br)
+SVP64RM_MMODE_SIZE = len(SVP64RMFields.mmode)
+SVP64RM_MASK_SIZE = len(SVP64RMFields.mask)
+SVP64RM_ELWIDTH_SIZE = len(SVP64RMFields.elwidth)
+SVP64RM_EWSRC_SIZE = len(SVP64RMFields.ewsrc)
+SVP64RM_SUBVL_SIZE = len(SVP64RMFields.subvl)
+SVP64RM_EXTRA2_SPEC_SIZE = len(SVP64RMFields.extra2[0])
+SVP64RM_EXTRA3_SPEC_SIZE = len(SVP64RMFields.extra3[0])
+SVP64RM_SMASK_SIZE = len(SVP64RMFields.smask)
+SVP64RM_MODE_SIZE = len(SVP64RMFields.mode)
 
 
 # SVP64 Prefix fields: see https://libre-soc.org/openpower/sv/svp64/
-class SVP64PrefixFields(SelectableIntMapping):
-    def __init__(self, value=0):
-        self.insn = SelectableInt(value, 32)
-        return super().__init__(si=self.insn, fields={
+class SVP64PrefixFields(SelectableIntMapping, bits=32, fields={
             "insn": range(32),
             # 6 bit major opcode EXT001, 2 bits "identifying" (7, 9), 24 SV ReMap
             "major": range(0, 6),
             "pid": (7, 9),
             # SVP64 24-bit RM (ReMap)
             "rm": ((6, 8) + tuple(range(10, 32))),
-        })
+        }):
+
+    def __init__(self, value=0):
+        super().__init__(value=value)
+        self.insn = self
 
 
-SV64P_MAJOR_SIZE = len(SVP64PrefixFields().major.br)
-SV64P_PID_SIZE = len(SVP64PrefixFields().pid.br)
-SV64P_RM_SIZE = len(SVP64PrefixFields().rm.br)
+SV64P_MAJOR_SIZE = len(SVP64PrefixFields.major)
+SV64P_PID_SIZE = len(SVP64PrefixFields.pid)
+SV64P_RM_SIZE = len(SVP64PrefixFields.rm)
 
 
 # CR register fields
index fc1dfeb9bb19b8684ed71c3a16bb7296049ff1e1..41079cad10bb1780a9d537353234cbc97852b975 100644 (file)
@@ -1,6 +1,7 @@
 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)
@@ -438,21 +439,53 @@ class SelectableInt:
         return struct.unpack('<d', data)[0]
 
 
-class SelectableIntMapping(dict):
-    def __init__(self, si, fields=None):
+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 = FieldSelectableInt(si, value)
+                value = tuple(value)
             return (key, value)
 
-        return super().__init__(map(field, fields.items()))
+        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):
+        print("SelectableIntMappingMeta", 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 self[attr]
+            return field(getattr(self.__class__, attr))
         except KeyError as error:
             raise AttributeError from error
 
index 114e7c6f46d2b3f6305821b6459164cdbddd1956..d79eca54d79cebb2eb35b77736ebc73cfe2fb156 100644 (file)
@@ -1,6 +1,5 @@
 import abc as _abc
 import argparse as _argparse
-import builtins as _builtins
 import dataclasses as _dataclasses
 import enum as _enum
 
@@ -20,6 +19,7 @@ from openpower.consts import SVP64MODE as _SVP64MODE
 from openpower.decoder.power_svp64 import SVP64RM as _SVP64RM
 from openpower.decoder.isa.caller import SVP64RMFields as _SVP64RMFields
 from openpower.decoder.isa.caller import SVP64PrefixFields as _SVP64PrefixFields
+from openpower.decoder.selectable_int import SelectableIntMapping
 
 
 DISCLAIMER = (
@@ -278,7 +278,7 @@ class Field(Struct):
 
 
 class FieldsMeta(CTypeMeta):
-    def __new__(metacls, name, bases, attrs, **kwargs):
+    def __new__(metacls, name, bases, attrs, base=SelectableIntMapping):
         def flatten(mapping, parent=""):
             for (key, value) in mapping.items():
                 key = f"{parent}_{key}" if parent else key
@@ -287,17 +287,18 @@ class FieldsMeta(CTypeMeta):
                 else:
                     yield (key.upper(), value)
 
-        fields = dict(flatten(mapping=kwargs))
+        mapping = dict(base)
+        fields = dict(flatten(mapping=mapping))
         keys = ((key, index) for (index, key) in enumerate(fields))
         enum_cls = Enum(name, entries=keys, tag=f"svp64_{name.lower()}_type")
 
         def field(item):
             (key, value) = item
-            length = Size(len(value.br))
-            mapping = Byte[32](map(lambda bit: Byte((value.si.bits - 1) - bit), reversed(value.br)))
+            length = Size(len(value))
+            mapping = Byte[32](map(lambda bit: Byte((base.bits - 1) - bit), reversed(value)))
             return (key, Field(length=length, mapping=mapping))
 
-        typedef = kwargs.pop("typedef", Field.c_typedef)
+        typedef = mapping.pop("typedef", Field.c_typedef)
         cls = super().__new__(metacls, name, bases, attrs, typedef=typedef)
         cls.__enum = enum_cls
         cls.__fields = dict(map(field, zip(enum_cls, fields.values())))
@@ -323,11 +324,11 @@ class Fields(metaclass=FieldsMeta):
         yield f"}}{suffix}"
 
 
-class Prefix(Fields, **_SVP64PrefixFields(0)):
+class Prefix(Fields, type=_SVP64PrefixFields):
     pass
 
 
-class RM(Fields, **_SVP64RMFields(0)):
+class RM(Fields, type=_SVP64RMFields):
     pass