Add mypy annotations to cdsl.predicates, settings.
Wherein we learned that only BoolSettings can be used as predicates.
This commit is contained in:
@@ -8,11 +8,10 @@ from .registers import RegClass, Register
|
|||||||
try:
|
try:
|
||||||
from typing import Tuple, Union, Any, Iterable, Sequence, List, Set, TYPE_CHECKING # noqa
|
from typing import Tuple, Union, Any, Iterable, Sequence, List, Set, TYPE_CHECKING # noqa
|
||||||
from .instructions import MaybeBoundInst, InstructionGroup, InstructionFormat # noqa
|
from .instructions import MaybeBoundInst, InstructionGroup, InstructionFormat # noqa
|
||||||
from .predicates import Predicate, FieldPredicate # noqa
|
from .predicates import PredNode # noqa
|
||||||
from .settings import SettingGroup # noqa
|
from .settings import SettingGroup # noqa
|
||||||
from .types import ValueType # noqa
|
from .types import ValueType # noqa
|
||||||
from .registers import RegBank # noqa
|
from .registers import RegBank # noqa
|
||||||
AnyPredicate = Union[Predicate, FieldPredicate]
|
|
||||||
OperandConstraint = Union[RegClass, Register, int]
|
OperandConstraint = Union[RegClass, Register, int]
|
||||||
ConstraintSeq = Union[OperandConstraint, Tuple[OperandConstraint, ...]]
|
ConstraintSeq = Union[OperandConstraint, Tuple[OperandConstraint, ...]]
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -80,8 +79,8 @@ class TargetISA(object):
|
|||||||
Ensures that all ISA predicates have an assigned bit number in
|
Ensures that all ISA predicates have an assigned bit number in
|
||||||
`self.settings`.
|
`self.settings`.
|
||||||
"""
|
"""
|
||||||
self.all_instps = list() # type: List[AnyPredicate]
|
self.all_instps = list() # type: List[PredNode]
|
||||||
instps = set() # type: Set[AnyPredicate]
|
instps = set() # type: Set[PredNode]
|
||||||
for cpumode in self.cpumodes:
|
for cpumode in self.cpumodes:
|
||||||
for enc in cpumode.encodings:
|
for enc in cpumode.encodings:
|
||||||
instp = enc.instp
|
instp = enc.instp
|
||||||
@@ -166,7 +165,7 @@ class EncRecipe(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, format, ins, outs, instp=None, isap=None):
|
def __init__(self, name, format, ins, outs, instp=None, isap=None):
|
||||||
# type: (str, InstructionFormat, ConstraintSeq, ConstraintSeq, AnyPredicate, AnyPredicate) -> None # noqa
|
# type: (str, InstructionFormat, ConstraintSeq, ConstraintSeq, PredNode, PredNode) -> None # noqa
|
||||||
self.name = name
|
self.name = name
|
||||||
self.format = format
|
self.format = format
|
||||||
self.instp = instp
|
self.instp = instp
|
||||||
@@ -219,7 +218,7 @@ class Encoding(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, cpumode, inst, recipe, encbits, instp=None, isap=None):
|
def __init__(self, cpumode, inst, recipe, encbits, instp=None, isap=None):
|
||||||
# type: (CPUMode, MaybeBoundInst, EncRecipe, int, AnyPredicate, AnyPredicate) -> None # noqa
|
# type: (CPUMode, MaybeBoundInst, EncRecipe, int, PredNode, PredNode) -> None # noqa
|
||||||
assert isinstance(cpumode, CPUMode)
|
assert isinstance(cpumode, CPUMode)
|
||||||
assert isinstance(recipe, EncRecipe)
|
assert isinstance(recipe, EncRecipe)
|
||||||
self.inst, self.typevars = inst.fully_bound()
|
self.inst, self.typevars = inst.fully_bound()
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ function determine the kind of predicate:
|
|||||||
|
|
||||||
- An *Instruction predicate* is evaluated on an instruction instance, so it can
|
- An *Instruction predicate* is evaluated on an instruction instance, so it can
|
||||||
inspect all the immediate fields and type variables of the instruction.
|
inspect all the immediate fields and type variables of the instruction.
|
||||||
Instruction predicates can be evaluatd before register allocation, so they
|
Instruction predicates can be evaluated before register allocation, so they
|
||||||
can not depend on specific register assignments to the value operands or
|
can not depend on specific register assignments to the value operands or
|
||||||
outputs.
|
outputs.
|
||||||
|
|
||||||
@@ -24,6 +24,17 @@ predicate, the context is the instruction format.
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
|
try:
|
||||||
|
from typing import Sequence, Tuple, Set, Any, Union, TYPE_CHECKING # noqa
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .formats import InstructionFormat, FormatField # noqa
|
||||||
|
from .settings import BoolSetting, SettingGroup # noqa
|
||||||
|
PredContext = Union[SettingGroup, InstructionFormat]
|
||||||
|
PredLeaf = Union[BoolSetting, 'FieldPredicate']
|
||||||
|
PredNode = Union[PredLeaf, 'Predicate']
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _is_parent(a, b):
|
def _is_parent(a, b):
|
||||||
"""
|
"""
|
||||||
@@ -58,7 +69,9 @@ class Predicate(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parts):
|
def __init__(self, parts):
|
||||||
self.name = None
|
# type: (Sequence[PredNode]) -> None
|
||||||
|
self.name = None # type: str
|
||||||
|
self.number = None # type: int
|
||||||
self.parts = parts
|
self.parts = parts
|
||||||
self.context = reduce(
|
self.context = reduce(
|
||||||
_descendant,
|
_descendant,
|
||||||
@@ -66,6 +79,7 @@ class Predicate(object):
|
|||||||
assert self.context, "Incompatible predicate parts"
|
assert self.context, "Incompatible predicate parts"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
# type: () -> str
|
||||||
if self.name:
|
if self.name:
|
||||||
return '{}.{}'.format(self.context.name, self.name)
|
return '{}.{}'.format(self.context.name, self.name)
|
||||||
else:
|
else:
|
||||||
@@ -74,15 +88,21 @@ class Predicate(object):
|
|||||||
', '.join(map(str, self.parts)))
|
', '.join(map(str, self.parts)))
|
||||||
|
|
||||||
def predicate_context(self):
|
def predicate_context(self):
|
||||||
|
# type: () -> PredContext
|
||||||
return self.context
|
return self.context
|
||||||
|
|
||||||
def predicate_leafs(self, leafs):
|
def predicate_leafs(self, leafs):
|
||||||
|
# type: (Set[PredLeaf]) -> None
|
||||||
"""
|
"""
|
||||||
Collect all leaf predicates into the `leafs` set.
|
Collect all leaf predicates into the `leafs` set.
|
||||||
"""
|
"""
|
||||||
for part in self.parts:
|
for part in self.parts:
|
||||||
part.predicate_leafs(leafs)
|
part.predicate_leafs(leafs)
|
||||||
|
|
||||||
|
def rust_predicate(self, prec):
|
||||||
|
# type: (int) -> str
|
||||||
|
raise NotImplementedError("rust_predicate is an abstract method")
|
||||||
|
|
||||||
|
|
||||||
class And(Predicate):
|
class And(Predicate):
|
||||||
"""
|
"""
|
||||||
@@ -92,9 +112,11 @@ class And(Predicate):
|
|||||||
precedence = 2
|
precedence = 2
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
|
# type: (*PredNode) -> None
|
||||||
super(And, self).__init__(args)
|
super(And, self).__init__(args)
|
||||||
|
|
||||||
def rust_predicate(self, prec):
|
def rust_predicate(self, prec):
|
||||||
|
# type: (int) -> str
|
||||||
"""
|
"""
|
||||||
Return a Rust expression computing the value of this predicate.
|
Return a Rust expression computing the value of this predicate.
|
||||||
|
|
||||||
@@ -112,6 +134,7 @@ class And(Predicate):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def combine(*args):
|
def combine(*args):
|
||||||
|
# type: (*PredNode) -> PredNode
|
||||||
"""
|
"""
|
||||||
Combine a sequence of predicates, allowing for `None` members.
|
Combine a sequence of predicates, allowing for `None` members.
|
||||||
|
|
||||||
@@ -135,9 +158,11 @@ class Or(Predicate):
|
|||||||
precedence = 1
|
precedence = 1
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
|
# type: (*PredNode) -> None
|
||||||
super(Or, self).__init__(args)
|
super(Or, self).__init__(args)
|
||||||
|
|
||||||
def rust_predicate(self, prec):
|
def rust_predicate(self, prec):
|
||||||
|
# type: (int) -> str
|
||||||
s = ' || '.join(p.rust_predicate(Or.precedence) for p in self.parts)
|
s = ' || '.join(p.rust_predicate(Or.precedence) for p in self.parts)
|
||||||
if prec > Or.precedence:
|
if prec > Or.precedence:
|
||||||
s = '({})'.format(s)
|
s = '({})'.format(s)
|
||||||
@@ -152,9 +177,11 @@ class Not(Predicate):
|
|||||||
precedence = 3
|
precedence = 3
|
||||||
|
|
||||||
def __init__(self, part):
|
def __init__(self, part):
|
||||||
|
# type: (PredNode) -> None
|
||||||
super(Not, self).__init__((part,))
|
super(Not, self).__init__((part,))
|
||||||
|
|
||||||
def rust_predicate(self, prec):
|
def rust_predicate(self, prec):
|
||||||
|
# type: (int) -> str
|
||||||
return '!' + self.parts[0].rust_predicate(Not.precedence)
|
return '!' + self.parts[0].rust_predicate(Not.precedence)
|
||||||
|
|
||||||
|
|
||||||
@@ -168,15 +195,19 @@ class FieldPredicate(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, field, function, args):
|
def __init__(self, field, function, args):
|
||||||
|
# type: (FormatField, str, Sequence[Any]) -> None
|
||||||
|
self.number = None # type: int
|
||||||
self.field = field
|
self.field = field
|
||||||
self.function = function
|
self.function = function
|
||||||
self.args = args
|
self.args = args
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
# type: () -> str
|
||||||
args = (self.field.name,) + tuple(map(str, self.args))
|
args = (self.field.name,) + tuple(map(str, self.args))
|
||||||
return '{}({})'.format(self.function, ', '.join(args))
|
return '{}({})'.format(self.function, ', '.join(args))
|
||||||
|
|
||||||
def predicate_context(self):
|
def predicate_context(self):
|
||||||
|
# type: () -> PredContext
|
||||||
"""
|
"""
|
||||||
This predicate can be evaluated in the context of an instruction
|
This predicate can be evaluated in the context of an instruction
|
||||||
format.
|
format.
|
||||||
@@ -184,9 +215,11 @@ class FieldPredicate(object):
|
|||||||
return self.field.format
|
return self.field.format
|
||||||
|
|
||||||
def predicate_leafs(self, leafs):
|
def predicate_leafs(self, leafs):
|
||||||
|
# type: (Set[PredLeaf]) -> None
|
||||||
leafs.add(self)
|
leafs.add(self)
|
||||||
|
|
||||||
def rust_predicate(self, prec):
|
def rust_predicate(self, prec):
|
||||||
|
# type: (int) -> str
|
||||||
"""
|
"""
|
||||||
Return a string of Rust code that evaluates this predicate.
|
Return a string of Rust code that evaluates this predicate.
|
||||||
"""
|
"""
|
||||||
@@ -210,6 +243,7 @@ class IsSignedInt(FieldPredicate):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, field, width, scale=0):
|
def __init__(self, field, width, scale=0):
|
||||||
|
# type: (FormatField, int, int) -> None
|
||||||
super(IsSignedInt, self).__init__(
|
super(IsSignedInt, self).__init__(
|
||||||
field, 'is_signed_int', (width, scale))
|
field, 'is_signed_int', (width, scale))
|
||||||
self.width = width
|
self.width = width
|
||||||
@@ -232,6 +266,7 @@ class IsUnsignedInt(FieldPredicate):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, field, width, scale=0):
|
def __init__(self, field, width, scale=0):
|
||||||
|
# type: (FormatField, int, int) -> None
|
||||||
super(IsUnsignedInt, self).__init__(
|
super(IsUnsignedInt, self).__init__(
|
||||||
field, 'is_unsigned_int', (width, scale))
|
field, 'is_unsigned_int', (width, scale))
|
||||||
self.width = width
|
self.width = width
|
||||||
|
|||||||
@@ -3,6 +3,13 @@ from __future__ import absolute_import
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from .predicates import Predicate
|
from .predicates import Predicate
|
||||||
|
|
||||||
|
try:
|
||||||
|
from typing import Set, List, Dict, Any, TYPE_CHECKING # noqa
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .predicates import PredLeaf, PredNode # noqa
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Setting(object):
|
class Setting(object):
|
||||||
"""
|
"""
|
||||||
@@ -13,25 +20,26 @@ class Setting(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, doc):
|
def __init__(self, doc):
|
||||||
self.name = None # Assigned later by `extract_names()`.
|
# type: (str) -> None
|
||||||
|
self.name = None # type: str # Assigned later by `extract_names()`.
|
||||||
|
self.number = None # type: int
|
||||||
self.__doc__ = doc
|
self.__doc__ = doc
|
||||||
# Offset of byte in settings vector containing this setting.
|
# Offset of byte in settings vector containing this setting.
|
||||||
self.byte_offset = None
|
self.byte_offset = None # type: int
|
||||||
self.group = SettingGroup.append(self)
|
self.group = SettingGroup.append(self)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
# type: () -> str
|
||||||
return '{}.{}'.format(self.group.name, self.name)
|
return '{}.{}'.format(self.group.name, self.name)
|
||||||
|
|
||||||
def predicate_context(self):
|
def predicate_context(self):
|
||||||
|
# type: () -> SettingGroup
|
||||||
"""
|
"""
|
||||||
Return the context where this setting can be evaluated as a (leaf)
|
Return the context where this setting can be evaluated as a (leaf)
|
||||||
predicate.
|
predicate.
|
||||||
"""
|
"""
|
||||||
return self.group
|
return self.group
|
||||||
|
|
||||||
def predicate_leafs(self, leafs):
|
|
||||||
leafs.add(self)
|
|
||||||
|
|
||||||
|
|
||||||
class BoolSetting(Setting):
|
class BoolSetting(Setting):
|
||||||
"""
|
"""
|
||||||
@@ -42,10 +50,13 @@ class BoolSetting(Setting):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, doc, default=False):
|
def __init__(self, doc, default=False):
|
||||||
|
# type: (str, bool) -> None
|
||||||
super(BoolSetting, self).__init__(doc)
|
super(BoolSetting, self).__init__(doc)
|
||||||
self.default = default
|
self.default = default
|
||||||
|
self.bit_offset = None # type: int
|
||||||
|
|
||||||
def default_byte(self):
|
def default_byte(self):
|
||||||
|
# type: () -> int
|
||||||
"""
|
"""
|
||||||
Get the default value of this setting, as a byte that can be bitwise
|
Get the default value of this setting, as a byte that can be bitwise
|
||||||
or'ed with the other booleans sharing the same byte.
|
or'ed with the other booleans sharing the same byte.
|
||||||
@@ -55,7 +66,12 @@ class BoolSetting(Setting):
|
|||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
def predicate_leafs(self, leafs):
|
||||||
|
# type: (Set[PredLeaf]) -> None
|
||||||
|
leafs.add(self)
|
||||||
|
|
||||||
def rust_predicate(self, prec):
|
def rust_predicate(self, prec):
|
||||||
|
# type: (int) -> str
|
||||||
"""
|
"""
|
||||||
Return the Rust code to compute the value of this setting.
|
Return the Rust code to compute the value of this setting.
|
||||||
|
|
||||||
@@ -74,12 +90,14 @@ class NumSetting(Setting):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, doc, default=0):
|
def __init__(self, doc, default=0):
|
||||||
|
# type: (str, int) -> None
|
||||||
super(NumSetting, self).__init__(doc)
|
super(NumSetting, self).__init__(doc)
|
||||||
assert default == int(default)
|
assert default == int(default)
|
||||||
assert default >= 0 and default <= 255
|
assert default >= 0 and default <= 255
|
||||||
self.default = default
|
self.default = default
|
||||||
|
|
||||||
def default_byte(self):
|
def default_byte(self):
|
||||||
|
# type: () -> int
|
||||||
return self.default
|
return self.default
|
||||||
|
|
||||||
|
|
||||||
@@ -94,12 +112,14 @@ class EnumSetting(Setting):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, doc, *args):
|
def __init__(self, doc, *args):
|
||||||
|
# type: (str, *str) -> None
|
||||||
super(EnumSetting, self).__init__(doc)
|
super(EnumSetting, self).__init__(doc)
|
||||||
assert len(args) > 0, "EnumSetting must have at least one value"
|
assert len(args) > 0, "EnumSetting must have at least one value"
|
||||||
self.values = tuple(str(x) for x in args)
|
self.values = tuple(str(x) for x in args)
|
||||||
self.default = self.values[0]
|
self.default = self.values[0]
|
||||||
|
|
||||||
def default_byte(self):
|
def default_byte(self):
|
||||||
|
# type: () -> int
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
@@ -119,23 +139,25 @@ class SettingGroup(object):
|
|||||||
_current = None # type: SettingGroup
|
_current = None # type: SettingGroup
|
||||||
|
|
||||||
def __init__(self, name, parent=None):
|
def __init__(self, name, parent=None):
|
||||||
|
# type: (str, SettingGroup) -> None
|
||||||
self.name = name
|
self.name = name
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.settings = []
|
self.settings = [] # type: List[Setting]
|
||||||
# Named predicates computed from settings in this group or its
|
# Named predicates computed from settings in this group or its
|
||||||
# parents.
|
# parents.
|
||||||
self.named_predicates = []
|
self.named_predicates = [] # type: List[Predicate]
|
||||||
# All boolean predicates that can be accessed by number. This includes:
|
# All boolean predicates that can be accessed by number. This includes:
|
||||||
# - All boolean settings in this group.
|
# - All boolean settings in this group.
|
||||||
# - All named predicates.
|
# - All named predicates.
|
||||||
# - Added anonymous predicates, see `number_predicate()`.
|
# - Added anonymous predicates, see `number_predicate()`.
|
||||||
# - Added parent predicates that are replicated in this group.
|
# - Added parent predicates that are replicated in this group.
|
||||||
# Maps predicate -> number.
|
# Maps predicate -> number.
|
||||||
self.predicate_number = OrderedDict()
|
self.predicate_number = OrderedDict() # type: OrderedDict[PredNode, int] # noqa
|
||||||
|
|
||||||
self.open()
|
self.open()
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
Open this setting group such that future new settings are added to this
|
Open this setting group such that future new settings are added to this
|
||||||
group.
|
group.
|
||||||
@@ -146,6 +168,7 @@ class SettingGroup(object):
|
|||||||
SettingGroup._current = self
|
SettingGroup._current = self
|
||||||
|
|
||||||
def close(self, globs=None):
|
def close(self, globs=None):
|
||||||
|
# type: (Dict[str, Any]) -> None
|
||||||
"""
|
"""
|
||||||
Close this setting group. This function must be called before opening
|
Close this setting group. This function must be called before opening
|
||||||
another setting group.
|
another setting group.
|
||||||
@@ -170,12 +193,14 @@ class SettingGroup(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def append(setting):
|
def append(setting):
|
||||||
|
# type: (Setting) -> SettingGroup
|
||||||
g = SettingGroup._current
|
g = SettingGroup._current
|
||||||
assert g, "Open a setting group before defining settings."
|
assert g, "Open a setting group before defining settings."
|
||||||
g.settings.append(setting)
|
g.settings.append(setting)
|
||||||
return g
|
return g
|
||||||
|
|
||||||
def number_predicate(self, pred):
|
def number_predicate(self, pred):
|
||||||
|
# type: (PredNode) -> int
|
||||||
"""
|
"""
|
||||||
Make sure that `pred` has an assigned number, and will be included in
|
Make sure that `pred` has an assigned number, and will be included in
|
||||||
this group's bit vector.
|
this group's bit vector.
|
||||||
@@ -200,6 +225,7 @@ class SettingGroup(object):
|
|||||||
return number
|
return number
|
||||||
|
|
||||||
def layout(self):
|
def layout(self):
|
||||||
|
# type: () -> None
|
||||||
"""
|
"""
|
||||||
Compute the layout of the byte vector used to represent this settings
|
Compute the layout of the byte vector used to represent this settings
|
||||||
group.
|
group.
|
||||||
@@ -250,6 +276,7 @@ class SettingGroup(object):
|
|||||||
self.number_predicate(p)
|
self.number_predicate(p)
|
||||||
|
|
||||||
def byte_size(self):
|
def byte_size(self):
|
||||||
|
# type: () -> int
|
||||||
"""
|
"""
|
||||||
Compute the number of bytes required to hold all settings and
|
Compute the number of bytes required to hold all settings and
|
||||||
precomputed predicates.
|
precomputed predicates.
|
||||||
|
|||||||
Reference in New Issue
Block a user