[PyCDE] Implement new DynamicInstance operation methodology (#2683)

This commit is contained in:
John Demme 2022-02-28 21:30:35 +01:00 committed by GitHub
parent 61b2eda047
commit 050063d299
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 255 additions and 193 deletions

View File

@ -17,7 +17,6 @@ class AppID:
through hierarchy changes."""
def __init__(self, *appid: Tuple[str]):
assert len(appid) > 0
self._parts = list()
for p in appid:
assert isinstance(p, str)
@ -25,6 +24,8 @@ class AppID:
@property
def head(self) -> str:
if len(self._parts) == 0:
return ""
return self._parts[0]
@property
@ -40,7 +41,7 @@ class AppID:
return AppID(*self._parts, part)
class AppIDIndex(dict):
class AppIDIndex(list):
"""Model the AppID hierarchy. Provides the ability to attach attributes to
AppIDs rather than instances, to get applied once the design is fully
generated."""
@ -57,7 +58,7 @@ class AppIDIndex(dict):
return self._children[appid.head].lookup(appid.tail)
def add_attribute(self, attr: Tuple[str, ir.Attribute]) -> None:
self[attr[0]] = attr[1]
self.append(attr)
def find_unused(self) -> Union[AppIDIndex, Dict[str, AppIDIndex]]:
if not self._used and len(self) > 0:
@ -76,7 +77,7 @@ class AppIDIndex(dict):
def _visit(idx, inst: Instance):
attrs = idx.lookup(inst.appid)
attrs._used = True
for (akey, attr) in attrs.items():
inst._attach_attribute(akey, attr)
for attr in attrs:
inst._attach_attribute(attr)
return lambda i, idx=self: _visit(idx, i)

View File

@ -19,5 +19,5 @@ def placement(subpath: Union[str, list[str]],
num: int = 0):
if isinstance(subpath, list):
subpath = "|".join(subpath)
loc = PhysLocation(devtype, x, y, num, subpath)
return (f"loc:{subpath}", loc)
loc = PhysLocation(devtype, x, y, num)
return (subpath, loc)

View File

@ -7,7 +7,7 @@ import typing
from circt.dialects import msft
from mlir.ir import StringAttr, ArrayAttr, FlatSymbolRefAttr
from mlir.ir import StringAttr, ArrayAttr, FlatSymbolRefAttr, Location
PrimitiveType = msft.PrimitiveType
@ -19,8 +19,7 @@ class PhysLocation:
prim_type: typing.Union[str, PrimitiveType],
x: int,
y: int,
num: typing.Union[int, None] = None,
sub_path: str = ""):
num: typing.Union[int, None] = None):
if isinstance(prim_type, str):
prim_type = getattr(PrimitiveType, prim_type)
@ -32,7 +31,7 @@ class PhysLocation:
assert isinstance(x, int)
assert isinstance(y, int)
assert isinstance(num, int)
self._loc = msft.PhysLocationAttr.get(prim_type, x, y, num, sub_path)
self._loc = msft.PhysLocationAttr.get(prim_type, x, y, num)
def __str__(self) -> str:
loc = self._loc
@ -127,6 +126,10 @@ class PlacementDB:
subpath = ""
self._db.add_placement(loc._loc, path, subpath, entity._entity_extern)
def place(self, inst, loc: PhysLocation, subpath: str = ""):
self._db.place(inst._dyn_inst.operation, loc._loc, subpath,
Location.current)
class EntityExtern:
__slots__ = ["_entity_extern"]

View File

@ -5,162 +5,213 @@
from __future__ import annotations
from typing import Union
from pycde.devicedb import PhysLocation, PrimitiveDB, PlacementDB
from numpy import isin
from .appid import AppID
from circt.dialects import hw, msft, seq
from circt.dialects import hw, msft
import mlir.ir as ir
import mlir.ir as _ir
# TODO: bug: holds an Operation* without releasing it. Use a level of
# indirection.
class Instance:
"""Represents a _specific_ instance, unique in a design. This is in contrast
to a module instantiation within another module."""
import pycde.system as system
import pycde.module as module
__slots__ = ["parent", "_ref", "_root", "_child_cache", "_spec_mod"]
global_ref_counter = 0
def __init__(self,
module: type,
instOp: Union[msft.InstanceOp, seq.CompRegOp],
parent: Instance,
sys: system.System,
primdb: PrimitiveDB = None):
assert module is not None
assert instOp is None or (isinstance(instOp, msft.InstanceOp) or
isinstance(instOp, seq.CompRegOp))
self.module = module
self.instOp = instOp
@staticmethod
def _get(root: RootInstance,
parent: Instance,
spec_mod: module._SpecializedModule = None):
self = Instance()
self._root = root
self.parent = parent
if parent is None:
self.placedb = PlacementDB(sys._get_circt_mod(module), primdb)
assert isinstance(sys, Instance.system.System)
self.sys = sys
self._child_cache = None
self._spec_mod = spec_mod
return self
@property
def path(self) -> list[Instance]:
if self.parent is None:
return []
return self.parent.path + [self]
@property
def root_module(self) -> hw.HWModuleOp:
if self.parent is None:
return self.module
return self.parent.root_module
@property
def root_instance(self) -> Instance:
if self.parent is None:
return self
return self.parent.root_instance
return self._root
@property
def path_attr(self) -> ir.ArrayAttr:
module_names = [self.sys._get_module_symbol(self.root_module)] + [
self.sys._get_module_symbol(instance.module)
for instance in self.path[:-1]
]
modules = [ir.StringAttr.get(name) for name in module_names]
instances = [instance.name_attr for instance in self.path]
def _dyn_inst(self) -> msft.DynamicInstanceOp:
"""Return the raw CIRCT op backing this Instance.
DANGEROUS! If used, take care to not hold on to the result object."""
return self._root._create_or_get_dyn_inst(self)
@property
def _module_symbol(self):
assert self._spec_mod is not None
return self._root._system._get_module_symbol(self._spec_mod)
def _path_attr(self) -> _ir.ArrayAttr:
module_names = [self._root._module_symbol] + \
[instance._module_symbol for instance in self.path[:-1]]
modules = [_ir.StringAttr.get(name) for name in module_names]
instances = [instance._name_attr for instance in self.path]
inner_refs = [hw.InnerRefAttr.get(m, i) for m, i in zip(modules, instances)]
return ir.ArrayAttr.get(inner_refs)
return _ir.ArrayAttr.get(inner_refs)
@property
def name(self):
return self.name_attr.value
return str(self._name_attr).strip('"')
@property
def name_attr(self):
return ir.StringAttr(self.instOp.sym_name)
@property
def is_root(self):
return self.parent is None
def _name_attr(self):
return self._root._get_static_op(self).attributes["sym_name"]
@property
def appid(self):
return AppID(*[i.name for i in self.path])
@classmethod
def get_global_ref_symbol(cls):
counter = cls.global_ref_counter
cls.global_ref_counter += 1
return ir.StringAttr.get("ref" + str(counter))
def __repr__(self):
path_names = map(lambda i: i.name, self.path)
return "<instance: [" + ", ".join(path_names) + "]>"
def children(self):
if self._child_cache is not None:
return self._child_cache
if self._spec_mod is None:
return []
symbols_in_mod = self._root._get_sym_ops_in_module(self._spec_mod)
children = [self._root._create_instance(self, op) for op in symbols_in_mod]
# TODO: make these weak refs
self._child_cache = children
return children
def walk(self, callback):
"""Descend the instance hierarchy, calling back on each instance."""
circt_mod = self.sys._get_circt_mod(self.module)
if isinstance(circt_mod, msft.MSFTModuleExternOp):
return
for op in circt_mod.entry_block:
if isinstance(op, seq.CompRegOp):
inst = Instance(circt_mod, op, self, self.sys)
callback(inst)
continue
callback(self)
for child in self.children():
child.walk(callback)
if not isinstance(op, msft.InstanceOp):
continue
def _attach_attribute(self, attr):
import pycde.devicedb as devdb
assert "moduleName" in op.attributes
tgt_modname = ir.FlatSymbolRefAttr(op.attributes["moduleName"]).value
tgt_mod = self.sys._get_symbol_module(tgt_modname).modcls
assert tgt_mod is not None
inst = Instance(tgt_mod, op, self, self.sys)
callback(inst)
inst.walk(callback)
def _attach_attribute(self, sub_path: str, attr: ir.Attribute):
if isinstance(attr, PhysLocation):
attr = attr._loc
db = self.root_instance.placedb._db
rc = db.add_placement(attr, self.path_attr, sub_path, self.instOp.operation)
if not rc:
raise ValueError("Failed to place")
# Create a global ref to this path.
global_ref_symbol = Instance.get_global_ref_symbol()
path_attr = self.path_attr
with ir.InsertionPoint(self.sys.mod.body):
global_ref = hw.GlobalRefOp(global_ref_symbol, path_attr)
# Attach the attribute to the global ref.
global_ref.attributes["loc:" + sub_path] = attr
# Add references to the global ref for each instance through the hierarchy.
for instance in self.path:
# Find any existing global refs.
if "circt.globalRef" in instance.instOp.attributes:
global_refs = [
ref for ref in ir.ArrayAttr(
instance.instOp.attributes["circt.globalRef"])
]
else:
global_refs = []
# Add the new global ref.
global_refs.append(hw.GlobalRefAttr.get(global_ref_symbol))
global_refs_attr = ir.ArrayAttr.get(global_refs)
instance.instOp.attributes["circt.globalRef"] = global_refs_attr
# Set the expected inner_sym attribute on the instance to abide by the
# global ref contract.
instance.instOp.attributes["inner_sym"] = instance.name_attr
assert isinstance(attr, tuple), "Only (subpath, loc) are supported"
if isinstance(attr[1], devdb.PhysLocation):
self._root._placedb.place(self, attr[1], attr[0])
else:
assert False
def place(self,
subpath: Union[str, list[str]],
devtype: msft.PrimitiveType,
x: int,
y: int,
num: int = 0):
num: int = 0,
subpath: Union[str, list[str]] = ""):
import pycde.devicedb as devdb
if isinstance(subpath, list):
subpath = "|".join(subpath)
loc = msft.PhysLocationAttr.get(devtype, x, y, num, subpath)
self._attach_attribute(subpath, loc)
loc = devdb.PhysLocation(devtype, x, y, num)
self._root.placedb.place(self, loc, subpath)
class RootInstance(Instance):
"""
A root of an instance hierarchy starting at top-level 'module'.
Provides:
- The placement database.
- A (necessary) level of indirection into CIRCT IR.
"""
import pycde.system as system
import pycde.devicedb as devdb
from .module import _SpecializedModule
__slots__ = [
"_module", "_placedb", "_subsymbol_cache", "_inst_to_static_op_cache",
"_inst_to_dyn_op_cache", "_system"
]
# TODO: Support rebuilding the caches.
@staticmethod
def _get(module: _SpecializedModule, sys: system.System):
self = RootInstance()
self._spec_mod = module
self._system = sys
self._placedb = None
self._root = self
self._subsymbol_cache = {}
self._inst_to_static_op_cache = {self: sys._get_circt_mod(module)}
self._inst_to_dyn_op_cache = {}
self._child_cache = None
return self
def _clear_cache(self):
"""Clear out all of the Operation* references."""
self._subsymbol_cache = None
self._inst_to_static_op_cache = None
self._inst_to_dyn_op_cache = None
self._child_cache = None
def createdb(self, primdb: devdb.PrimitiveDB = None):
import pycde.devicedb as devdb
self._placedb = devdb.PlacementDB(
self._system._get_circt_mod(self._spec_mod), primdb)
def _get_static_op(self, inst: Instance):
# We don't support cache rebuilds yet.
assert self._inst_to_static_op_cache is not None
assert inst in self._inst_to_static_op_cache
return self._inst_to_static_op_cache[inst]
@property
def name(self):
return "<<root>>"
@property
def _name_attr(self):
return None
@property
def placedb(self):
if self._placedb is None:
raise Exception("Must `createdb` first")
return self._placedb
@property
def path(self) -> list[Instance]:
return []
def _create_or_get_dyn_inst(self, inst: Instance):
# We don't support cache rebuilding yet
assert self._inst_to_dyn_op_cache is not None
if inst not in self._inst_to_dyn_op_cache:
with self._system._get_ip():
self._inst_to_dyn_op_cache[inst] = \
msft.DynamicInstanceOp.create(inst._path_attr())
return self._inst_to_dyn_op_cache[inst]
def _create_instance(self, parent: Instance, static_op: _ir.Operation):
import circt.dialects.msft as circtms
spec_mod = None
if isinstance(static_op, circtms.InstanceOp):
spec_mod = self._system._get_symbol_module(static_op.moduleName)
inst = Instance._get(self, parent, spec_mod)
self._inst_to_static_op_cache[inst] = static_op
return inst
def _get_sym_ops_in_module(self, instance_module: _SpecializedModule):
if instance_module not in self._subsymbol_cache:
circt_mod = self._system._get_circt_mod(instance_module)
if isinstance(circt_mod, msft.MSFTModuleExternOp):
return []
def has_symbol(op):
return "sym_name" in op.attributes
self._subsymbol_cache[instance_module] = \
[op for op in circt_mod.entry_block if has_symbol(op)]
return self._subsymbol_cache[instance_module]

View File

@ -6,7 +6,7 @@ from pycde.devicedb import EntityExtern, PrimitiveDB, PhysicalRegion
from .module import _SpecializedModule
from .pycde_types import types
from .instance import Instance
from .instance import Instance, RootInstance
import mlir
import mlir.ir as ir
@ -35,12 +35,12 @@ class System:
__slots__ = [
"mod", "modules", "name", "passed", "_module_symbols", "_symbol_modules",
"_old_system_token", "_symbols", "_generate_queue", "_primdb",
"_output_directory", "files"
"_old_system_token", "_symbols", "_generate_queue", "_output_directory",
"files", "_instance_cache"
]
PASSES = """
msft-partition,
msft-lower-instances, msft-partition,
lower-msft-to-hw{{verilog-file={verilog_file}}},
lower-seq-to-sv, hw.module(prettify-verilog), hw.module(hw-cleanup),
msft-export-tcl{{tops={tops} tcl-file={tcl_file}}}
@ -48,7 +48,6 @@ class System:
def __init__(self,
modules,
primdb: PrimitiveDB = None,
name: str = "PyCDESystem",
output_directory: str = None):
self.passed = False
@ -59,10 +58,9 @@ class System:
self._symbol_modules: dict[str, _SpecializedModule] = {}
self._symbols: typing.Set[str] = None
self._generate_queue = []
self._instance_cache: dict[_SpecializedModule, RootInstance] = {}
self.files: typing.Set[str] = set()
self._primdb = primdb
if output_directory is None:
output_directory = os.path.join(os.getcwd(), self.name)
self._output_directory = output_directory
@ -73,6 +71,10 @@ class System:
def _get_ip(self):
return ir.InsertionPoint(self.mod.body)
@staticmethod
def set_debug():
ir._GlobalDebug.flag = True
# TODO: Return a read-only proxy.
@property
def symbols(self) -> typing.Dict[str, ir.Operation]:
@ -129,6 +131,8 @@ class System:
def _get_symbol_module(self, symbol):
"""Get the _SpecializedModule for a symbol."""
if isinstance(symbol, ir.FlatSymbolRefAttr):
symbol = symbol.value
return self._symbol_modules[symbol]
def _get_module_symbol(self, spec_mod):
@ -201,7 +205,10 @@ class System:
return len(self._generate_queue)
def get_instance(self, mod_cls: object) -> Instance:
return Instance(mod_cls, None, None, self, self._primdb)
mod = mod_cls._pycde_mod
if mod not in self._instance_cache:
self._instance_cache[mod] = RootInstance._get(mod, self)
return self._instance_cache[mod]
class DevNull:

View File

@ -51,7 +51,7 @@ class Value:
clk=clk,
reset=rst,
name=name,
inner_sym=name)
sym_name=name)
@property
def _namehint_attrname(self):

