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)
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)))
198 return int(str(om.OMIntegerAttr(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()
255 bb = _current_backedge_builder.get(
None)
257 raise RuntimeError(
"No backedge builder found in context!")
262 return BackedgeBuilder.current().
_create(*args, **kwargs)
268 instance_of: ir.Operation =
None,
269 loc: ir.Location =
None):
272 self.
edgesedges.add(edge)
278 def __exit__(self, exc_type, exc_value, traceback):
279 if exc_value
is not None:
281 _current_backedge_builder.reset(self.
old_bb_tokenold_bb_token)
283 for edge
in list(self.
edgesedges):
285 msg =
"Backedge: " + edge.port_name +
"\n"
286 if edge.instance_of
is not None:
287 msg +=
"InstanceOf: " + str(edge.instance_of).split(
" {")[0] +
"\n"
288 if edge.op_view
is not None:
289 op = edge.op_view.operation
290 msg +=
"Instance: " + str(op)
295 0, f
"Uninitialized backedges remain in module '{self.circuit_name}'")
300 __slots__ = [
"index",
"operation",
"value",
"backedge_owner"]
303 operation: ir.Operation,
306 backedge_owner=
None):
307 if not isinstance(index, int):
308 raise TypeError(
"Index must be int")
311 if not hasattr(operation,
"operands"):
312 raise TypeError(
"Operation must be have 'operands' attribute")
320 return self.
valuevalue.type
324 """Helper class to incrementally construct an instance of an operation that
325 names its operands and results"""
330 input_port_mapping=None,
333 needs_result_type=False,
336 if input_port_mapping
is None:
337 input_port_mapping = {}
340 if post_args
is None:
344 result_names = self.result_names()
346 for i
in range(len(result_names)):
347 result_indices[result_names[i]] = i
354 operand_names = self.operand_names()
355 for i
in range(len(operand_names)):
356 arg_name = operand_names[i]
357 operand_indices[arg_name] = i
358 if arg_name
in input_port_mapping:
359 value =
get_value(input_port_mapping[arg_name])
363 backedges[i] = backedge
364 operand = backedge.result
365 operand_values.append(operand)
368 if isinstance(data_type, list):
369 operand_values = [operand_values]
377 if data_type
is not None and (needs_result_type
or len(backedges) == 0):
378 pre_args.insert(0, data_type)
380 self.
opviewopview = cls(*pre_args, *operand_values, *post_args, **kwargs)
387 if "operand_indices" in dir(self)
and name
in self.
operand_indicesoperand_indices:
389 value = self.
opviewopview.operands[index]
393 if "result_indices" in dir(self)
and name
in self.
result_indicesresult_indices:
395 value = self.
opviewopview.results[index]
399 if name ==
"attributes":
400 return self.
opviewopview.operation.attributes
403 raise AttributeError(f
"unknown port name {name}")
406 return BackedgeBuilder.create(data_type, arg_name, self)
410 """Get the operation associated with this builder."""
411 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 __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)
ir.Type type_to_pytype(t)
def attribute_to_var(attr)