Loading [MathJax]/extensions/tex2jax.js
CIRCT 22.0.0git
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CheckLayers.cpp
Go to the documentation of this file.
1//===- CheckLayers.cpp - check layer legality -----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
15#include "llvm/ADT/PostOrderIterator.h"
16
17namespace circt {
18namespace firrtl {
19#define GEN_PASS_DEF_CHECKLAYERS
20#include "circt/Dialect/FIRRTL/Passes.h.inc"
21} // namespace firrtl
22} // namespace circt
23
24using namespace circt;
25using namespace firrtl;
26using namespace mlir;
27
28namespace {
29class CheckLayers {
30 CheckLayers(InstanceGraph &instanceGraph, InstanceInfo &instanceInfo)
31 : iGraph(instanceGraph), iInfo(instanceInfo) {}
32
33 /// Walk a module and record any illegal layerblocks/Grand Central companions
34 /// under layerblocks/Grand Central companions. This function should be run
35 /// on children before parents for accurate reporting.
36 void run(FModuleOp moduleOp) {
37
38 // The module is _never_ instantiated under a layer. There is nothing to do
39 // because erroneous instantiations are reported when examining the module.
40 // Note: Grand Central companions are under a layer (because InstanceInfo
41 // uses the inclusive definition of "under" to be consistent with how the
42 // design-under-test module is "under" the design).
43 if (!iInfo.anyInstanceUnderLayer(moduleOp))
44 return;
45
46 // Check if this module has any layerblock ops. If these exist, then these
47 // may be errors.
48 SmallVector<Operation *> layerBlockOps;
49 moduleOp->walk([&](LayerBlockOp layerBlockOp) {
50 layerBlockOps.push_back(layerBlockOp);
51 });
52
53 bool isGCCompanion =
55
56 // Both Grand Central copmanions and modules that transitively instantiate
57 // layerblocks/Grand Central companions require analysis of their
58 // instantiation sites. However, if this is a normal module instantiated
59 // under a layer and it contains no layerblocks, then early exit to avoid
60 // unnecessarily examining instantiation sites.
61 if (!isGCCompanion && !transitiveModules.contains(moduleOp) &&
62 layerBlockOps.empty())
63 return;
64
65 // Record instantiations of this module under layerblocks or modules that
66 // are under layer blocks. Update transitive modules.
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);
76 }
77 }
78
79 // The module _may_ contain no errors if it is a Grand Central companion or
80 // a transitive module. Do a final check to ensure that an error exists.
81 if (layerBlockOps.empty() && instUnderLayerBlock.empty() &&
82 instUnderLayerModule.empty())
83 return;
84
85 // Record that an error occurred and print out an error message on the
86 // module with notes for more information.
87 error = true;
88 auto diag = moduleOp->emitOpError();
89 if (isGCCompanion)
90 diag
91 << "is a Grand Central companion that either contains layerblocks or";
92
93 else
94 diag << "either contains layerblocks or";
95 diag << " has at least one instance that is or contains a Grand Central "
96 "companion or layerblocks";
97
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";
106 }
107
108public:
109 static LogicalResult run(InstanceGraph &instanceGraph,
110 InstanceInfo &instanceInfo) {
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);
117 }
118 }
119 return failure(checkLayers.error);
120 }
121
122private:
123 /// Pre-populated analyses
124 InstanceGraph &iGraph;
125 InstanceInfo &iInfo;
126
127 /// A module whose instances (transitively) contain layerblocks or Grand
128 /// Central companions. This is used so that every illegal instantiation can
129 /// be reported. This is populated by `run` and requires child modules to be
130 /// visited before parents.
131 DenseSet<Operation *> transitiveModules;
132
133 /// Indicates if this checker found an error.
134 bool error = false;
135};
136} // end anonymous namespace
137
139 : public circt::firrtl::impl::CheckLayersBase<CheckLayersPass> {
140public:
141 void runOnOperation() override {
142 if (failed(CheckLayers::run(getAnalysis<InstanceGraph>(),
143 getAnalysis<InstanceInfo>())))
144 return signalPassFailure();
145 markAllAnalysesPreserved();
146 }
147};
static Location getLoc(DefSlot slot)
Definition Mem2Reg.cpp:217
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.
constexpr const char * companionAnnoClass
void error(Twine message)
Definition LSPUtils.cpp:16
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
int run(Type[Generator] generator=CppGenerator, cmdline_args=sys.argv)
Definition codegen.py:121