View File

@ -26,7 +26,7 @@ class CompReg:
clk=ports.clk,
input=ports.input,
name="reg",
inner_sym="reg")
sym_name="reg")
ports.output = compreg
@ -37,7 +37,9 @@ appid.lookup(pycde.AppID("reg")).add_attribute(loc)
mod = pycde.System([CompReg], name="CompReg", output_directory=sys.argv[1])
mod.print()
mod.generate()
mod.get_instance(CompReg).walk(appid.apply_attributes_visitor)
top_inst = mod.get_instance(CompReg)
top_inst.createdb()
top_inst.walk(appid.apply_attributes_visitor)
mod.print()
mod.emit_outputs()

View File

@ -23,7 +23,7 @@ class UnParameterized:
@pycde.generator
def construct(mod):
Nothing()
Nothing().name = "nothing_inst"
mod.y = mod.x
@ -35,8 +35,8 @@ class Test:
@pycde.generator
def build(_):
c1 = pycde.dialects.hw.ConstantOp(pycde.types.i1, 1)
UnParameterized(x=c1)
UnParameterized(x=c1)
UnParameterized(x=c1).name = "unparam"
UnParameterized(x=c1).name = "unparam"
# Set up the primitive locations. Errors out if location is placed but doesn't
@ -54,7 +54,7 @@ print(PhysLocation(PrimitiveType.DSP, 39, 25))
# CHECK: msft.module @UnParameterized
# CHECK-NOT: msft.module @UnParameterized
t = pycde.System([Test], primdb, name="Test", output_directory=sys.argv[1])
t = pycde.System([Test], name="Test", output_directory=sys.argv[1])
t.generate(["construct"])
t.print()
@ -63,68 +63,67 @@ UnParameterized.print()
# CHECK-LABEL: === Hierarchy
print("=== Hierarchy")
# CHECK-NEXT: <instance: []>
# CHECK-NEXT: <instance: [UnParameterized]>
# CHECK-NEXT: <instance: [UnParameterized, Nothing]>
# CHECK-NEXT: <instance: [UnParameterized_1]>
# CHECK-NEXT: <instance: [UnParameterized_1, Nothing]>
mod = t.get_instance(Test).walk(lambda inst: print(inst))
locs = pycde.AppIDIndex()
locs.lookup(pycde.AppID("UnParameterized_1"))["loc"] = \
(["memory", "bank"], PrimitiveType.M20K, 39, 25, 0)
test_inst = t.get_instance(Test)
test_inst.createdb(primdb)
mod = test_inst.walk(lambda inst: print(inst))
def place_inst(inst):
global x, y
if inst.module == Nothing:
inst.place("dsp_inst", PrimitiveType.DSP, x, y)
x += 1
y += 2
else:
props = locs.lookup(inst.appid)
if "loc" in props:
inst.place(*props["loc"])
if inst.name == "UnParameterized_1":
inst.place(PrimitiveType.M20K, 39, 25, 0, "memory|bank")
x = 0
y = 10
t.get_instance(Test).walk(place_inst)
instance_attrs = pycde.AppIDIndex()
loc = placement(["memory", "bank"], PrimitiveType.M20K, 15, 25, 0)
instance_attrs.lookup(pycde.AppID("UnParameterized")).add_attribute(loc)
loc = placement(["memory", "bank"], PrimitiveType.DSP, 39, 25, 0)
loc = placement("", PrimitiveType.DSP, 39, 25, 0)
instance_attrs.lookup(pycde.AppID("UnParameterized",
"Nothing")).add_attribute(loc)
region1 = t.create_physical_region("region_0").add_bounds((0, 10), (0, 10))
region1.add_bounds((10, 20), (10, 20))
ref = region1.get_ref()
instance_attrs.lookup(pycde.AppID("UnParameterized",
"Nothing")).add_attribute(ref)
# TODO: Add back physical region support
region_anon = t.create_physical_region()
assert region_anon._physical_region.sym_name.value == "region_1"
# region1 = t.create_physical_region("region_0").add_bounds((0, 10), (0, 10))
# region1.add_bounds((10, 20), (10, 20))
# ref = region1.get_ref()
# instance_attrs.lookup(pycde.AppID("UnParameterized",
# "Nothing")).add_attribute(ref)
region_explicit = t.create_physical_region("region_1")
assert region_explicit._physical_region.sym_name.value == "region_1_1"
# region_anon = t.create_physical_region()
# assert region_anon._physical_region.sym_name.value == "region_1"
# region_explicit = t.create_physical_region("region_1")
# assert region_explicit._physical_region.sym_name.value == "region_1_1"
test_inst = t.get_instance(Test)
test_inst.createdb()
test_inst.walk(instance_attrs.apply_attributes_visitor)
reserved_loc = PhysLocation(PrimitiveType.M20K, 40, 40, 0)
entity_extern = t.create_entity_extern("tag")
test_inst.placedb.reserve_location(reserved_loc, entity_extern)
# TODO: add back anonymous reservations
# reserved_loc = PhysLocation(PrimitiveType.M20K, 40, 40, 0)
# entity_extern = t.create_entity_extern("tag")
# test_inst.placedb.reserve_location(reserved_loc, entity_extern)
assert test_inst.placedb.get_instance_at(loc[1]) is not None
assert test_inst.placedb.get_instance_at(
PhysLocation(PrimitiveType.M20K, 0, 0, 0)) is None
assert test_inst.placedb.get_instance_at(reserved_loc) is not None
# assert test_inst.placedb.get_instance_at(reserved_loc) is not None
assert instance_attrs.find_unused() is None
instance_attrs.lookup(pycde.AppID("doesnotexist")).add_attribute(loc)
assert (len(instance_attrs.find_unused()) == 1)
print("=== Pre-pass mlir dump")
t.print()
print("=== Running passes")
t.run_passes()
print("=== Final mlir dump")
@ -132,13 +131,9 @@ t.print()
# OUTPUT-LABEL: proc Test_config { parent }
# OUTPUT-NOT: set_location_assignment M20K_X40_Y40
# OUTPUT-DAG: set_location_assignment MPDSP_X0_Y10_N0 -to $parent|UnParameterized|Nothing|dsp_inst
# OUTPUT-DAG: set_location_assignment MPDSP_X39_Y25_N0 -to $parent|UnParameterized|Nothing|memory|bank
# OUTPUT-DAG: set_location_assignment M20K_X15_Y25_N0 -to $parent|UnParameterized|memory|bank
# OUTPUT-DAG: set_location_assignment MPDSP_X1_Y12_N0 -to $parent|UnParameterized_1|Nothing|dsp_inst
# OUTPUT-DAG: set_location_assignment M20K_X39_Y25_N0 -to $parent|UnParameterized_1|memory|bank
# OUTPUT-DAG: set_instance_assignment -name PLACE_REGION "X0 Y0 X10 Y10;X10 Y10 X20 Y20" -to $parent|UnParameterized|Nothing
# OUTPUT-DAG: set_instance_assignment -name RESERVE_PLACE_REGION OFF -to $parent|UnParameterized|Nothing
# OUTPUT-DAG: set_instance_assignment -name CORE_ONLY_PLACE_REGION ON -to $parent|UnParameterized|Nothing
# OUTPUT-DAG: set_instance_assignment -name REGION_NAME region_0 -to $parent|UnParameterized|Nothing
# OUTPUT-DAG: set_location_assignment M20K_X15_Y25_N0 -to $parent|UnParameterized|memory|bank
# OUTPUT-DAG: set_location_assignment MPDSP_X39_Y25_N0 -to $parent|UnParameterized|Nothing
# OUTPUT-NOT: set_location_assignment
# OUTPUT-NEXT: }
t.emit_outputs()

