[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"
|
||||
|
||||
def QoREstimation : Pass<"qor-estimation", "FuncOp"> {
|
||||
def QoREstimation : Pass<"qor-estimation", "ModuleOp"> {
|
||||
let summary = "Estimate the performance and resource utilization";
|
||||
let description = [{
|
||||
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",
|
||||
/*default=*/"\"../config/target-spec.ini\"",
|
||||
"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 {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// HLSCppToolBase Class Declaration
|
||||
// HLSCppToolBase Class Declaration and Definition
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class HLSCppToolBase {
|
||||
|
@ -99,26 +99,6 @@ public:
|
|||
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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -17,7 +17,7 @@ def ConvertToHLSCpp : Pass<"convert-to-hlscpp", "FuncOp"> {
|
|||
let constructor = "mlir::scalehls::createConvertToHLSCppPass()";
|
||||
|
||||
let options = [
|
||||
Option<"TopFunction", "top-function", "std::string", /*default=*/"\"main\"",
|
||||
Option<"topFunction", "top-function", "std::string", /*default=*/"\"main\"",
|
||||
"The top function for HLS synthesis">,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace scalehls {
|
|||
|
||||
/// Pragma optimization passes.
|
||||
std::unique_ptr<mlir::Pass> createPragmaDSEPass();
|
||||
std::unique_ptr<mlir::Pass> createInsertPipelinePragmaPass();
|
||||
std::unique_ptr<mlir::Pass> createLoopPipeliningPass();
|
||||
std::unique_ptr<mlir::Pass> createArrayPartitionPass();
|
||||
|
||||
/// Loop optimization passes.
|
||||
|
|
|
@ -35,17 +35,17 @@ def ArrayPartition : Pass<"array-partition", "FuncOp"> {
|
|||
let constructor = "mlir::scalehls::createArrayPartitionPass()";
|
||||
}
|
||||
|
||||
def InsertPipelinePragma : Pass<"insert-pipeline-pragma", "FuncOp"> {
|
||||
let summary = "Insert pipeline pragma";
|
||||
def LoopPipelining : Pass<"loop-pipelining", "FuncOp"> {
|
||||
let summary = "Apply loop pipelining";
|
||||
let description = [{
|
||||
This insert-pipeline-pragma pass will insert pipeline pragma to the
|
||||
innermost loop level.
|
||||
This loop-pipelining pass will insert pipeline pragma to the innermost n-th
|
||||
loop level, and automatically unroll all inner loops.
|
||||
}];
|
||||
|
||||
let constructor = "mlir::scalehls::createInsertPipelinePragmaPass()";
|
||||
let constructor = "mlir::scalehls::createLoopPipeliningPass()";
|
||||
|
||||
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)">
|
||||
];
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "Dialect/HLSCpp/HLSCpp.h"
|
||||
#include "mlir/Analysis/AffineAnalysis.h"
|
||||
#include "mlir/Analysis/AffineStructures.h"
|
||||
#include "mlir/Analysis/LoopAnalysis.h"
|
||||
#include "mlir/IR/Operation.h"
|
||||
#include "mlir/IR/PatternMatch.h"
|
||||
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
|
||||
|
@ -16,107 +17,6 @@ using namespace mlir;
|
|||
using namespace scalehls;
|
||||
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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -505,6 +405,48 @@ void HLSCppEstimator::estimateFunc(FuncOp func) {
|
|||
if (func.getBlocks().size() != 1)
|
||||
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());
|
||||
|
||||
MemAccessDict dict;
|
||||
|
@ -521,25 +463,13 @@ void HLSCppEstimator::estimateFunc(FuncOp func) {
|
|||
namespace {
|
||||
struct QoREstimation : public scalehls::QoREstimationBase<QoREstimation> {
|
||||
void runOnOperation() override {
|
||||
auto builder = OpBuilder(getOperation());
|
||||
|
||||
// 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));
|
||||
auto module = getOperation();
|
||||
auto builder = OpBuilder(module);
|
||||
|
||||
// Estimate performance and resource utilization.
|
||||
HLSCppEstimator estimator(builder, targetSpec);
|
||||
estimator.estimateFunc(getOperation());
|
||||
for (auto func : module.getOps<FuncOp>())
|
||||
estimator.estimateFunc(func);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
|
|
@ -29,7 +29,7 @@ void ConvertToHLSCpp::runOnOperation() {
|
|||
if (!func.getAttr("dataflow"))
|
||||
func.setAttr("dataflow", builder.getBoolAttr(false));
|
||||
|
||||
if (func.getName() == TopFunction)
|
||||
if (func.getName() == topFunction)
|
||||
func.setAttr("top_function", builder.getBoolAttr(true));
|
||||
else
|
||||
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
|
||||
// is acceptable because AssignOp is only used to handle some weird
|
||||
// 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
|
||||
// value, it will be annotated as interface.
|
||||
bool interfaceFlag =
|
||||
|
|
|
@ -111,8 +111,7 @@ void ArrayPartition::runOnOperation() {
|
|||
|
||||
// Apply array partition.
|
||||
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) {
|
||||
|
@ -131,6 +130,7 @@ void ArrayPartition::runOnOperation() {
|
|||
applyArrayPartition<mlir::AffineStoreOp>(storeDict, builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<mlir::Pass> scalehls::createArrayPartitionPass() {
|
||||
return std::make_unique<ArrayPartition>();
|
||||
|
|
|
@ -14,13 +14,12 @@ using namespace mlir;
|
|||
using namespace scalehls;
|
||||
|
||||
namespace {
|
||||
struct InsertPipelinePragma
|
||||
: public InsertPipelinePragmaBase<InsertPipelinePragma> {
|
||||
struct LoopPipelining : public LoopPipeliningBase<LoopPipelining> {
|
||||
void runOnOperation() override;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
void InsertPipelinePragma::runOnOperation() {
|
||||
void LoopPipelining::runOnOperation() {
|
||||
auto func = getOperation();
|
||||
auto builder = OpBuilder(func);
|
||||
|
||||
|
@ -30,8 +29,8 @@ void InsertPipelinePragma::runOnOperation() {
|
|||
forOp.walk([&](mlir::AffineForOp loop) { nestedLoops.push_back(loop); });
|
||||
|
||||
auto targetLoop = nestedLoops.back();
|
||||
if (nestedLoops.size() > insertLevel)
|
||||
targetLoop = *std::next(nestedLoops.begin(), insertLevel);
|
||||
if (nestedLoops.size() > pipelineLevel)
|
||||
targetLoop = *std::next(nestedLoops.begin(), pipelineLevel);
|
||||
|
||||
targetLoop.setAttr("pipeline", builder.getBoolAttr(true));
|
||||
|
||||
|
@ -53,6 +52,6 @@ void InsertPipelinePragma::runOnOperation() {
|
|||
std::move(patterns));
|
||||
}
|
||||
|
||||
std::unique_ptr<mlir::Pass> scalehls::createInsertPipelinePragmaPass() {
|
||||
return std::make_unique<InsertPipelinePragma>();
|
||||
std::unique_ptr<mlir::Pass> scalehls::createLoopPipeliningPass() {
|
||||
return std::make_unique<LoopPipelining>();
|
||||
}
|
|
@ -40,7 +40,6 @@ void RemoveVarLoopBound::runOnOperation() {
|
|||
|
||||
// For now, only if the variable bound is the induction variable of
|
||||
// one of the outer loops, the removal is possible.
|
||||
unsigned idx = 0;
|
||||
if (auto valOwner = getForInductionVarOwner(val)) {
|
||||
if (valOwner.hasConstantUpperBound()) {
|
||||
// Set new constant loop bound.
|
||||
|
|
|
@ -34,10 +34,10 @@ alp=-affine-loop-perfection
|
|||
rvb=-remove-var-loop-bound
|
||||
par=-array-partition
|
||||
|
||||
p0=-insert-pipeline-pragma="insert-level=0"
|
||||
p1=-insert-pipeline-pragma="insert-level=1"
|
||||
p2=-insert-pipeline-pragma="insert-level=2"
|
||||
p3=-insert-pipeline-pragma="insert-level=3"
|
||||
p0=-loop-pipelining="pipeline-level=0"
|
||||
p1=-loop-pipelining="pipeline-level=1"
|
||||
p2=-loop-pipelining="pipeline-level=2"
|
||||
p3=-loop-pipelining="pipeline-level=3"
|
||||
|
||||
u1=-affine-loop-unroll="unroll-full unroll-num-reps=1"
|
||||
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 ;;
|
||||
|
||||
# Apply ... + 1st-level loop tiling + pipeline.
|
||||
17) scalehls-opt $hta $alp $rvb "$t1s2" $cth="$name" "$p1" "$u1" $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 ;;
|
||||
19) scalehls-opt $hta $alp $rvb "$t1s8" $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" $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.
|
||||
20) scalehls-opt $hta $alp $rvb "$t1s2" $cth="$name" "$p1" "$u1" $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 ;;
|
||||
22) scalehls-opt $hta $alp $rvb "$t1s8" $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" $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.
|
||||
23) scalehls-opt $hta $alp $rvb "$t2s2" $cth="$name" "$p2" "$u2" $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 ;;
|
||||
25) scalehls-opt $hta $alp $rvb "$t2s8" $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" $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.
|
||||
26) scalehls-opt $hta $alp $rvb "$t2s2" $cth="$name" "$p2" "$u2" $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 ;;
|
||||
28) scalehls-opt $hta $alp $rvb "$t2s8" $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" $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.
|
||||
29) scalehls-opt $hta $alp $rvb "$t3s2" $cth="$name" "$p3" "$u3" $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 ;;
|
||||
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" $can $file | scalehls-translate $emit -o $output ;;
|
||||
|
||||
# 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 ;;
|
||||
32) scalehls-opt $hta $alp $rvb "$t3s4" $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" $par $can $file | scalehls-translate $emit -o $output ;;
|
||||
esac
|
||||
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