CIRCT  20.0.0git
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 
14 #include "mlir/Pass/Pass.h"
15 #include "llvm/ADT/DepthFirstIterator.h"
16 #include "llvm/ADT/PostOrderIterator.h"
17 
18 namespace circt {
19 namespace firrtl {
20 #define GEN_PASS_DEF_CHECKLAYERS
21 #include "circt/Dialect/FIRRTL/Passes.h.inc"
22 } // namespace firrtl
23 } // namespace circt
24 
25 using namespace circt;
26 using namespace firrtl;
27 using namespace mlir;
28 
29 namespace {
30 class CheckLayers {
31  CheckLayers(InstanceGraph &instanceGraph, InstanceInfo &instanceInfo)
32  : iGraph(instanceGraph), iInfo(instanceInfo) {}
33 
34  /// Walk a module, reporting any illegal instantation of layers under layers,
35  /// and record if this module contains any layerblocks.
36  void run(FModuleOp moduleOp) {
37  // No instance is under a layer block. No further examination is necessary.
38  if (!iInfo.anyInstanceUnderLayer(moduleOp))
39  return;
40 
41  // The module is under a layer block. Verify that it has no layer blocks.
42  LayerBlockOp layerBlockOp;
43  moduleOp.getBodyBlock()->walk([&](LayerBlockOp op) {
44  layerBlockOp = op;
45  return WalkResult::interrupt();
46  });
47  if (!layerBlockOp)
48  return;
49 
50  // The module contains layer blocks and is instantiated under a layer block.
51  // Walk up the instance hierarchy to find the first instance which is
52  // directly under a layer block.
53  error = true;
54  for (auto *node : llvm::inverse_depth_first(iGraph.lookup(moduleOp))) {
55  auto modOp = node->getModule();
56  if (previousErrors.contains(node) || !iInfo.anyInstanceUnderLayer(modOp))
57  continue;
58  for (auto *instNode : node->uses()) {
59  auto instanceOp = instNode->getInstance();
60  if (instanceOp->getParentOfType<LayerBlockOp>()) {
61  auto moduleName = modOp.getModuleNameAttr();
62  auto diag = emitError(instanceOp.getLoc())
63  << "cannot instantiate " << moduleName
64  << " under a layerblock, because " << moduleName
65  << " contains a layerblock";
66  diag.attachNote(layerBlockOp->getLoc()) << "layerblock here";
67  previousErrors.insert(node);
68  continue;
69  }
70  }
71  }
72  }
73 
74 public:
75  static LogicalResult run(InstanceGraph &instanceGraph,
76  InstanceInfo &instanceInfo) {
77  CheckLayers checkLayers(instanceGraph, instanceInfo);
78  DenseSet<InstanceGraphNode *> visited;
79  for (auto *root : instanceGraph) {
80  for (auto *node : llvm::inverse_post_order_ext(root, visited)) {
81  if (auto moduleOp = dyn_cast<FModuleOp>(node->getModule<Operation *>()))
82  checkLayers.run(moduleOp);
83  }
84  }
85  return failure(checkLayers.error);
86  }
87 
88 private:
89  /// Pre-populated analyses
90  InstanceGraph &iGraph;
91  InstanceInfo &iInfo;
92 
93  /// This records modules for which we have already generated errors when doing
94  /// a top-down walk.
95  DenseSet<const InstanceGraphNode *> previousErrors;
96 
97  /// Indicates if this checker found an error.
98  bool error = false;
99 };
100 } // end anonymous namespace
101 
103  : public circt::firrtl::impl::CheckLayersBase<CheckLayersPass> {
104 public:
105  void runOnOperation() override {
106  if (failed(CheckLayers::run(getAnalysis<InstanceGraph>(),
107  getAnalysis<InstanceInfo>())))
108  return signalPassFailure();
109  markAllAnalysesPreserved();
110  }
111 };
112 
113 std::unique_ptr<Pass> circt::firrtl::createCheckLayers() {
114  return std::make_unique<CheckLayersPass>();
115 }
void runOnOperation() override
This graph tracks modules and where they are instantiated.
std::unique_ptr< mlir::Pass > createCheckLayers()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
int run(Type[Generator] generator=CppGenerator, cmdline_args=sys.argv)
Definition: codegen.py:121