View File

@ -33,9 +33,8 @@ typedef int32_t CirctMSFTPrimitiveType;
MLIR_CAPI_EXPORTED bool
circtMSFTAttributeIsAPhysLocationAttribute(MlirAttribute);
MLIR_CAPI_EXPORTED MlirAttribute
circtMSFTPhysLocationAttrGet(MlirContext, CirctMSFTPrimitiveType, uint64_t x,
uint64_t y, uint64_t num, MlirStringRef subPath);
MLIR_CAPI_EXPORTED MlirAttribute circtMSFTPhysLocationAttrGet(
MlirContext, CirctMSFTPrimitiveType, uint64_t x, uint64_t y, uint64_t num);
MLIR_CAPI_EXPORTED CirctMSFTPrimitiveType
circtMSFTPhysLocationAttrGetPrimitiveType(MlirAttribute);
MLIR_CAPI_EXPORTED uint64_t circtMSFTPhysLocationAttrGetX(MlirAttribute);

View File

@ -143,14 +143,13 @@ void circt::python::populateDialectMSFTSubmodule(py::module &m) {
.def_classmethod(
"get",
[](py::object cls, PrimitiveType devType, uint64_t x, uint64_t y,
uint64_t num, std::string subPath, MlirContext ctxt) {
auto cSubPath = mlirStringRefCreateFromCString(subPath.c_str());
uint64_t num, MlirContext ctxt) {
return cls(circtMSFTPhysLocationAttrGet(ctxt, (uint64_t)devType, x,
y, num, cSubPath));
y, num));
},
"Create a physical location attribute", py::arg(),
py::arg("dev_type"), py::arg("x"), py::arg("y"), py::arg("num"),
py::arg("sub_path") = py::str(""), py::arg("ctxt") = py::none())
py::arg("ctxt") = py::none())
.def_property_readonly(
"devtype",
[](MlirAttribute self) {

View File

@ -139,6 +139,13 @@ class PhysicalRegionOp:
self.attributes["bounds"] = new_bounds
class InstanceOp:
@property
def moduleName(self):
return _ir.FlatSymbolRefAttr(self.attributes["moduleName"])
class EntityExternOp:
@staticmethod

View File

@ -150,8 +150,8 @@ bool circtMSFTAttributeIsAPhysLocationAttribute(MlirAttribute attr) {
}
MlirAttribute circtMSFTPhysLocationAttrGet(MlirContext cCtxt,
CirctMSFTPrimitiveType devType,
uint64_t x, uint64_t y, uint64_t num,
MlirStringRef subPath) {
uint64_t x, uint64_t y,
uint64_t num) {
auto *ctxt = unwrap(cCtxt);
return wrap(PhysLocationAttr::get(
ctxt, PrimitiveTypeAttr::get(ctxt, (PrimitiveType)devType), x, y, num));

View File

@ -158,7 +158,8 @@ LogicalResult DynamicInstanceOpLowering::matchAndRewrite(
}
}
if (symNotFound)
return failure();
return rewriter.notifyMatchFailure(
inst, "Could not find operation corresponding to appid");
// Relocate all my children.
rewriter.setInsertionPointAfter(inst);
@ -633,13 +634,10 @@ void PassCommon::getAndSortModules(ModuleOp topMod,
/// Fill a symbol cache with all the top level symbols.
void PassCommon::populateSymbolCache(mlir::ModuleOp mod) {
for (Operation &op : mod.getBody()->getOperations()) {
StringAttr symName = SymbolTable::getSymbolName(&op);
if (!symName)
continue;
// Add the symbol to the cache.
topLevelSyms.addDefinition(symName, &op);
}
for (Operation &op : mod.getBody()->getOperations())
if (auto symOp = dyn_cast<mlir::SymbolOpInterface>(op))
if (auto name = symOp.getNameAttr())
topLevelSyms.addDefinition(name, symOp);
topLevelSyms.freeze();
}