# 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.generator` module
"""
# Futures
from __future__ import absolute_import, annotations
# Built-in modules
import abc
from typing import TYPE_CHECKING, List
# Third party modules
# Own modules
from microprobe.exceptions import MicroprobeArchitectureDefinitionError
from microprobe.utils.imp import find_subclasses
from microprobe.utils.logger import get_logger
from microprobe.utils.typeguard_decorator import typeguard_testsuite
# Type hinting
if TYPE_CHECKING:
from microprobe.target.isa.register import Register
from microprobe.code.ins import Instruction
# Constants
LOG = get_logger(__name__)
__all__ = ["import_classes_from", "Generator"]
# Functions
[docs]
@typeguard_testsuite
def import_classes_from(modules: List[str]):
"""
:param modules:
"""
LOG.info("Start")
classes = {}
for module_str in modules:
for cls in find_subclasses(module_str, Generator):
name = cls.__name__
if name in classes:
raise MicroprobeArchitectureDefinitionError(
"Duplicated "
"definition"
" of Generator '%s' "
"in module '%s'", name, module_str)
LOG.info("%s generator imported", name)
classes[name] = cls
if len(classes) == 0:
LOG.warning("No generators imported.")
LOG.info("End")
return list(classes.values())
# Classes
[docs]
@typeguard_testsuite
class Generator(abc.ABC):
""" """
[docs]
def __init__(self, arch):
"""
:param arch:
"""
self._arch = arch
[docs]
@abc.abstractmethod
def check(self, value, fvalue, address=False):
"""
:param value:
:param fvalue:
:param address: (Default value = False)
"""
raise NotImplementedError
[docs]
@abc.abstractmethod
def generate(self,
value,
fvalue,
dummy_reg,
dummy_instr=None,
address=False):
"""
:param value:
:param fvalue:
:param dummy_reg:
:param dummy_instr: (Default value = None)
:param address: (Default value = False)
"""
assert (value, fvalue) == self.check(value, fvalue, address=address), \
"Check error: (%s, %s) != %s " % (value, fvalue,
self.check(value,
fvalue,
address=address))
@property
@abc.abstractmethod
def instr_name(self):
raise NotImplementedError
@property
def arch(self):
return self._arch
def _orig_reg(self, value, reg: Register, instr: Instruction):
"""
:param value:
:param reg:
:param instr:
"""
if value in list(self.arch.constants.keys()):
reg2 = self.arch.constants[value][-1]
if reg2 != reg:
instr.add_allow_register(reg2)
return reg2
return reg
@property
def alias(self): # pylint: disable=no-self-use
return []