[Passes] small bugs fixed; remove HLSCppAnalyzer; insert-pipeline-pragma to loop-pipelining
This commit is contained in:
parent
c24b418c4a
commit
3f6d8e8560
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
include "mlir/Pass/PassBase.td"
|
include "mlir/Pass/PassBase.td"
|
||||||
|
|
||||||
def QoREstimation : Pass<"qor-estimation", "FuncOp"> {
|
def QoREstimation : Pass<"qor-estimation", "ModuleOp"> {
|
||||||
let summary = "Estimate the performance and resource utilization";
|
let summary = "Estimate the performance and resource utilization";
|
||||||
let description = [{
|
let description = [{
|
||||||
This qor-estimation pass will analyze the input CDFG and pragma operations
|
This qor-estimation pass will analyze the input CDFG and pragma operations
|
||||||
|
@ -21,6 +21,8 @@ def QoREstimation : Pass<"qor-estimation", "FuncOp"> {
|
||||||
Option<"targetSpec", "target-spec", "std::string",
|
Option<"targetSpec", "target-spec", "std::string",
|
||||||
/*default=*/"\"../config/target-spec.ini\"",
|
/*default=*/"\"../config/target-spec.ini\"",
|
||||||
"File path: target backend specifications and configurations">,
|
"File path: target backend specifications and configurations">,
|
||||||
|
Option<"topFunction", "top-function", "std::string", /*default=*/"",
|
||||||
|
"The top function for HLS synthesis">
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace mlir {
|
||||||
namespace scalehls {
|
namespace scalehls {
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// HLSCppToolBase Class Declaration
|
// HLSCppToolBase Class Declaration and Definition
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
class HLSCppToolBase {
|
class HLSCppToolBase {
|
||||||
|
@ -99,26 +99,6 @@ public:
|
||||||
OpBuilder &builder;
|
OpBuilder &builder;
|
||||||
};
|
};
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// HLSCppAnalyzer Class Declaration
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
class HLSCppAnalyzer : public HLSCppVisitorBase<HLSCppAnalyzer, bool>,
|
|
||||||
public HLSCppToolBase {
|
|
||||||
public:
|
|
||||||
explicit HLSCppAnalyzer(OpBuilder &builder) : HLSCppToolBase(builder) {}
|
|
||||||
|
|
||||||
bool visitUnhandledOp(Operation *op) { return true; }
|
|
||||||
|
|
||||||
using HLSCppVisitorBase::visitOp;
|
|
||||||
bool visitOp(ArrayOp op);
|
|
||||||
bool visitOp(AffineForOp op);
|
|
||||||
bool visitOp(AffineIfOp op);
|
|
||||||
|
|
||||||
void analyzeBlock(Block &block);
|
|
||||||
void analyzeFunc(FuncOp func);
|
|
||||||
};
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// HLSCppEstimator Class Declaration
|
// HLSCppEstimator Class Declaration
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -17,7 +17,7 @@ def ConvertToHLSCpp : Pass<"convert-to-hlscpp", "FuncOp"> {
|
||||||
let constructor = "mlir::scalehls::createConvertToHLSCppPass()";
|
let constructor = "mlir::scalehls::createConvertToHLSCppPass()";
|
||||||
|
|
||||||
let options = [
|
let options = [
|
||||||
Option<"TopFunction", "top-function", "std::string", /*default=*/"\"main\"",
|
Option<"topFunction", "top-function", "std::string", /*default=*/"\"main\"",
|
||||||
"The top function for HLS synthesis">,
|
"The top function for HLS synthesis">,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace scalehls {
|
||||||
|
|
||||||
/// Pragma optimization passes.
|
/// Pragma optimization passes.
|
||||||
std::unique_ptr<mlir::Pass> createPragmaDSEPass();
|
std::unique_ptr<mlir::Pass> createPragmaDSEPass();
|
||||||
std::unique_ptr<mlir::Pass> createInsertPipelinePragmaPass();
|
std::unique_ptr<mlir::Pass> createLoopPipeliningPass();
|
||||||
std::unique_ptr<mlir::Pass> createArrayPartitionPass();
|
std::unique_ptr<mlir::Pass> createArrayPartitionPass();
|
||||||
|
|
||||||
/// Loop optimization passes.
|
/// Loop optimization passes.
|
||||||
|
|
|
@ -35,17 +35,17 @@ def ArrayPartition : Pass<"array-partition", "FuncOp"> {
|
||||||
let constructor = "mlir::scalehls::createArrayPartitionPass()";
|
let constructor = "mlir::scalehls::createArrayPartitionPass()";
|
||||||
}
|
}
|
||||||
|
|
||||||
def InsertPipelinePragma : Pass<"insert-pipeline-pragma", "FuncOp"> {
|
def LoopPipelining : Pass<"loop-pipelining", "FuncOp"> {
|
||||||
let summary = "Insert pipeline pragma";
|
let summary = "Apply loop pipelining";
|
||||||
let description = [{
|
let description = [{
|
||||||
This insert-pipeline-pragma pass will insert pipeline pragma to the
|
This loop-pipelining pass will insert pipeline pragma to the innermost n-th
|
||||||
innermost loop level.
|
loop level, and automatically unroll all inner loops.
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let constructor = "mlir::scalehls::createInsertPipelinePragmaPass()";
|
let constructor = "mlir::scalehls::createLoopPipeliningPass()";
|
||||||
|
|
||||||
let options = [
|
let options = [
|
||||||
Option<"insertLevel", "insert-level", "unsigned", /*default=*/"1",
|
Option<"pipelineLevel", "pipeline-level", "unsigned", /*default=*/"1",
|
||||||
"Positive number: loop level to be pipelined (from innermost)">
|
"Positive number: loop level to be pipelined (from innermost)">
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "Dialect/HLSCpp/HLSCpp.h"
|
#include "Dialect/HLSCpp/HLSCpp.h"
|
||||||
#include "mlir/Analysis/AffineAnalysis.h"
|
#include "mlir/Analysis/AffineAnalysis.h"
|
||||||
#include "mlir/Analysis/AffineStructures.h"
|
#include "mlir/Analysis/AffineStructures.h"
|
||||||
|
#include "mlir/Analysis/LoopAnalysis.h"
|
||||||
#include "mlir/IR/Operation.h"
|
#include "mlir/IR/Operation.h"
|
||||||
#include "mlir/IR/PatternMatch.h"
|
#include "mlir/IR/PatternMatch.h"
|
||||||
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
|
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
|
||||||
|
@ -16,107 +17,6 @@ using namespace mlir;
|
||||||
using namespace scalehls;
|
using namespace scalehls;
|
||||||
using namespace hlscpp;
|
using namespace hlscpp;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// HLSCppAnalyzer Class Definition
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
bool HLSCppAnalyzer::visitOp(ArrayOp op) {
|
|
||||||
unsigned factor = 1;
|
|
||||||
if (getBoolAttrValue(op, "partition")) {
|
|
||||||
for (unsigned i = 0, e = op.getType().cast<ShapedType>().getRank(); i < e;
|
|
||||||
++i)
|
|
||||||
factor *= getPartitionFactor(op, i);
|
|
||||||
}
|
|
||||||
setAttrValue(op, "partition_num", factor);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HLSCppAnalyzer::visitOp(AffineForOp op) {
|
|
||||||
// If the current loop is annotated as unroll, all inner loops and itself are
|
|
||||||
// automatically unrolled.
|
|
||||||
if (getBoolAttrValue(op, "unroll")) {
|
|
||||||
op.walk([&](AffineForOp forOp) {
|
|
||||||
if (forOp.getLoopBody().getBlocks().size() != 1)
|
|
||||||
op.emitError("has zero or more than one basic blocks.");
|
|
||||||
if (failed(loopUnrollFull(forOp))) {
|
|
||||||
forOp.emitError("failed to be fully unrolled.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the current loop is annotated as pipeline, all intter loops are
|
|
||||||
// automatically unrolled.
|
|
||||||
if (getBoolAttrValue(op, "pipeline")) {
|
|
||||||
op.walk([&](AffineForOp forOp) {
|
|
||||||
if (forOp != op) {
|
|
||||||
if (forOp.getLoopBody().getBlocks().size() != 1)
|
|
||||||
op.emitError("has zero or more than one basic blocks.");
|
|
||||||
if (failed(loopUnrollFull(forOp))) {
|
|
||||||
forOp.emitError("failed to be fully unrolled.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// We assume loop contains a single basic block.
|
|
||||||
auto &body = op.getLoopBody();
|
|
||||||
if (body.getBlocks().size() != 1)
|
|
||||||
op.emitError("has zero or more than one basic blocks.");
|
|
||||||
|
|
||||||
// Recursively analyze all inner loops.
|
|
||||||
analyzeBlock(body.front());
|
|
||||||
|
|
||||||
// Set an attribute indicating the trip count. For now, we assume all loops
|
|
||||||
// have static loop bound.
|
|
||||||
if (!op.hasConstantLowerBound() || !op.hasConstantUpperBound())
|
|
||||||
op.emitError("has variable upper or lower bound.");
|
|
||||||
|
|
||||||
unsigned tripCount =
|
|
||||||
(op.getConstantUpperBound() - op.getConstantLowerBound()) / op.getStep();
|
|
||||||
setAttrValue(op, "trip_count", tripCount);
|
|
||||||
|
|
||||||
// Set attributes indicating this loop can be flatten or not.
|
|
||||||
unsigned opNum = 0;
|
|
||||||
unsigned forNum = 0;
|
|
||||||
bool innerFlatten = false;
|
|
||||||
|
|
||||||
for (auto &bodyOp : body.front()) {
|
|
||||||
if (!isa<AffineYieldOp>(bodyOp))
|
|
||||||
opNum += 1;
|
|
||||||
if (isa<AffineForOp>(bodyOp)) {
|
|
||||||
forNum += 1;
|
|
||||||
innerFlatten = getBoolAttrValue(&bodyOp, "flatten");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (forNum == 0 || (opNum == 1 && innerFlatten))
|
|
||||||
setAttrValue(op, "flatten", true);
|
|
||||||
else
|
|
||||||
setAttrValue(op, "flatten", false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HLSCppAnalyzer::visitOp(AffineIfOp op) { return true; }
|
|
||||||
|
|
||||||
void HLSCppAnalyzer::analyzeBlock(Block &block) {
|
|
||||||
for (auto &op : block) {
|
|
||||||
if (dispatchVisitor(&op))
|
|
||||||
continue;
|
|
||||||
op.emitError("can't be correctly analyzed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HLSCppAnalyzer::analyzeFunc(FuncOp func) {
|
|
||||||
if (func.getBlocks().size() != 1)
|
|
||||||
func.emitError("has zero or more than one basic blocks.");
|
|
||||||
|
|
||||||
analyzeBlock(func.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// HLSCppEstimator Class Definition
|
// HLSCppEstimator Class Definition
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -505,6 +405,48 @@ void HLSCppEstimator::estimateFunc(FuncOp func) {
|
||||||
if (func.getBlocks().size() != 1)
|
if (func.getBlocks().size() != 1)
|
||||||
func.emitError("has zero or more than one basic blocks.");
|
func.emitError("has zero or more than one basic blocks.");
|
||||||
|
|
||||||
|
// Extract all static parameters and current pragma configurations.
|
||||||
|
func.walk([&](ArrayOp op) {
|
||||||
|
unsigned factor = 1;
|
||||||
|
if (getBoolAttrValue(op, "partition")) {
|
||||||
|
for (unsigned i = 0, e = op.getType().cast<ShapedType>().getRank(); i < e;
|
||||||
|
++i)
|
||||||
|
factor *= getPartitionFactor(op, i);
|
||||||
|
}
|
||||||
|
setAttrValue(op, "partition_num", factor);
|
||||||
|
});
|
||||||
|
|
||||||
|
func.walk([&](AffineForOp op) {
|
||||||
|
// We assume loop contains a single basic block.
|
||||||
|
auto &body = op.getLoopBody();
|
||||||
|
if (body.getBlocks().size() != 1)
|
||||||
|
op.emitError("has zero or more than one basic blocks.");
|
||||||
|
|
||||||
|
// Set an attribute indicating the trip count. For now, we assume all
|
||||||
|
// loops have static loop bound.
|
||||||
|
unsigned tripCount = getConstantTripCount(op).getValue();
|
||||||
|
setAttrValue(op, "trip_count", tripCount);
|
||||||
|
|
||||||
|
// Set attributes indicating this loop can be flatten or not.
|
||||||
|
unsigned opNum = 0;
|
||||||
|
unsigned forNum = 0;
|
||||||
|
bool innerFlatten = false;
|
||||||
|
|
||||||
|
for (auto &bodyOp : body.front()) {
|
||||||
|
if (!isa<AffineYieldOp>(bodyOp))
|
||||||
|
opNum += 1;
|
||||||
|
if (isa<AffineForOp>(bodyOp)) {
|
||||||
|
forNum += 1;
|
||||||
|
innerFlatten = getBoolAttrValue(&bodyOp, "flatten");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forNum == 0 || (opNum == 1 && innerFlatten))
|
||||||
|
setAttrValue(op, "flatten", true);
|
||||||
|
else
|
||||||
|
setAttrValue(op, "flatten", false);
|
||||||
|
});
|
||||||
|
|
||||||
estimateBlock(func.front());
|
estimateBlock(func.front());
|
||||||
|
|
||||||
MemAccessDict dict;
|
MemAccessDict dict;
|
||||||
|
@ -521,25 +463,13 @@ void HLSCppEstimator::estimateFunc(FuncOp func) {
|
||||||
namespace {
|
namespace {
|
||||||
struct QoREstimation : public scalehls::QoREstimationBase<QoREstimation> {
|
struct QoREstimation : public scalehls::QoREstimationBase<QoREstimation> {
|
||||||
void runOnOperation() override {
|
void runOnOperation() override {
|
||||||
auto builder = OpBuilder(getOperation());
|
auto module = getOperation();
|
||||||
|
auto builder = OpBuilder(module);
|
||||||
// Extract all static parameters and current pragma configurations.
|
|
||||||
HLSCppAnalyzer analyzer(builder);
|
|
||||||
analyzer.analyzeFunc(getOperation());
|
|
||||||
|
|
||||||
// Canonicalize the analyzed IR.
|
|
||||||
OwningRewritePatternList patterns;
|
|
||||||
|
|
||||||
auto *context = &getContext();
|
|
||||||
for (auto *op : context->getRegisteredOperations())
|
|
||||||
op->getCanonicalizationPatterns(patterns, context);
|
|
||||||
|
|
||||||
Operation *op = getOperation();
|
|
||||||
applyPatternsAndFoldGreedily(op->getRegions(), std::move(patterns));
|
|
||||||
|
|
||||||
// Estimate performance and resource utilization.
|
// Estimate performance and resource utilization.
|
||||||
HLSCppEstimator estimator(builder, targetSpec);
|
HLSCppEstimator estimator(builder, targetSpec);
|
||||||
estimator.estimateFunc(getOperation());
|
for (auto func : module.getOps<FuncOp>())
|
||||||
|
estimator.estimateFunc(func);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -29,7 +29,7 @@ void ConvertToHLSCpp::runOnOperation() {
|
||||||
if (!func.getAttr("dataflow"))
|
if (!func.getAttr("dataflow"))
|
||||||
func.setAttr("dataflow", builder.getBoolAttr(false));
|
func.setAttr("dataflow", builder.getBoolAttr(false));
|
||||||
|
|
||||||
if (func.getName() == TopFunction)
|
if (func.getName() == topFunction)
|
||||||
func.setAttr("top_function", builder.getBoolAttr(true));
|
func.setAttr("top_function", builder.getBoolAttr(true));
|
||||||
else
|
else
|
||||||
func.setAttr("top_function", builder.getBoolAttr(false));
|
func.setAttr("top_function", builder.getBoolAttr(false));
|
||||||
|
@ -87,7 +87,7 @@ void ConvertToHLSCpp::runOnOperation() {
|
||||||
// an AssignOp, it will always not be annotated as interface. This
|
// an AssignOp, it will always not be annotated as interface. This
|
||||||
// is acceptable because AssignOp is only used to handle some weird
|
// is acceptable because AssignOp is only used to handle some weird
|
||||||
// corner cases that rarely happen.
|
// corner cases that rarely happen.
|
||||||
if (!arrayOp.getAttr("interface") && func.getName() == TopFunction) {
|
if (!arrayOp.getAttr("interface") && func.getName() == topFunction) {
|
||||||
// Only if when the array is an block arguments or a returned
|
// Only if when the array is an block arguments or a returned
|
||||||
// value, it will be annotated as interface.
|
// value, it will be annotated as interface.
|
||||||
bool interfaceFlag =
|
bool interfaceFlag =
|
||||||
|
|
|
@ -111,24 +111,24 @@ void ArrayPartition::runOnOperation() {
|
||||||
|
|
||||||
// Apply array partition.
|
// Apply array partition.
|
||||||
for (auto forOp : func.getOps<mlir::AffineForOp>()) {
|
for (auto forOp : func.getOps<mlir::AffineForOp>()) {
|
||||||
auto outermost = getPipelineLoop(forOp);
|
if (auto outermost = getPipelineLoop(forOp)) {
|
||||||
|
// Collect memory access information.
|
||||||
|
MemAccessDict loadDict;
|
||||||
|
outermost.walk([&](mlir::AffineLoadOp loadOp) {
|
||||||
|
auto arrayOp = cast<ArrayOp>(loadOp.getMemRef().getDefiningOp());
|
||||||
|
loadDict[arrayOp].push_back(loadOp);
|
||||||
|
});
|
||||||
|
|
||||||
// Collect memory access information.
|
MemAccessDict storeDict;
|
||||||
MemAccessDict loadDict;
|
outermost.walk([&](mlir::AffineStoreOp storeOp) {
|
||||||
outermost.walk([&](mlir::AffineLoadOp loadOp) {
|
auto arrayOp = cast<ArrayOp>(storeOp.getMemRef().getDefiningOp());
|
||||||
auto arrayOp = cast<ArrayOp>(loadOp.getMemRef().getDefiningOp());
|
storeDict[arrayOp].push_back(storeOp);
|
||||||
loadDict[arrayOp].push_back(loadOp);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
MemAccessDict storeDict;
|
// Apply array partition pragma.
|
||||||
outermost.walk([&](mlir::AffineStoreOp storeOp) {
|
applyArrayPartition<mlir::AffineLoadOp>(loadDict, builder);
|
||||||
auto arrayOp = cast<ArrayOp>(storeOp.getMemRef().getDefiningOp());
|
applyArrayPartition<mlir::AffineStoreOp>(storeDict, builder);
|
||||||
storeDict[arrayOp].push_back(storeOp);
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Apply array partition pragma.
|
|
||||||
applyArrayPartition<mlir::AffineLoadOp>(loadDict, builder);
|
|
||||||
applyArrayPartition<mlir::AffineStoreOp>(storeDict, builder);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,12 @@ using namespace mlir;
|
||||||
using namespace scalehls;
|
using namespace scalehls;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct InsertPipelinePragma
|
struct LoopPipelining : public LoopPipeliningBase<LoopPipelining> {
|
||||||
: public InsertPipelinePragmaBase<InsertPipelinePragma> {
|
|
||||||
void runOnOperation() override;
|
void runOnOperation() override;
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void InsertPipelinePragma::runOnOperation() {
|
void LoopPipelining::runOnOperation() {
|
||||||
auto func = getOperation();
|
auto func = getOperation();
|
||||||
auto builder = OpBuilder(func);
|
auto builder = OpBuilder(func);
|
||||||
|
|
||||||
|
@ -30,8 +29,8 @@ void InsertPipelinePragma::runOnOperation() {
|
||||||
forOp.walk([&](mlir::AffineForOp loop) { nestedLoops.push_back(loop); });
|
forOp.walk([&](mlir::AffineForOp loop) { nestedLoops.push_back(loop); });
|
||||||
|
|
||||||
auto targetLoop = nestedLoops.back();
|
auto targetLoop = nestedLoops.back();
|
||||||
if (nestedLoops.size() > insertLevel)
|
if (nestedLoops.size() > pipelineLevel)
|
||||||
targetLoop = *std::next(nestedLoops.begin(), insertLevel);
|
targetLoop = *std::next(nestedLoops.begin(), pipelineLevel);
|
||||||
|
|
||||||
targetLoop.setAttr("pipeline", builder.getBoolAttr(true));
|
targetLoop.setAttr("pipeline", builder.getBoolAttr(true));
|
||||||
|
|
||||||
|
@ -53,6 +52,6 @@ void InsertPipelinePragma::runOnOperation() {
|
||||||
std::move(patterns));
|
std::move(patterns));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<mlir::Pass> scalehls::createInsertPipelinePragmaPass() {
|
std::unique_ptr<mlir::Pass> scalehls::createLoopPipeliningPass() {
|
||||||
return std::make_unique<InsertPipelinePragma>();
|
return std::make_unique<LoopPipelining>();
|
||||||
}
|
}
|
|
@ -40,7 +40,6 @@ void RemoveVarLoopBound::runOnOperation() {
|
||||||
|
|
||||||
// For now, only if the variable bound is the induction variable of
|
// For now, only if the variable bound is the induction variable of
|
||||||
// one of the outer loops, the removal is possible.
|
// one of the outer loops, the removal is possible.
|
||||||
unsigned idx = 0;
|
|
||||||
if (auto valOwner = getForInductionVarOwner(val)) {
|
if (auto valOwner = getForInductionVarOwner(val)) {
|
||||||
if (valOwner.hasConstantUpperBound()) {
|
if (valOwner.hasConstantUpperBound()) {
|
||||||
// Set new constant loop bound.
|
// Set new constant loop bound.
|
||||||
|
|
|
@ -34,10 +34,10 @@ alp=-affine-loop-perfection
|
||||||
rvb=-remove-var-loop-bound
|
rvb=-remove-var-loop-bound
|
||||||
par=-array-partition
|
par=-array-partition
|
||||||
|
|
||||||
p0=-insert-pipeline-pragma="insert-level=0"
|
p0=-loop-pipelining="pipeline-level=0"
|
||||||
p1=-insert-pipeline-pragma="insert-level=1"
|
p1=-loop-pipelining="pipeline-level=1"
|
||||||
p2=-insert-pipeline-pragma="insert-level=2"
|
p2=-loop-pipelining="pipeline-level=2"
|
||||||
p3=-insert-pipeline-pragma="insert-level=3"
|
p3=-loop-pipelining="pipeline-level=3"
|
||||||
|
|
||||||
u1=-affine-loop-unroll="unroll-full unroll-num-reps=1"
|
u1=-affine-loop-unroll="unroll-full unroll-num-reps=1"
|
||||||
u2=-affine-loop-unroll="unroll-full unroll-num-reps=2"
|
u2=-affine-loop-unroll="unroll-full unroll-num-reps=2"
|
||||||
|
@ -96,32 +96,32 @@ do
|
||||||
16) scalehls-opt $hta $alp $rvb $cth="$name" "$p3" $par $can $file | scalehls-translate $emit -o $output ;;
|
16) scalehls-opt $hta $alp $rvb $cth="$name" "$p3" $par $can $file | scalehls-translate $emit -o $output ;;
|
||||||
|
|
||||||
# Apply ... + 1st-level loop tiling + pipeline.
|
# Apply ... + 1st-level loop tiling + pipeline.
|
||||||
17) scalehls-opt $hta $alp $rvb "$t1s2" $cth="$name" "$p1" "$u1" $can $file | scalehls-translate $emit -o $output ;;
|
17) scalehls-opt $hta $alp $rvb "$t1s2" $cth="$name" "$p1" $can $file | scalehls-translate $emit -o $output ;;
|
||||||
18) scalehls-opt $hta $alp $rvb "$t1s4" $cth="$name" "$p1" "$u1" $can $file | scalehls-translate $emit -o $output ;;
|
18) scalehls-opt $hta $alp $rvb "$t1s4" $cth="$name" "$p1" $can $file | scalehls-translate $emit -o $output ;;
|
||||||
19) scalehls-opt $hta $alp $rvb "$t1s8" $cth="$name" "$p1" "$u1" $can $file | scalehls-translate $emit -o $output ;;
|
19) scalehls-opt $hta $alp $rvb "$t1s8" $cth="$name" "$p1" $can $file | scalehls-translate $emit -o $output ;;
|
||||||
|
|
||||||
# Apply ... + 1st-level loop tiling + pipeline + array partition.
|
# Apply ... + 1st-level loop tiling + pipeline + array partition.
|
||||||
20) scalehls-opt $hta $alp $rvb "$t1s2" $cth="$name" "$p1" "$u1" $par $can $file | scalehls-translate $emit -o $output ;;
|
20) scalehls-opt $hta $alp $rvb "$t1s2" $cth="$name" "$p1" $par $can $file | scalehls-translate $emit -o $output ;;
|
||||||
21) scalehls-opt $hta $alp $rvb "$t1s4" $cth="$name" "$p1" "$u1" $par $can $file | scalehls-translate $emit -o $output ;;
|
21) scalehls-opt $hta $alp $rvb "$t1s4" $cth="$name" "$p1" $par $can $file | scalehls-translate $emit -o $output ;;
|
||||||
22) scalehls-opt $hta $alp $rvb "$t1s8" $cth="$name" "$p1" "$u1" $par $can $file | scalehls-translate $emit -o $output ;;
|
22) scalehls-opt $hta $alp $rvb "$t1s8" $cth="$name" "$p1" $par $can $file | scalehls-translate $emit -o $output ;;
|
||||||
|
|
||||||
# Apply ... + 2nd-level loop tiling + pipeline.
|
# Apply ... + 2nd-level loop tiling + pipeline.
|
||||||
23) scalehls-opt $hta $alp $rvb "$t2s2" $cth="$name" "$p2" "$u2" $can $file | scalehls-translate $emit -o $output ;;
|
23) scalehls-opt $hta $alp $rvb "$t2s2" $cth="$name" "$p2" $can $file | scalehls-translate $emit -o $output ;;
|
||||||
24) scalehls-opt $hta $alp $rvb "$t2s4" $cth="$name" "$p2" "$u2" $can $file | scalehls-translate $emit -o $output ;;
|
24) scalehls-opt $hta $alp $rvb "$t2s4" $cth="$name" "$p2" $can $file | scalehls-translate $emit -o $output ;;
|
||||||
25) scalehls-opt $hta $alp $rvb "$t2s8" $cth="$name" "$p2" "$u2" $can $file | scalehls-translate $emit -o $output ;;
|
25) scalehls-opt $hta $alp $rvb "$t2s8" $cth="$name" "$p2" $can $file | scalehls-translate $emit -o $output ;;
|
||||||
|
|
||||||
# Apply ... + 2nd-level loop tiling + pipeline + array partition.
|
# Apply ... + 2nd-level loop tiling + pipeline + array partition.
|
||||||
26) scalehls-opt $hta $alp $rvb "$t2s2" $cth="$name" "$p2" "$u2" $par $can $file | scalehls-translate $emit -o $output ;;
|
26) scalehls-opt $hta $alp $rvb "$t2s2" $cth="$name" "$p2" $par $can $file | scalehls-translate $emit -o $output ;;
|
||||||
27) scalehls-opt $hta $alp $rvb "$t2s4" $cth="$name" "$p2" "$u2" $par $can $file | scalehls-translate $emit -o $output ;;
|
27) scalehls-opt $hta $alp $rvb "$t2s4" $cth="$name" "$p2" $par $can $file | scalehls-translate $emit -o $output ;;
|
||||||
28) scalehls-opt $hta $alp $rvb "$t2s8" $cth="$name" "$p2" "$u2" $par $can $file | scalehls-translate $emit -o $output ;;
|
28) scalehls-opt $hta $alp $rvb "$t2s8" $cth="$name" "$p2" $par $can $file | scalehls-translate $emit -o $output ;;
|
||||||
|
|
||||||
# Apply ... + 3rd-level loop tiling + pipeline.
|
# Apply ... + 3rd-level loop tiling + pipeline.
|
||||||
29) scalehls-opt $hta $alp $rvb "$t3s2" $cth="$name" "$p3" "$u3" $can $file | scalehls-translate $emit -o $output ;;
|
29) scalehls-opt $hta $alp $rvb "$t3s2" $cth="$name" "$p3" $can $file | scalehls-translate $emit -o $output ;;
|
||||||
30) scalehls-opt $hta $alp $rvb "$t3s4" $cth="$name" "$p3" "$u3" $can $file | scalehls-translate $emit -o $output ;;
|
30) scalehls-opt $hta $alp $rvb "$t3s4" $cth="$name" "$p3" $can $file | scalehls-translate $emit -o $output ;;
|
||||||
|
|
||||||
# Apply ... + 3rd-level loop tiling + pipeline + array partition.
|
# Apply ... + 3rd-level loop tiling + pipeline + array partition.
|
||||||
31) scalehls-opt $hta $alp $rvb "$t3s2" $cth="$name" "$p3" "$u3" $par $can $file | scalehls-translate $emit -o $output ;;
|
31) scalehls-opt $hta $alp $rvb "$t3s2" $cth="$name" "$p3" $par $can $file | scalehls-translate $emit -o $output ;;
|
||||||
32) scalehls-opt $hta $alp $rvb "$t3s4" $cth="$name" "$p3" "$u3" $par $can $file | scalehls-translate $emit -o $output ;;
|
32) scalehls-opt $hta $alp $rvb "$t3s4" $cth="$name" "$p3" $par $can $file | scalehls-translate $emit -o $output ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
// RUN: scalehls-opt -insert-pipeline-pragma %s | FileCheck %s
|
|
||||||
|
|
||||||
// CHECK-LABEL: func @test_for
|
|
||||||
func @test_for() {
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
// RUN: scalehls-opt -loop-pipelining %s | FileCheck %s
|
||||||
|
|
||||||
|
// CHECK-LABEL: func @test_for
|
||||||
|
func @test_for() {
|
||||||
|
return
|
||||||
|
}
|
Loading…
Reference in New Issue