Source code for m2isar.metamodel.utils.scalar_staticness

# SPDX-License-Identifier: Apache-2.0
#
# This file is part of the M2-ISA-R project: https://github.com/tum-ei-eda/M2-ISA-R
#
# Copyright (C) 2022
# Chair of Electrical Design Automation
# Technical University of Munich

"""Transformation functions to determine which vars in a function or instruction
behavior are to be considered static.
"""

import dataclasses
from functools import singledispatchmethod
from typing import Any, cast

from ...metamodel import arch, behav, attribute_info
from .ExprVisitor import ExprVisitor

# pylint: disable=unused-argument

[docs] class VarAccessVisitor(ExprVisitor): """Visitor that determines Variable staticness for behavior expression trees.""" @singledispatchmethod
[docs] def generate(self, expr: behav.BaseNode, context=None): raise NotImplementedError(f"No visit method implemented for type {type(expr).__name__} in {type(expr).__name__}")
@generate.register
[docs] def _(self, expr: behav.Operation, context: attribute_info.AccessContext): statements = [] for stmt in expr.statements: temp = self.generate(stmt, context) if isinstance(temp, list): statements.extend(temp) else: statements.append(temp) return expr
@generate.register def _(self, expr: behav.Block, context): stmts = [self.generate(x, context) for x in expr.statements] valid = [s for s in stmts if s is not None] if not valid: return attribute_info.AccessAttribute.NONE return min(valid) @generate.register def _(self, expr: behav.BinaryOperation, context: attribute_info.AccessContext): left = self.generate(expr.left, context) right = self.generate(expr.right, context) return min(left, right) @generate.register def _(self, expr: behav.SliceOperation, context: attribute_info.AccessContext): expr_result = self.generate(expr.expr, context) left = self.generate(expr.left, context) right = self.generate(expr.right, context) return min(expr_result, left, right) @generate.register def _(self, expr: behav.ConcatOperation, context: attribute_info.AccessContext): left = self.generate(expr.left, context) right = self.generate(expr.right, context) return min(left, right) @generate.register def _(self, expr: behav.Literal, context: attribute_info.AccessContext): return attribute_info.AccessAttribute.READ @generate.register def _(self, expr: behav.Tensor, context: attribute_info.AccessContext): return attribute_info.AccessAttribute.READ @generate.register def _(self, expr: behav.VarDefinition, context: attribute_info.AccessContext): var = cast(Any, expr.var) var.attributes["static"] = attribute_info.AccessAttribute.RW return attribute_info.AccessAttribute.RW @generate.register def _(self, expr: behav.Break, context): return attribute_info.AccessAttribute.READ @generate.register def _(self, expr: behav.Assignment, context: attribute_info.AccessContext): self.generate(expr.target, context) if context.access_is_static != attribute_info.AccessAttribute.NONE or isinstance(expr.target, behav.VarDefinition): expr_static = self.generate(expr.expr, context) if expr_static != attribute_info.AccessAttribute.NONE: expr_static = attribute_info.AccessAttribute.RW else: expr_static = attribute_info.AccessAttribute.NONE if isinstance(expr.target, behav.NamedReference) and isinstance(expr.target.reference, arch.Variable): target_ref = cast(Any, expr.target.reference) target_ref.attributes["static"] &= expr_static if isinstance(expr.target, behav.VarDefinition): target_var = cast(Any, expr.target.var) target_var.attributes["static"] &= expr_static @generate.register def _(self, expr: behav.Conditional, context: attribute_info.AccessContext): conds = [self.generate(x, context) for x in expr.conds] stmt_context = dataclasses.replace(context, access_is_static=min(conds)) _ = [self.generate(x, stmt_context) for x in expr.stmts] @generate.register def _(self, expr: behav.Loop, context: attribute_info.AccessContext): cond = self.generate(expr.cond, context) stmt_context = dataclasses.replace(context, access_is_static=cond) _ = [self.generate(x, stmt_context) for x in expr.stmts] @generate.register def _(self, expr: behav.Ternary, context: attribute_info.AccessContext): cond = self.generate(expr.cond, context) then_expr = self.generate(expr.then_expr, context) else_expr = self.generate(expr.else_expr, context) return min(cond, then_expr, else_expr) @generate.register def _(self, expr: behav.Return, context: attribute_info.AccessContext): if expr.expr is not None: return self.generate(expr.expr, context) return attribute_info.AccessAttribute.RW @generate.register def _(self, expr: behav.UnaryOperation, context: attribute_info.AccessContext): right = self.generate(expr.right, context) return right @generate.register def _(self, expr: behav.NamedReference, context: attribute_info.AccessContext): if isinstance(expr.reference, arch.Variable): return expr.reference.attributes.get("static") static_map = { arch.Memory: attribute_info.AccessAttribute.NONE, arch.RegisterBank: attribute_info.AccessAttribute.NONE, arch.Register: attribute_info.AccessAttribute.NONE, arch.Alias: attribute_info.AccessAttribute.NONE, arch.BitFieldDescr: attribute_info.AccessAttribute.READ, arch.Parameter: attribute_info.AccessAttribute.READ, arch.FnParam: attribute_info.AccessAttribute.READ } return static_map.get(type(expr.reference), attribute_info.AccessAttribute.NONE) @generate.register def _(self, expr: behav.IndexedReference, context: attribute_info.AccessContext): self.generate(expr.index, context) return attribute_info.AccessAttribute.NONE @generate.register def _(self, expr: behav.TypeConv, context: attribute_info.AccessContext): expr_result = self.generate(expr.expr, context) return expr_result @generate.register def _(self, expr: behav.Callable, context: attribute_info.AccessContext): args = [self.generate(arg, context) for arg in expr.args] is_static = bool(expr.ref_or_name.attributes.get("static", False)) args.append(attribute_info.AccessAttribute.READ if is_static else attribute_info.AccessAttribute.NONE) return min(args) @generate.register def _(self, expr: behav.ProcedureCall, context: attribute_info.AccessContext): args = [self.generate(arg, context) for arg in expr.args] is_static = bool(expr.ref_or_name.attributes.get("static", False)) args.append(attribute_info.AccessAttribute.READ if is_static else attribute_info.AccessAttribute.NONE) return min(args) @generate.register def _(self, expr: behav.Group, context: attribute_info.AccessContext): expr_result = self.generate(expr.expr, context) return expr_result