+import abc as _abc
import argparse as _argparse
import codecs as _codecs
import dataclasses as _dataclasses
import pathlib as _pathlib
import re as _re
-
from openpower.decoder.power_enums import (
- SVPtype as _SVPtype,
- SVEtype as _SVEtype,
In1Sel as _In1Sel,
In2Sel as _In2Sel,
In3Sel as _In3Sel,
OutSel as _OutSel,
CRInSel as _CRInSel,
CROutSel as _CROutSel,
+ SVPtype as _SVPtype,
+ SVEtype as _SVEtype,
SVEXTRA as _SVEXTRA,
)
+def indent(strings):
+ return map(lambda string: (" " + string), strings)
+
+
+class Field:
+ @classmethod
+ @_abc.abstractmethod
+ def c_decl(self, name):
+ pass
+
+ @_abc.abstractmethod
+ def c_value(self, prefix="", suffix=""):
+ pass
+
+ @classmethod
+ @_abc.abstractmethod
+ def c_var(self, name):
+ pass
+
+
+class Enum(Field, _enum.Enum):
+ @classmethod
+ def c_decl(cls):
+ c_tag = f"svp64_{cls.__name__.lower()}"
+ yield f"enum {c_tag} {{"
+ for item in cls:
+ yield from indent(item.c_value(suffix=","))
+ yield f"}};"
+
+ def c_value(self, prefix="", suffix=""):
+ c_tag = f"svp64_{self.__class__.__name__.lower()}"
+ yield f"{prefix}{c_tag.upper()}_{self.name.upper()}{suffix}"
+
+ @classmethod
+ def c_var(cls, name):
+ c_tag = f"svp64_{cls.__name__.lower()}"
+ yield f"enum {c_tag} {name};"
+
+
+# Python forbids inheriting from enum unless it's empty.
+In1Sel = Enum("In1Sel", {item.name:item.value for item in _In1Sel})
+In2Sel = Enum("In2Sel", {item.name:item.value for item in _In2Sel})
+In3Sel = Enum("In3Sel", {item.name:item.value for item in _In3Sel})
+OutSel = Enum("OutSel", {item.name:item.value for item in _OutSel})
+CRInSel = Enum("CRInSel", {item.name:item.value for item in _CRInSel})
+CROutSel = Enum("CROutSel", {item.name:item.value for item in _CROutSel})
+SVPType = Enum("SVPType", {item.name:item.value for item in _SVPtype})
+SVEType = Enum("SVEType", {item.name:item.value for item in _SVEtype})
+SVEXTRA = Enum("SVEXTRA", {item.name:item.value for item in _SVEXTRA})
+
+
+class Opcode(Field, str):
+ def c_value(self, prefix="", suffix=""):
+ yield f"{prefix}\"{self}\"{suffix}"
+
+ @classmethod
+ def c_var(cls, name):
+ yield f"const char *{name};"
+
+
+class Name(Field, str):
+ def __repr__(self):
+ escaped = self.replace("\"", "\\\"")
+ return f"\"{escaped}\""
+
+ def c_value(self, prefix="", suffix=""):
+ yield f"{prefix}{self!r}{suffix}"
+
+ @classmethod
+ def c_var(cls, name):
+ yield f"const char *{name};"
+
+
@_dataclasses.dataclass(eq=True, frozen=True)
class Entry:
- opcode: str
- ptype: _SVPtype
- etype: _SVEtype
- in1: _In1Sel
- in2: _In2Sel
- in3: _In3Sel
- out: _OutSel
- out2: _OutSel
- cr_in: _CRInSel
- cr_out: _CROutSel
- sv_in1: _SVEXTRA
- sv_in2: _SVEXTRA
- sv_in3: _SVEXTRA
- sv_out: _SVEXTRA
- sv_out2: _SVEXTRA
- sv_cr_in: _SVEXTRA
- sv_cr_out: _SVEXTRA
- name: str
+ name: Name
+ opcode: Opcode
+ in1: In1Sel
+ in2: In2Sel
+ in3: In3Sel
+ out: OutSel
+ out2: OutSel
+ cr_in: CRInSel
+ cr_out: CROutSel
+ ptype: SVPType
+ etype: SVEType
+ sv_in1: SVEXTRA
+ sv_in2: SVEXTRA
+ sv_in3: SVEXTRA
+ sv_out: SVEXTRA
+ sv_out2: SVEXTRA
+ sv_cr_in: SVEXTRA
+ sv_cr_out: SVEXTRA
+
+ @classmethod
+ def c_decl(cls):
+ yield f"struct svp64_entry {{"
+ for field in _dataclasses.fields(cls):
+ if issubclass(field.type, Enum):
+ bits = len(field.type).bit_length()
+ yield from indent([f"uint64_t {field.name} : {bits};"])
+ else:
+ yield from indent(field.type.c_var(name=field.name))
+ yield f"}};"
+
+ def c_value(self, prefix="", suffix=""):
+ yield f"{prefix}{{"
+ for field in _dataclasses.fields(self):
+ name = field.name
+ attr = getattr(self, name)
+ yield from indent(attr.c_value(prefix=f".{name} = ", suffix=","))
+ yield f"}}{suffix}"
+
+ @classmethod
+ def c_var(cls, name):
+ yield f"struct svp64_entry {name};"
def regex_enum(enum):
if match is not None:
entry = match.groupdict()
for field in _dataclasses.fields(Entry):
- cls = field.type
key = field.name
value = entry[key]
- if issubclass(cls, _enum.Enum):
- value = {item.name:item for item in cls}[value]
- elif key == "opcode":
- if value.startswith("2#"):
- value = value[2:-1]
+ if issubclass(field.type, _enum.Enum):
+ value = {item.name:item for item in field.type}[value]
else:
- value = cls(value)
+ value = field.type(value)
entry[key] = value
yield Entry(**entry)