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"
41struct 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";
53void TestDebugAnalysisPass::runOnOperation() {
54 auto *context = &getContext();
55 auto &analysis = getAnalysis<DebugAnalysis>();
56 for (
auto *op : analysis.debugOps) {
57 op->setAttr(
"debug.only", UnitAttr::get(context));
66struct 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";
79void 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));
104 deps.push_back(ArrayAttr::get(context, comps));
107 auto dependences = ArrayAttr::get(context, deps);
108 op->setAttr(
"dependences", dependences);
117struct 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";
130void 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)) {
142 if (dep.isAuxiliary())
143 op->setAttr(
"dependence", UnitAttr::get(context));
154struct 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.";
167void 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",
180 ArrayAttr::get(&getContext(), attrs));
188struct 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.";
202static 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: "
257void 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>();
assert(baseType &&"element must be base type")
static Block * getBodyBlock(FModuleLike mod)
static void printModuleInfo(igraph::ModuleOpInterface op, firrtl::InstanceInfo &iInfo)
static void printCircuitInfo(firrtl::CircuitOp op, firrtl::InstanceInfo &iInfo)
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.
Operation * getParent()
Return the parent under which all nodes are nested.
FailureOr< llvm::ArrayRef< InstanceGraphNode * > > getInferredTopLevelNodes()
Get the nodes corresponding to the inferred top-level modules of a circuit.
This class models a cyclic scheduling problem.
OS & operator<<(OS &os, const InnerSymTarget &target)
Printing InnerSymTarget's.
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...