@@ -1711,27 +1711,42 @@ void GrandCentralPass::runOnOperation() {
1711
1711
instancePaths = &instancePathCache;
1712
1712
1713
1713
// / Contains the set of modules which are instantiated by the DUT, but not a
1714
- // / companion or instantiated by a companion. If no DUT exists, treat the top
1715
- // / module as if it were the DUT. This works by doing a depth-first walk of
1716
- // / the instance graph, starting from the "effective" DUT and stopping the
1717
- // / search at any modules which are known companions.
1718
- DenseSet<igraph::ModuleOpInterface> dutModules;
1719
- FModuleOp effectiveDUT = dut;
1720
- if (!effectiveDUT)
1721
- effectiveDUT = cast<FModuleOp>(
1722
- *instancePaths->instanceGraph .getTopLevelNode ()->getModule ());
1723
- auto dfRange =
1724
- llvm::depth_first (instancePaths->instanceGraph .lookup (effectiveDUT));
1725
- for (auto i = dfRange.begin (), e = dfRange.end (); i != e;) {
1726
- auto module = cast<FModuleLike>(*i->getModule ());
1727
- if (AnnotationSet (module).hasAnnotation (companionAnnoClass)) {
1728
- i.skipChildren ();
1729
- continue ;
1714
+ // / companion, instantiated by a companion, or instantiated under a bind. If
1715
+ // / no DUT exists, treat the top module as if it were the DUT. This works by
1716
+ // / doing a depth-first walk of the instance graph, starting from the
1717
+ // / "effective" DUT and stopping the search at any modules which are known
1718
+ // / companions or any instances which are marked "lowerToBind".
1719
+ DenseSet<InstanceGraphNode *> dutModules;
1720
+ InstanceGraphNode *effectiveDUT;
1721
+ if (dut)
1722
+ effectiveDUT = instancePaths->instanceGraph .lookup (dut);
1723
+ else
1724
+ effectiveDUT = instancePaths->instanceGraph .getTopLevelNode ();
1725
+ {
1726
+ SmallVector<InstanceGraphNode *> modules ({effectiveDUT});
1727
+ while (!modules.empty ()) {
1728
+ auto *m = modules.pop_back_val ();
1729
+ for (InstanceRecord *a : *m) {
1730
+ auto *mod = a->getTarget ();
1731
+ // Skip modules that we've visited, that are are under the companion
1732
+ // module, or are bound/under a layer block.
1733
+ if (auto block = a->getInstance ()->getParentOfType <LayerBlockOp>()) {
1734
+ auto diag = a->getInstance ().emitOpError ()
1735
+ << " is instantiated under a '" << block.getOperationName ()
1736
+ << " ' op which is unexpected by GrandCentral (did you "
1737
+ " forget to run the LowerLayers pass?)" ;
1738
+ diag.attachNote (block.getLoc ())
1739
+ << " the '" << block.getOperationName () << " ' op is here" ;
1740
+ removalError = true ;
1741
+ }
1742
+ if (dutModules.contains (mod) ||
1743
+ AnnotationSet (mod->getModule ()).hasAnnotation (companionAnnoClass) ||
1744
+ cast<InstanceOp>(*a->getInstance ()).getLowerToBind ())
1745
+ continue ;
1746
+ modules.push_back (mod);
1747
+ dutModules.insert (mod);
1748
+ }
1730
1749
}
1731
- dutModules.insert (i->getModule <igraph::ModuleOpInterface>());
1732
- // Manually increment the iterator to avoid walking off the end from
1733
- // skipChildren.
1734
- ++i;
1735
1750
}
1736
1751
1737
1752
// Maybe return the lone instance of a module. Generate errors on the op if
@@ -1765,7 +1780,6 @@ void GrandCentralPass::runOnOperation() {
1765
1780
// / (2) the leafMap. Annotations are removed as they are discovered and if
1766
1781
// / they are not malformed.
1767
1782
DenseSet<Operation *> modulesToDelete;
1768
- removalError = false ;
1769
1783
circuitOp.walk ([&](Operation *op) {
1770
1784
TypeSwitch<Operation *>(op)
1771
1785
.Case <RegOp, RegResetOp, WireOp, NodeOp>([&](auto op) {
@@ -1950,12 +1964,11 @@ void GrandCentralPass::runOnOperation() {
1950
1964
// Check to see if we should change the output directory of a
1951
1965
// module. Only update in the following conditions:
1952
1966
// 1) The module is the companion.
1953
- // 2) The module is NOT instantiated by the effective DUT.
1967
+ // 2) The module is NOT instantiated by the effective DUT or
1968
+ // is under a bind.
1954
1969
auto *modNode = instancePaths->instanceGraph .lookup (mod);
1955
1970
SmallVector<InstanceRecord *> instances (modNode->uses ());
1956
- if (modNode != companionNode &&
1957
- dutModules.count (
1958
- modNode->getModule <igraph::ModuleOpInterface>()))
1971
+ if (modNode != companionNode && dutModules.count (modNode))
1959
1972
continue ;
1960
1973
1961
1974
LLVM_DEBUG ({
0 commit comments