Source code for microprobe.target.isa.register_type

# Copyright 2011-2021 IBM Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""":mod:`microprobe.target.isa.register_type` module

"""

# Futures
from __future__ import absolute_import

# Built-in modules
import abc
import hashlib
import os
from typing import Dict, List, Tuple

# Third party modules

# Own modules
from microprobe.exceptions import MicroprobeArchitectureDefinitionError
from microprobe.utils.logger import get_logger
from microprobe.utils.typeguard_decorator import typeguard_testsuite
from microprobe.utils.yaml import read_yaml

# Constants
SCHEMA = os.path.join(os.path.dirname(os.path.abspath(__file__)), "schemas",
                      "register_type.yaml")
LOG = get_logger(__name__)
__all__ = ["import_definition", "RegisterType", "GenericRegisterType"]

# Functions


[docs] @typeguard_testsuite def import_definition(cls, filenames, dummy): """ :param filenames: :param dummy: """ LOG.debug("Start") regts = {} regts_duplicated = {} for filename in filenames: regt_data = read_yaml(filename, SCHEMA) for elem in regt_data: name = elem["Name"] size = elem["Size"] descr = elem.get("Description", "No description") u4aa = elem.get("AddressArithmetic", False) u4fa = elem.get("FloatArithmetic", False) u4va = elem.get("VectorArithmetic", False) regt = cls(name, descr, size, u4aa, u4fa, u4va) key = tuple([size, u4aa, u4fa, u4va]) if key in regts_duplicated: LOG.warning( "Similar definition of register types: '%s' and" " '%s'. Check if definition needed.", name, regts_duplicated[key]) else: regts_duplicated[key] = name LOG.debug(regt) if name in regts: raise MicroprobeArchitectureDefinitionError( "Duplicated " "definition of register type '%s' " "found in '%s'" % (name, filename)) regts[name] = regt LOG.debug("End") return regts
# Classes
[docs] @typeguard_testsuite class RegisterType(abc.ABC): """Abstract base class to represent a Register Type"""
[docs] @abc.abstractmethod def __init__(self): pass
@property @abc.abstractmethod def name(self) -> str: """Register type name (:class:`~.str`)""" raise NotImplementedError @property @abc.abstractmethod def description(self) -> str: """Register type name (:class:`~.str`)""" raise NotImplementedError @property @abc.abstractmethod def size(self) -> int: """Register size in bits (::class:`~.int`)""" raise NotImplementedError @property @abc.abstractmethod def used_for_address_arithmetic(self) -> bool: raise NotImplementedError @property @abc.abstractmethod def used_for_float_arithmetic(self) -> bool: raise NotImplementedError @property @abc.abstractmethod def used_for_vector_arithmetic(self) -> bool: raise NotImplementedError def __str__(self): """x.__str__() <==> str(x)""" return "%8s: %s (bit size: %d)" % (self.name, self.description, self.size) def __repr__(self): """x.__repr__() <==> str(x)""" return "%8s: %s (bit size: %d)" % (self.name, self.description, self.size) @abc.abstractmethod def __hash__(self) -> int: raise NotImplementedError
[docs] @typeguard_testsuite class GenericRegisterType(RegisterType): """A class to represent a register type. Each register type is identified by its *type*, its *size* in bits and also its *semantic* properites (e.g. if they are used for address arithmetic, or for floating point cumpations, etc.) . :param rtype: Register type name :type rtype: :class:`~.str` :param rdescr: Register type description :type rdescr: :class:`~.str` :param rsize: Register size in bits :type rsize: :class:`~.int` """ _cmp_attributes = [ "name", "description", "size", "used_for_address_arithmetic", "used_for_float_arithmetic", "used_for_vector_arithmetic" ]
[docs] def __init__(self, rtype: str, rdescr: str, rsize: int, u4aa: bool, u4fa: bool, u4va: bool): """ :param rtype: :param rdescr: :param rsize: :param u4aa: :param u4fa: :param u4va: """ super(GenericRegisterType, self).__init__() self._rtype = rtype self._rdescr = rdescr self._rsize = rsize self._used_for_address_arithmetic = u4aa self._used_for_float_arithmetic = u4fa self._used_for_vector_arithmetic = u4va self._hash = int( hashlib.sha512( (str(self.name) + str(self.description) + str(self.size) + str(self.used_for_address_arithmetic) + str(self.used_for_float_arithmetic) + str(self.used_for_vector_arithmetic)).encode()).hexdigest(), 16)
@property def name(self): """Register type name (:class:`~.str`)""" return self._rtype @property def description(self): """Register type description (:class:`~.str`)""" return self._rdescr @property def size(self): """Register type size in bits (::class:`~.int`)""" return self._rsize @property def used_for_address_arithmetic(self): return self._used_for_address_arithmetic @property def used_for_float_arithmetic(self): return self._used_for_float_arithmetic @property def used_for_vector_arithmetic(self): return self._used_for_vector_arithmetic def __hash__(self): return self._hash def _check_cmp(self, other): if not isinstance(other, self.__class__): raise NotImplementedError("%s != %s" % (other.__class__, self.__class__)) def __eq__(self, other): """x.__eq__(y) <==> x==y""" self._check_cmp(other) for attr in self._cmp_attributes: if not getattr(self, attr) == getattr(other, attr): return False return True def __ne__(self, other): """x.__ne__(y) <==> x!=y""" self._check_cmp(other) for attr in self._cmp_attributes: if not getattr(self, attr) == getattr(other, attr): return True return False def __lt__(self, other): """x.__lt__(y) <==> x<y""" self._check_cmp(other) for attr in self._cmp_attributes: if getattr(self, attr) < getattr(other, attr): return True elif getattr(self, attr) > getattr(other, attr): return False return False def __gt__(self, other): """x.__gt__(y) <==> x>y""" self._check_cmp(other) for attr in self._cmp_attributes: if getattr(self, attr) > getattr(other, attr): return True elif getattr(self, attr) < getattr(other, attr): return False return False def __le__(self, other): """x.__le__(y) <==> x<=y""" self._check_cmp(other) for attr in self._cmp_attributes: if getattr(self, attr) <= getattr(other, attr): continue else: return False return True def __ge__(self, other): """x.__ge__(y) <==> x>=y""" self._check_cmp(other) for attr in self._cmp_attributes: if getattr(self, attr) >= getattr(other, attr): continue else: return False return True