15#include "llvm/ADT/PostOrderIterator.h"
19#define GEN_PASS_DEF_CHECKLAYERS
20#include "circt/Dialect/FIRRTL/Passes.h.inc"
25using 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;
142 if (failed(CheckLayers::run(getAnalysis<InstanceGraph>(),
143 getAnalysis<InstanceInfo>())))
144 return signalPassFailure();
145 markAllAnalysesPreserved();
150 return std::make_unique<CheckLayersPass>();
static Location getLoc(DefSlot slot)
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
void error(Twine message)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
int run(Type[Generator] generator=CppGenerator, cmdline_args=sys.argv)