7 from contextlib
import AbstractContextManager
8 from contextvars
import ContextVar
9 from typing
import List
11 _current_backedge_builder = ContextVar(
"current_bb")
20 def __init__(self, module: str, port_names: List[str]):
22 f
"Ports {port_names} unconnected in design module {module}.")
26 """Resolve a Value from a few supported types."""
28 if isinstance(obj, ir.Value):
30 if hasattr(obj,
"result"):
32 if hasattr(obj,
"value"):
38 """A convenient way to use BackedgeBuilder."""
39 if not isinstance(destination, OpOperand):
41 f
"cannot connect to destination of type {type(destination)}. "
45 raise TypeError(f
"cannot connect from source of type {type(source)}")
47 index = destination.index
48 destination.operation.operands[index] = value
49 if destination.backedge_owner
and \
50 index
in destination.backedge_owner.backedges:
51 destination.backedge_owner.backedges[index].erase()
52 del destination.backedge_owner.backedges[index]
56 """Create an MLIR attribute from a Python object for a few common cases."""
57 if isinstance(obj, ir.Attribute):
59 if isinstance(obj, bool):
60 return ir.BoolAttr.get(obj)
61 if isinstance(obj, int):
62 attrTy = ir.IntegerType.get_signless(64)
63 return ir.IntegerAttr.get(attrTy, obj)
64 if isinstance(obj, str):
65 return ir.StringAttr.get(obj)
66 if isinstance(obj, list):
69 return ir.ArrayAttr.get(arr)
73 raise TypeError(f
"Cannot convert type '{type(obj)}' to MLIR attribute")
81 if not isinstance(t, ir.Type):
82 raise TypeError(
"type_to_pytype only accepts MLIR Type objects")
86 if t.__class__ != ir.Type:
89 from .dialects
import esi, hw, seq
91 return ir.IntegerType(t)
99 return hw.ArrayType(t)
103 return hw.StructType(t)
107 return hw.TypeAliasType(t)
111 return hw.InOutType(t)
115 return seq.ClockType(t)
119 return esi.ChannelType(t)
127 raise TypeError(f
"Cannot convert {repr(t)} to python type")
137 if not isinstance(attr, ir.Attribute):
138 raise TypeError(
"attribute_to_var only accepts MLIR Attributes")
142 if attr.__class__ != ir.Attribute
and hasattr(attr,
"value"):
145 from .dialects
import hw, om
147 return ir.BoolAttr(attr).value
151 return ir.IntegerAttr(attr).value
155 return ir.StringAttr(hw.InnerSymAttr(attr).symName).value
159 return ir.StringAttr(attr).value
163 return ir.FlatSymbolRefAttr(attr).value
167 return ir.TypeAttr(attr).value
171 arr = ir.ArrayAttr(attr)
176 dict = ir.DictAttr(attr)
185 ref = hw.InnerRefAttr(attr)
186 return (ir.StringAttr(ref.module).value, ir.StringAttr(ref.name).value)
190 return list(map(attribute_to_var, om.ListAttr(attr)))
202 return om.PathAttr(attr).value
206 raise TypeError(f
"Cannot convert {repr(attr)} to python value")
210 from .dialects
import hw
211 if type(mlir_type)
is ir.Type:
213 if isinstance(mlir_type, hw.TypeAliasType):
227 instance_of: ir.Operation,
228 loc: ir.Location =
None):
229 self.creator: BackedgeBuilder = creator
230 self.
dummy_opdummy_op = ir.Operation.create(
"builtin.unrealized_conversion_cast",
245 if self
in self.creator.edges:
246 self.creator.edges.remove(self)
247 self.
dummy_opdummy_op.operation.erase()
254 bb = _current_backedge_builder.get(
None)
256 raise RuntimeError(
"No backedge builder found in context!")
261 return BackedgeBuilder.current().
_create(*args, **kwargs)
267 instance_of: ir.Operation =
None,
268 loc: ir.Location =
None):
271 self.
edgesedges.add(edge)
277 def __exit__(self, exc_type, exc_value, traceback):
278 if exc_value
is not None:
280 _current_backedge_builder.reset(self.
old_bb_tokenold_bb_token)
282 for edge
in list(self.
edgesedges):
284 msg =
"Backedge: " + edge.port_name +
"\n"
285 if edge.instance_of
is not None:
286 msg +=
"InstanceOf: " + str(edge.instance_of).split(
" {")[0] +
"\n"
287 if edge.op_view
is not None:
288 op = edge.op_view.operation
289 msg +=
"Instance: " + str(op)
293 errors.insert(0,
"Uninitialized backedges remain in circuit!")
298 __slots__ = [
"index",
"operation",
"value",
"backedge_owner"]
301 operation: ir.Operation,
304 backedge_owner=
None):
305 if not isinstance(index, int):
306 raise TypeError(
"Index must be int")
309 if not hasattr(operation,
"operands"):
310 raise TypeError(
"Operation must be have 'operands' attribute")
318 return self.
valuevalue.type
322 """Helper class to incrementally construct an instance of an operation that
323 names its operands and results"""
328 input_port_mapping=None,
331 needs_result_type=False,
334 if input_port_mapping
is None:
335 input_port_mapping = {}
338 if post_args
is None:
342 result_names = self.result_names()
344 for i
in range(len(result_names)):
345 result_indices[result_names[i]] = i
352 operand_names = self.operand_names()
353 for i
in range(len(operand_names)):
354 arg_name = operand_names[i]
355 operand_indices[arg_name] = i
356 if arg_name
in input_port_mapping:
357 value =
get_value(input_port_mapping[arg_name])
361 backedges[i] = backedge
362 operand = backedge.result
363 operand_values.append(operand)
366 if isinstance(data_type, list):
367 operand_values = [operand_values]
375 if data_type
is not None and (needs_result_type
or len(backedges) == 0):
376 pre_args.insert(0, data_type)
378 self.
opviewopview = cls(*pre_args, *operand_values, *post_args, **kwargs)
385 if "operand_indices" in dir(self)
and name
in self.
operand_indicesoperand_indices:
387 value = self.
opviewopview.operands[index]
391 if "result_indices" in dir(self)
and name
in self.
result_indicesresult_indices:
393 value = self.
opviewopview.results[index]
397 if name ==
"attributes":
398 return self.
opviewopview.operation.attributes
401 raise AttributeError(f
"unknown port name {name}")
404 return BackedgeBuilder.create(data_type, arg_name, self)
408 """Get the operation associated with this builder."""
409 return self.
opviewopview.operation
def __init__(self, creator, ir.Type type, str backedge_name, op_view, ir.Operation instance_of, ir.Location loc=None)
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.
def connect(destination, source)
ir.Attribute var_to_attribute(obj, bool none_on_fail=False)
def get_self_or_inner(mlir_type)
ir.Type type_to_pytype(t)
def attribute_to_var(attr)