From 502f841f970a57de615179ee9184c761712855ca Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Thu, 30 Dec 2021 16:55:33 +0000 Subject: [PATCH] sv_binutils: introduce helper classes --- src/openpower/sv/sv_binutils.py | 148 ++++++++++++++++++++++++++------ 1 file changed, 120 insertions(+), 28 deletions(-) diff --git a/src/openpower/sv/sv_binutils.py b/src/openpower/sv/sv_binutils.py index dc85cc4b..5990c103 100644 --- a/src/openpower/sv/sv_binutils.py +++ b/src/openpower/sv/sv_binutils.py @@ -1,3 +1,4 @@ +import abc as _abc import argparse as _argparse import codecs as _codecs import dataclasses as _dataclasses @@ -5,40 +6,135 @@ import enum as _enum 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): @@ -92,16 +188,12 @@ def parse(stream): 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) -- 2.30.2