21 #include "mlir/Dialect/Affine/IR/AffineMemoryOpInterfaces.h"
22 #include "mlir/Dialect/Affine/IR/AffineOps.h"
23 #include "mlir/Dialect/Func/IR/FuncOps.h"
24 #include "mlir/IR/BuiltinOps.h"
25 #include "mlir/IR/Value.h"
26 #include "mlir/Pass/Pass.h"
27 #include "llvm/ADT/DepthFirstIterator.h"
28 #include "llvm/Support/Debug.h"
32 using namespace circt;
41 struct TestDebugAnalysisPass
42 :
public PassWrapper<TestDebugAnalysisPass, OperationPass<mlir::ModuleOp>> {
43 MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestDebugAnalysisPass)
45 void runOnOperation()
override;
46 StringRef getArgument()
const override {
return "test-debug-analysis"; }
47 StringRef getDescription()
const override {
48 return "Perform debug analysis and emit results as attributes";
53 void TestDebugAnalysisPass::runOnOperation() {
54 auto *context = &getContext();
55 auto &analysis = getAnalysis<DebugAnalysis>();
56 for (
auto *op : analysis.debugOps) {
66 struct TestDependenceAnalysisPass
67 :
public PassWrapper<TestDependenceAnalysisPass,
68 OperationPass<func::FuncOp>> {
69 MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestDependenceAnalysisPass)
71 void runOnOperation()
override;
72 StringRef getArgument()
const override {
return "test-dependence-analysis"; }
73 StringRef getDescription()
const override {
74 return "Perform dependence analysis and emit results as attributes";
79 void TestDependenceAnalysisPass::runOnOperation() {
80 MLIRContext *context = &getContext();
84 getOperation().walk([&](Operation *op) {
85 if (!isa<AffineReadOpInterface, AffineWriteOpInterface>(op))
88 SmallVector<Attribute> deps;
90 for (
auto dep : analysis.getDependences(op)) {
91 if (dep.dependenceType != DependenceResult::HasDependence)
94 SmallVector<Attribute> comps;
95 for (auto comp : dep.dependenceComponents) {
96 SmallVector<Attribute> vector;
98 IntegerAttr::get(IntegerType::get(context, 64), *comp.lb));
100 IntegerAttr::get(IntegerType::get(context, 64), *comp.ub));
101 comps.push_back(ArrayAttr::get(context, vector));
108 op->setAttr(
"dependences", dependences);
117 struct TestSchedulingAnalysisPass
118 :
public PassWrapper<TestSchedulingAnalysisPass,
119 OperationPass<func::FuncOp>> {
120 MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestSchedulingAnalysisPass)
122 void runOnOperation()
override;
123 StringRef getArgument()
const override {
return "test-scheduling-analysis"; }
124 StringRef getDescription()
const override {
125 return "Perform scheduling analysis and emit results as attributes";
130 void TestSchedulingAnalysisPass::runOnOperation() {
131 MLIRContext *context = &getContext();
135 getOperation().walk([&](AffineForOp forOp) {
136 if (isa<AffineForOp>(forOp.getBody()->front()))
139 forOp.getBody()->walk([&](Operation *op) {
140 for (auto dep : problem.getDependences(op)) {
141 assert(!dep.isInvalid());
142 if (dep.isAuxiliary())
143 op->setAttr(
"dependence", UnitAttr::get(context));
154 struct InferTopModulePass
155 :
public PassWrapper<InferTopModulePass, OperationPass<mlir::ModuleOp>> {
156 MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(InferTopModulePass)
158 void runOnOperation()
override;
159 StringRef getArgument()
const override {
return "test-infer-top-level"; }
160 StringRef getDescription()
const override {
161 return "Perform top level module inference and emit results as attributes "
162 "on the enclosing module.";
167 void InferTopModulePass::runOnOperation() {
175 llvm::SmallVector<Attribute, 4> attrs;
176 for (
auto *node : *res)
177 attrs.push_back(node->getModule().getModuleNameAttr());
179 analysis.
getParent()->setAttr(
"test.top",
188 struct FIRRTLInstanceInfoPass
189 :
public PassWrapper<FIRRTLInstanceInfoPass,
190 OperationPass<firrtl::CircuitOp>> {
191 MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(FIRRTLInstanceInfoPass)
193 void runOnOperation()
override;
194 StringRef getArgument()
const override {
return "test-firrtl-instance-info"; }
195 StringRef getDescription()
const override {
196 return "Run firrtl::InstanceInfo analysis and show the results. This pass "
197 "is intended to be used for testing purposes only.";
202 static llvm::raw_ostream &
operator<<(llvm::raw_ostream &os,
const bool a) {
205 return os <<
"false";
210 OpPrintingFlags flags;
212 llvm::errs() <<
" - operation: ";
213 op->print(llvm::errs(), flags);
215 <<
" hasDut: " << iInfo.
hasDut() <<
"\n"
217 if (
auto dutNode = iInfo.
getDut())
218 dutNode->print(llvm::errs(), flags);
220 llvm::errs() <<
"null";
222 <<
" effectiveDut: ";
224 llvm::errs() <<
"\n";
229 OpPrintingFlags flags;
231 llvm::errs() <<
" - operation: ";
232 op->print(llvm::errs(), flags);
234 <<
" isDut: " << iInfo.
isDut(op) <<
"\n"
239 <<
" anyInstanceUnderEffectiveDut: "
241 <<
" allInstancesUnderEffectiveDut: "
243 <<
" anyInstanceUnderLayer: "
245 <<
" allInstancesUnderLayer: "
251 <<
" anyInstanceInEffectiveDesign: "
253 <<
" allInstancesInEffectiveDesign: "
257 void FIRRTLInstanceInfoPass::runOnOperation() {
258 auto &iInfo = getAnalysis<firrtl::InstanceInfo>();
262 getOperation().
getBodyBlock()->getOps<igraph::ModuleOpInterface>())
273 registerPass([]() -> std::unique_ptr<Pass> {
274 return std::make_unique<TestDependenceAnalysisPass>();
276 registerPass([]() -> std::unique_ptr<Pass> {
277 return std::make_unique<TestSchedulingAnalysisPass>();
279 registerPass([]() -> std::unique_ptr<Pass> {
280 return std::make_unique<TestDebugAnalysisPass>();
282 registerPass([]() -> std::unique_ptr<Pass> {
283 return std::make_unique<InferTopModulePass>();
285 registerPass([]() -> std::unique_ptr<Pass> {
286 return std::make_unique<FIRRTLInstanceInfoPass>();
static Block * getBodyBlock(FModuleLike mod)
static void printModuleInfo(igraph::ModuleOpInterface op, firrtl::InstanceInfo &iInfo)
static void printCircuitInfo(firrtl::CircuitOp op, firrtl::InstanceInfo &iInfo)
static llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const bool a)
bool allInstancesUnderLayer(igraph::ModuleOpInterface op)
Return true if all instances of this module are under (or transitively under) layer blocks.
igraph::ModuleOpInterface getDut()
Return the design-under-test if one is defined for the circuit, otherwise return null.
bool hasDut()
Return true if this circuit has a design-under-test.
bool allInstancesInEffectiveDesign(igraph::ModuleOpInterface op)
Return true if all instances of this module are within (or transitively withiin) the effective design...
bool isDut(igraph::ModuleOpInterface op)
Return true if this module is the design-under-test.
bool anyInstanceUnderDut(igraph::ModuleOpInterface op)
Return true if at least one instance of this module is under (or transitively under) the design-under...
bool anyInstanceUnderEffectiveDut(igraph::ModuleOpInterface op)
Return true if at least one instance is under (or transitively under) the effective design-under-test...
bool allInstancesUnderEffectiveDut(igraph::ModuleOpInterface op)
Return true if all instances are under (or transitively under) the effective design-under-test.
igraph::ModuleOpInterface getEffectiveDut()
Return the "effective" design-under-test.
bool allInstancesUnderDut(igraph::ModuleOpInterface op)
Return true if all instances of this module are under (or transitively under) the design-under-test.
bool anyInstanceInEffectiveDesign(igraph::ModuleOpInterface op)
Return true if any instance of this module is within (or transitively within) the effective design.
bool allInstancesInDesign(igraph::ModuleOpInterface op)
Return true if all instances of this module are within (or transitively withiin) the design.
bool anyInstanceUnderLayer(igraph::ModuleOpInterface op)
Return true if at least one instance of this module is under (or transitively under) a layer.
bool anyInstanceInDesign(igraph::ModuleOpInterface op)
Return true if any instance of this module is within (or transitively within) the design.
HW-specific instance graph with a virtual entry node linking to all publicly visible modules.
FailureOr< llvm::ArrayRef< InstanceGraphNode * > > getInferredTopLevelNodes()
Get the nodes corresponding to the inferred top-level modules of a circuit.
Operation * getParent()
Return the parent under which all nodes are nested.
This class models a cyclic scheduling problem.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
void registerAnalysisTestPasses()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
CyclicSchedulingAnalysis constructs a CyclicProblem for each AffineForOp by performing a memory depen...
scheduling::CyclicProblem & getProblem(mlir::affine::AffineForOp forOp)
MemoryDependenceAnalysis traverses any AffineForOps in the FuncOp body and checks for affine memory a...