15 #include "llvm/ADT/PostOrderIterator.h"
19 #define GEN_PASS_DEF_CHECKLAYERS
20 #include "circt/Dialect/FIRRTL/Passes.h.inc"
24 using namespace circt;
25 using namespace firrtl;
31 : iGraph(instanceGraph), iInfo(instanceInfo) {}
36 void run(FModuleOp moduleOp) {
43 if (!iInfo.anyInstanceUnderLayer(moduleOp))
48 SmallVector<Operation *> layerBlockOps;
49 moduleOp->walk([&](LayerBlockOp layerBlockOp) {
50 layerBlockOps.push_back(layerBlockOp);
61 if (!isGCCompanion && !transitiveModules.contains(moduleOp) &&
62 layerBlockOps.empty())
67 SmallVector<Operation *> instUnderLayerBlock, instUnderLayerModule;
68 for (
auto *instNode : iGraph.lookup(moduleOp)->uses()) {
69 auto *instOp = instNode->getInstance().getOperation();
70 if (instOp->getParentOfType<LayerBlockOp>())
71 instUnderLayerBlock.push_back(instOp);
72 else if (
auto parent = instOp->getParentOfType<FModuleOp>();
73 iInfo.anyInstanceUnderLayer(parent)) {
74 transitiveModules.insert(parent);
75 instUnderLayerModule.push_back(instOp);
81 if (layerBlockOps.empty() && instUnderLayerBlock.empty() &&
82 instUnderLayerModule.empty())
88 auto diag = moduleOp->emitOpError();
91 <<
"is a Grand Central companion that either contains layerblocks or";
94 diag <<
"either contains layerblocks or";
95 diag <<
" has at least one instance that is or contains a Grand Central "
96 "companion or layerblocks";
98 for (
auto *layerBlockOp : layerBlockOps)
99 diag.attachNote(layerBlockOp->getLoc()) <<
"illegal layerblock here";
100 for (
auto *instUnderLayerBlock : instUnderLayerBlock)
101 diag.attachNote(instUnderLayerBlock->getLoc())
102 <<
"illegal instantiation under a layerblock here";
103 for (
auto *instUnderLayerModule : instUnderLayerModule)
104 diag.attachNote(instUnderLayerModule->getLoc())
105 <<
"illegal instantiation in a module under a layer here";
111 CheckLayers checkLayers(instanceGraph, instanceInfo);
112 DenseSet<InstanceGraphNode *> visited;
113 for (
auto *root : instanceGraph) {
114 for (
auto *node : llvm::post_order_ext(root, visited)) {
115 if (
auto moduleOp = dyn_cast<FModuleOp>(node->getModule<Operation *>()))
116 checkLayers.run(moduleOp);
119 return failure(checkLayers.error);
131 DenseSet<Operation *> transitiveModules;
143 getAnalysis<InstanceInfo>())))
144 return signalPassFailure();
145 markAllAnalysesPreserved();
150 return std::make_unique<CheckLayersPass>();
void runOnOperation() override
bool hasAnnotation(StringRef className) const
Return true if we have an annotation with the specified class name.
This graph tracks modules and where they are instantiated.
std::unique_ptr< mlir::Pass > createCheckLayers()
constexpr const char * companionAnnoClass
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
int run(Type[Generator] generator=CppGenerator, cmdline_args=sys.argv)