mirror of https://github.com/llvm/circt.git
200 lines
6.6 KiB
C++
200 lines
6.6 KiB
C++
//===- TestPasses.cpp - Test passes for the analysis infrastructure -------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements test passes for the analysis infrastructure.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "circt/Analysis/DebugAnalysis.h"
|
|
#include "circt/Analysis/DependenceAnalysis.h"
|
|
#include "circt/Analysis/SchedulingAnalysis.h"
|
|
#include "circt/Dialect/HW/HWInstanceGraph.h"
|
|
#include "circt/Scheduling/Problems.h"
|
|
#include "mlir/Dialect/Affine/IR/AffineMemoryOpInterfaces.h"
|
|
#include "mlir/Dialect/Affine/IR/AffineOps.h"
|
|
#include "mlir/Dialect/Func/IR/FuncOps.h"
|
|
#include "mlir/IR/BuiltinOps.h"
|
|
#include "mlir/IR/Value.h"
|
|
#include "mlir/Pass/Pass.h"
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
using namespace mlir;
|
|
using namespace mlir::affine;
|
|
using namespace circt;
|
|
using namespace circt::analysis;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// DebugAnalysis
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
struct TestDebugAnalysisPass
|
|
: public PassWrapper<TestDebugAnalysisPass, OperationPass<mlir::ModuleOp>> {
|
|
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestDebugAnalysisPass)
|
|
|
|
void runOnOperation() override;
|
|
StringRef getArgument() const override { return "test-debug-analysis"; }
|
|
StringRef getDescription() const override {
|
|
return "Perform debug analysis and emit results as attributes";
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
void TestDebugAnalysisPass::runOnOperation() {
|
|
auto *context = &getContext();
|
|
auto &analysis = getAnalysis<DebugAnalysis>();
|
|
for (auto *op : analysis.debugOps) {
|
|
op->setAttr("debug.only", UnitAttr::get(context));
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// DependenceAnalysis
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
struct TestDependenceAnalysisPass
|
|
: public PassWrapper<TestDependenceAnalysisPass,
|
|
OperationPass<func::FuncOp>> {
|
|
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestDependenceAnalysisPass)
|
|
|
|
void runOnOperation() override;
|
|
StringRef getArgument() const override { return "test-dependence-analysis"; }
|
|
StringRef getDescription() const override {
|
|
return "Perform dependence analysis and emit results as attributes";
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
void TestDependenceAnalysisPass::runOnOperation() {
|
|
MLIRContext *context = &getContext();
|
|
|
|
MemoryDependenceAnalysis analysis(getOperation());
|
|
|
|
getOperation().walk([&](Operation *op) {
|
|
if (!isa<AffineReadOpInterface, AffineWriteOpInterface>(op))
|
|
return;
|
|
|
|
SmallVector<Attribute> deps;
|
|
|
|
for (auto dep : analysis.getDependences(op)) {
|
|
if (dep.dependenceType != DependenceResult::HasDependence)
|
|
continue;
|
|
|
|
SmallVector<Attribute> comps;
|
|
for (auto comp : dep.dependenceComponents) {
|
|
SmallVector<Attribute> vector;
|
|
vector.push_back(
|
|
IntegerAttr::get(IntegerType::get(context, 64), *comp.lb));
|
|
vector.push_back(
|
|
IntegerAttr::get(IntegerType::get(context, 64), *comp.ub));
|
|
comps.push_back(ArrayAttr::get(context, vector));
|
|
}
|
|
|
|
deps.push_back(ArrayAttr::get(context, comps));
|
|
}
|
|
|
|
auto dependences = ArrayAttr::get(context, deps);
|
|
op->setAttr("dependences", dependences);
|
|
});
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// SchedulingAnalysis
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
struct TestSchedulingAnalysisPass
|
|
: public PassWrapper<TestSchedulingAnalysisPass,
|
|
OperationPass<func::FuncOp>> {
|
|
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestSchedulingAnalysisPass)
|
|
|
|
void runOnOperation() override;
|
|
StringRef getArgument() const override { return "test-scheduling-analysis"; }
|
|
StringRef getDescription() const override {
|
|
return "Perform scheduling analysis and emit results as attributes";
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
void TestSchedulingAnalysisPass::runOnOperation() {
|
|
MLIRContext *context = &getContext();
|
|
|
|
CyclicSchedulingAnalysis analysis = getAnalysis<CyclicSchedulingAnalysis>();
|
|
|
|
getOperation().walk([&](AffineForOp forOp) {
|
|
if (isa<AffineForOp>(forOp.getBody()->front()))
|
|
return;
|
|
CyclicProblem problem = analysis.getProblem(forOp);
|
|
forOp.getBody()->walk([&](Operation *op) {
|
|
for (auto dep : problem.getDependences(op)) {
|
|
assert(!dep.isInvalid());
|
|
if (dep.isAuxiliary())
|
|
op->setAttr("dependence", UnitAttr::get(context));
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// InstanceGraph
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
struct InferTopModulePass
|
|
: public PassWrapper<InferTopModulePass, OperationPass<mlir::ModuleOp>> {
|
|
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(InferTopModulePass)
|
|
|
|
void runOnOperation() override;
|
|
StringRef getArgument() const override { return "test-infer-top-level"; }
|
|
StringRef getDescription() const override {
|
|
return "Perform top level module inference and emit results as attributes "
|
|
"on the enclosing module.";
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
void InferTopModulePass::runOnOperation() {
|
|
circt::hw::InstanceGraph &analysis = getAnalysis<circt::hw::InstanceGraph>();
|
|
auto res = analysis.getInferredTopLevelNodes();
|
|
if (failed(res)) {
|
|
signalPassFailure();
|
|
return;
|
|
}
|
|
|
|
llvm::SmallVector<Attribute, 4> attrs;
|
|
for (auto *node : *res)
|
|
attrs.push_back(node->getModule().getModuleNameAttr());
|
|
|
|
analysis.getParent()->setAttr("test.top",
|
|
ArrayAttr::get(&getContext(), attrs));
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Pass registration
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace circt {
|
|
namespace test {
|
|
void registerAnalysisTestPasses() {
|
|
registerPass([]() -> std::unique_ptr<Pass> {
|
|
return std::make_unique<TestDependenceAnalysisPass>();
|
|
});
|
|
registerPass([]() -> std::unique_ptr<Pass> {
|
|
return std::make_unique<TestSchedulingAnalysisPass>();
|
|
});
|
|
registerPass([]() -> std::unique_ptr<Pass> {
|
|
return std::make_unique<TestDebugAnalysisPass>();
|
|
});
|
|
registerPass([]() -> std::unique_ptr<Pass> {
|
|
return std::make_unique<InferTopModulePass>();
|
|
});
|
|
}
|
|
} // namespace test
|
|
} // namespace circt
|