CIRCT  20.0.0git
om.py
Go to the documentation of this file.
1 # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2 # See https://llvm.org/LICENSE.txt for license information.
3 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4 
5 from __future__ import annotations
6 
7 from ._om_ops_gen import *
8 from .._mlir_libs._circt._om import AnyType, Evaluator as BaseEvaluator, Object as BaseObject, List as BaseList, Tuple as BaseTuple, Map as BaseMap, BasePath as BaseBasePath, BasePathType, Path, PathType, ClassType, ReferenceAttr, ListAttr, ListType, MapAttr, OMIntegerAttr
9 
10 from ..ir import Attribute, Diagnostic, DiagnosticSeverity, Module, StringAttr, IntegerAttr, IntegerType
11 from ..support import attribute_to_var, var_to_attribute
12 
13 import sys
14 import logging
15 from dataclasses import fields
16 from typing import TYPE_CHECKING, Any, Sequence, TypeVar
17 
18 if TYPE_CHECKING:
19  from _typeshed.stdlib.dataclass import DataclassInstance
20 
21 
22 # Wrap a base mlir object with high-level object.
23 def wrap_mlir_object(value):
24  # For primitives, return the Python value directly.
25  if isinstance(value, (int, float, str, bool, tuple, list, dict)):
26  return value
27 
28  if isinstance(value, BaseList):
29  return List(value)
30 
31  if isinstance(value, BaseTuple):
32  return Tuple(value)
33 
34  if isinstance(value, BaseMap):
35  return Map(value)
36 
37  if isinstance(value, BaseBasePath):
38  return BasePath(value)
39 
40  if isinstance(value, Path):
41  return value
42 
43  # For objects, return an Object, wrapping the base implementation.
44  assert isinstance(value, BaseObject)
45  return Object(value)
46 
47 
48 def om_var_to_attribute(obj, none_on_fail: bool = False) -> ir.Attrbute:
49  if isinstance(obj, int):
50  return OMIntegerAttr.get(IntegerAttr.get(IntegerType.get_signless(64), obj))
51  return var_to_attribute(obj, none_on_fail)
52 
53 
55  # Check if the value is any of our container or custom types.
56  if isinstance(value, List):
57  return BaseList(value)
58 
59  if isinstance(value, Tuple):
60  return BaseTuple(value)
61 
62  if isinstance(value, Map):
63  return BaseMap(value)
64 
65  if isinstance(value, BasePath):
66  return BaseBasePath(value)
67 
68  if isinstance(value, Path):
69  return value
70 
71  if isinstance(value, Object):
72  return BaseObject(value)
73 
74  # Otherwise, it must be a primitive, so just return it.
75  return value
76 
77 
78 class List(BaseList):
79 
80  def __init__(self, obj: BaseList) -> None:
81  super().__init__(obj)
82 
83  def __getitem__(self, i):
84  val = super().__getitem__(i)
85  return wrap_mlir_object(val)
86 
87  # Support iterating over a List by yielding its elements.
88  def __iter__(self):
89  for i in range(0, self.__len__()):
90  yield self.__getitem____getitem__(i)
91 
92 
94 
95  def __init__(self, obj: BaseTuple) -> None:
96  super().__init__(obj)
97 
98  def __getitem__(self, i):
99  val = super().__getitem__(i)
100  return wrap_mlir_object(val)
101 
102  # Support iterating over a Tuple by yielding its elements.
103  def __iter__(self):
104  for i in range(0, self.__len__()):
105  yield self.__getitem____getitem__(i)
106 
107 
108 class Map(BaseMap):
109 
110  def __init__(self, obj: BaseMap) -> None:
111  super().__init__(obj)
112 
113  def __getitem__(self, key):
114  val = super().__getitem__(key)
115  return wrap_mlir_object(val)
116 
117  def keys(self):
118  return [wrap_mlir_object(arg) for arg in super().keys()]
119 
120  def items(self):
121  for i in self:
122  yield i
123 
124  def values(self):
125  for (_, v) in self:
126  yield v
127 
128  # Support iterating over a Map
129  def __iter__(self):
130  for i in super().keys():
131  yield (wrap_mlir_object(i), self.__getitem____getitem__(i))
132 
133 
135 
136  @staticmethod
137  def get_empty(context=None) -> "BasePath":
138  return BasePath(BaseBasePath.get_empty(context))
139 
140 
141 # Define the Object class by inheriting from the base implementation in C++.
143 
144  def __init__(self, obj: BaseObject) -> None:
145  super().__init__(obj)
146 
147  def __getattr__(self, name: str):
148  # Call the base method to get a field.
149  field = super().__getattr__(name)
150  return wrap_mlir_object(field)
151 
152  def get_field_loc(self, name: str):
153  # Call the base method to get the loc.
154  loc = super().get_field_loc(name)
155  return loc
156 
157  # Support iterating over an Object by yielding its fields.
158  def __iter__(self):
159  for name in self.field_names:
160  yield (name, getattr(self, name))
161 
162 
163 # Define the Evaluator class by inheriting from the base implementation in C++.
165 
166  def __init__(self, mod: Module) -> None:
167  """Instantiate an Evaluator with a Module."""
168 
169  # Call the base constructor.
170  super().__init__(mod)
171 
172  # Set up logging for diagnostics.
173  logging.basicConfig(
174  format="[%(asctime)s] %(name)s (%(levelname)s) %(message)s",
175  datefmt="%Y-%m-%d %H:%M:%S",
176  level=logging.INFO,
177  stream=sys.stdout,
178  )
179  self._logger_logger = logging.getLogger("Evaluator")
180 
181  # Attach our Diagnostic handler.
182  mod.context.attach_diagnostic_handler(self._handle_diagnostic_handle_diagnostic)
183 
184  def instantiate(self, cls: str, *args: Any) -> Object:
185  """Instantiate an Object with a class name and actual parameters."""
186 
187  # Convert the class name and actual parameters to Attributes within the
188  # Evaluator's context.
189  with self.module.context:
190  # Get the class name from the class name.
191  class_name = StringAttr.get(cls)
192 
193  # Get the actual parameter Values from the supplied variadic
194  # arguments.
195  actual_params = [unwrap_python_object(arg) for arg in args]
196 
197  # Call the base instantiate method.
198  obj = super().instantiate(class_name, actual_params)
199 
200  # Return the Object, wrapping the base implementation.
201  return Object(obj)
202 
203  def _handle_diagnostic(self, diagnostic: Diagnostic) -> bool:
204  """Handle MLIR Diagnostics by logging them."""
205 
206  # Log the diagnostic message at the appropriate level.
207  if diagnostic.severity == DiagnosticSeverity.ERROR:
208  self._logger_logger.error(diagnostic.message)
209  elif diagnostic.severity == DiagnosticSeverity.WARNING:
210  self._logger_logger.warning(diagnostic.message)
211  else:
212  self._logger_logger.info(diagnostic.message)
213 
214  # Log any diagnostic notes at the info level.
215  for note in diagnostic.notes:
216  self._logger_logger.info(str(note))
217 
218  # Flush the stdout stream to ensure logs appear when expected.
219  sys.stdout.flush()
220 
221  # Return True, indicating this diagnostic has been fully handled.
222  return True
"BasePath" get_empty(context=None)
Definition: om.py:137
None __init__(self, Module mod)
Definition: om.py:166
bool _handle_diagnostic(self, Diagnostic diagnostic)
Definition: om.py:203
Object instantiate(self, str cls, *Any args)
Definition: om.py:184
Definition: om.py:78
def __getitem__(self, i)
Definition: om.py:83
def __iter__(self)
Definition: om.py:88
None __init__(self, BaseList obj)
Definition: om.py:80
Definition: om.py:108
None __init__(self, BaseMap obj)
Definition: om.py:110
def keys(self)
Definition: om.py:117
def items(self)
Definition: om.py:120
def __getitem__(self, key)
Definition: om.py:113
def __iter__(self)
Definition: om.py:129
def values(self)
Definition: om.py:124
Definition: om.py:142
None __init__(self, BaseObject obj)
Definition: om.py:144
def __iter__(self)
Definition: om.py:158
def __getattr__(self, str name)
Definition: om.py:147
def get_field_loc(self, str name)
Definition: om.py:152
Definition: om.py:93
def __getitem__(self, i)
Definition: om.py:98
def __iter__(self)
Definition: om.py:103
None __init__(self, BaseTuple obj)
Definition: om.py:95
ir.Attribute var_to_attribute(obj, bool none_on_fail=False)
Definition: support.py:57
def wrap_mlir_object(value)
Definition: om.py:23
def unwrap_python_object(value)
Definition: om.py:54
ir.Attrbute om_var_to_attribute(obj, bool none_on_fail=False)
Definition: om.py:48