7 from ._mlir_libs._circt._support
import _walk_with_filter
8 from .ir
import Operation
9 from contextlib
import AbstractContextManager
10 from contextvars
import ContextVar
11 from typing
import List
13 _current_backedge_builder = ContextVar(
"current_bb")
22 def __init__(self, module: str, port_names: List[str]):
24 f
"Ports {port_names} unconnected in design module {module}.")
28 """Resolve a Value from a few supported types."""
30 if isinstance(obj, ir.Value):
32 if hasattr(obj,
"result"):
34 if hasattr(obj,
"value"):
40 """A convenient way to use BackedgeBuilder."""
41 if not isinstance(destination, OpOperand):
43 f
"cannot connect to destination of type {type(destination)}. "
47 raise TypeError(f
"cannot connect from source of type {type(source)}")
49 index = destination.index
50 destination.operation.operands[index] = value
51 if destination.backedge_owner
and \
52 index
in destination.backedge_owner.backedges:
53 destination.backedge_owner.backedges[index].erase()
54 del destination.backedge_owner.backedges[index]
58 """Create an MLIR attribute from a Python object for a few common cases."""
59 if isinstance(obj, ir.Attribute):
61 if isinstance(obj, bool):
62 return ir.BoolAttr.get(obj)
63 if isinstance(obj, int):
64 attrTy = ir.IntegerType.get_signless(64)
65 return ir.IntegerAttr.get(attrTy, obj)
66 if isinstance(obj, str):
67 return ir.StringAttr.get(obj)
68 if isinstance(obj, list):
71 return ir.ArrayAttr.get(arr)
75 raise TypeError(f
"Cannot convert type '{type(obj)}' to MLIR attribute")
83 if not isinstance(t, ir.Type):
84 raise TypeError(
"type_to_pytype only accepts MLIR Type objects")
88 if t.__class__ != ir.Type:
91 from .dialects
import esi, hw, seq
93 return ir.IntegerType(t)
101 return hw.ArrayType(t)
105 return hw.StructType(t)
109 return hw.TypeAliasType(t)
113 return hw.InOutType(t)
117 return seq.ClockType(t)
129 raise TypeError(f
"Cannot convert {repr(t)} to python type")
139 if not isinstance(attr, ir.Attribute):
140 raise TypeError(
"attribute_to_var only accepts MLIR Attributes")
144 if attr.__class__ != ir.Attribute
and hasattr(attr,
"value"):
147 from .dialects
import hw, om
149 return ir.BoolAttr(attr).value
153 return ir.IntegerAttr(attr).value
157 return ir.StringAttr(hw.InnerSymAttr(attr).symName).value
161 return ir.StringAttr(attr).value
165 return ir.FlatSymbolRefAttr(attr).value
169 return ir.TypeAttr(attr).value
173 arr = ir.ArrayAttr(attr)
178 dict = ir.DictAttr(attr)
187 ref = hw.InnerRefAttr(attr)
188 return (ir.StringAttr(ref.module).value, ir.StringAttr(ref.name).value)
192 return list(map(attribute_to_var, om.ListAttr(attr)))
200 return int(str(om.OMIntegerAttr(attr)))
204 return om.PathAttr(attr).value
208 raise TypeError(f
"Cannot convert {repr(attr)} to python value")
212 from .dialects
import hw
213 if type(mlir_type)
is ir.Type:
215 if isinstance(mlir_type, hw.TypeAliasType):
229 instance_of: ir.Operation,
230 loc: ir.Location =
None):
231 self.creator: BackedgeBuilder = creator
232 self.
dummy_opdummy_op = ir.Operation.create(
"builtin.unrealized_conversion_cast",
248 if self
in self.creator.edges:
249 self.creator.edges.remove(self)
250 self.
dummy_opdummy_op.operation.erase()
258 bb = _current_backedge_builder.get(
None)
260 raise RuntimeError(
"No backedge builder found in context!")
265 return BackedgeBuilder.current().
_create(*args, **kwargs)
271 instance_of: ir.Operation =
None,
272 loc: ir.Location =
None):
275 self.
edgesedges.add(edge)
281 def __exit__(self, exc_type, exc_value, traceback):
282 if exc_value
is not None:
284 _current_backedge_builder.reset(self.
old_bb_tokenold_bb_token)
286 for edge
in list(self.
edgesedges):
288 msg =
"Backedge: " + edge.port_name +
"\n"
289 if edge.instance_of
is not None:
290 msg +=
"InstanceOf: " + str(edge.instance_of).split(
" {")[0] +
"\n"
291 if edge.op_view
is not None:
292 op = edge.op_view.operation
293 msg +=
"Instance: " + str(op)
294 if edge.loc
is not None:
295 msg +=
"Location: " + str(edge.loc)
300 0, f
"Uninitialized backedges remain in module '{self.circuit_name}'")
305 __slots__ = [
"index",
"operation",
"value",
"backedge_owner"]
308 operation: ir.Operation,
311 backedge_owner=
None):
312 if not isinstance(index, int):
313 raise TypeError(
"Index must be int")
316 if not hasattr(operation,
"operands"):
317 raise TypeError(
"Operation must be have 'operands' attribute")
325 return self.
valuevalue.type
329 """Helper class to incrementally construct an instance of an operation that
330 names its operands and results"""
335 input_port_mapping=None,
338 needs_result_type=False,
341 if input_port_mapping
is None:
342 input_port_mapping = {}
345 if post_args
is None:
349 result_names = self.result_names()
351 for i
in range(len(result_names)):
352 result_indices[result_names[i]] = i
359 operand_names = self.operand_names()
360 for i
in range(len(operand_names)):
361 arg_name = operand_names[i]
362 operand_indices[arg_name] = i
363 if arg_name
in input_port_mapping:
364 value =
get_value(input_port_mapping[arg_name])
368 backedges[i] = backedge
369 operand = backedge.result
370 operand_values.append(operand)
373 if isinstance(data_type, list):
374 operand_values = [operand_values]
382 if data_type
is not None and (needs_result_type
or len(backedges) == 0):
383 pre_args.insert(0, data_type)
385 self.
opviewopview = cls(*pre_args, *operand_values, *post_args, **kwargs)
392 if "operand_indices" in dir(self)
and name
in self.
operand_indicesoperand_indices:
394 value = self.
opviewopview.operands[index]
398 if "result_indices" in dir(self)
and name
in self.
result_indicesresult_indices:
400 value = self.
opviewopview.results[index]
404 if name ==
"attributes":
405 return self.
opviewopview.operation.attributes
408 raise AttributeError(f
"unknown port name {name}")
411 return BackedgeBuilder.create(data_type, arg_name, self)
415 """Get the operation associated with this builder."""
416 return self.
opviewopview.operation
424 op_names_identifiers = [name.OPERATION_NAME
for name
in op_views]
425 return _walk_with_filter(operation, op_names_identifiers, callback,
def __init__(self, creator, ir.Type type, str backedge_name, op_view, ir.Operation instance_of, ir.Location loc=None)
def __init__(self, str circuit_name="")
def _create(self, ir.Type type, str port_name, op_view, ir.Operation instance_of=None, ir.Location loc=None)
def __exit__(self, exc_type, exc_value, traceback)
def create(*args, **kwargs)
def create_default_value(self, index, data_type, arg_name)
def __init__(self, cls, data_type=None, input_port_mapping=None, pre_args=None, post_args=None, needs_result_type=False, **kwargs)
def __getattr__(self, name)
def __init__(self, ir.Operation operation, int index, value, backedge_owner=None)
def __init__(self, str module, List[str] port_names)
Bundles represent a collection of channels.
Channels are the basic communication primitives.
def connect(destination, source)
ir.Attribute var_to_attribute(obj, bool none_on_fail=False)
def get_self_or_inner(mlir_type)
def walk_with_filter(Operation operation, List[ir.OpView] op_views, callback, walk_order)
ir.Type type_to_pytype(t)
def attribute_to_var(attr)