[LoopPipelining] recursively fully unroll all inner loops until no failure are met
This commit is contained in:
parent
47837eee6e
commit
4a594c9303
|
@ -40,7 +40,7 @@ $ # Loop and pragma-level optimizations, performance estimation, and C++ code ge
|
|||
$ scalehls-opt samples/polybench/syrk.mlir \
|
||||
-affine-loop-perfection -remove-variable-bound -affine-loop-normalize \
|
||||
-partial-affine-loop-tile="tile-level=1 tile-size=4" \
|
||||
-legalize-to-hlscpp="top-function=test_syrk" -loop-pipelining="pipeline-level=1" \
|
||||
-legalize-to-hlscpp="top-func=test_syrk" -loop-pipelining="pipeline-level=1" \
|
||||
-affine-store-forward -simplify-memref-access -array-partition -cse -canonicalize \
|
||||
-qor-estimation="target-spec=config/target-spec.ini" \
|
||||
| scalehls-translate -emit-hlscpp
|
||||
|
@ -55,7 +55,7 @@ $ benchmark-gen -type "cnn" -config "config/cnn-config.ini" -number 1 \
|
|||
| scalehls-opt -legalize-dataflow -split-function \
|
||||
-hlskernel-bufferize -hlskernel-to-affine -func-bufferize \
|
||||
-affine-loop-perfection -affine-loop-normalize \
|
||||
-legalize-to-hlscpp="top-function=auto_gen_cnn" \
|
||||
-legalize-to-hlscpp="top-func=auto_gen_cnn" \
|
||||
-affine-store-forward -simplify-memref-access -cse -canonicalize \
|
||||
-qor-estimation="target-spec=config/target-spec.ini" \
|
||||
| scalehls-translate -emit-hlscpp
|
||||
|
@ -85,7 +85,7 @@ $ # Legalize the output of ONNX-MLIR, optimize and emit C++ code.
|
|||
$ scalehls-opt resnet18.mlir -legalize-onnx -affine-loop-normalize -canonicalize \
|
||||
-legalize-dataflow="min-gran=2 insert-copy=false" -split-function \
|
||||
-convert-linalg-to-affine-loops -affine-loop-fusion \
|
||||
-legalize-to-hlscpp="top-function=main_graph" \
|
||||
-legalize-to-hlscpp="top-func=main_graph" \
|
||||
| scalehls-translate -emit-hlscpp
|
||||
```
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ def LegalizeToHLSCpp : Pass<"legalize-to-hlscpp", "FuncOp"> {
|
|||
let constructor = "mlir::scalehls::createLegalizeToHLSCppPass()";
|
||||
|
||||
let options = [
|
||||
Option<"topFunction", "top-function", "std::string", /*default=*/"\"main\"",
|
||||
Option<"topFunc", "top-func", "std::string", /*default=*/"\"main\"",
|
||||
"The top function for HLS synthesis">,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ def FuncPipelining : Pass<"func-pipelining", "FuncOp"> {
|
|||
let constructor = "mlir::scalehls::createFuncPipeliningPass()";
|
||||
|
||||
let options = [
|
||||
Option<"targetFunction", "target-function", "std::string",
|
||||
Option<"targetFunc", "target-func", "std::string",
|
||||
/*default=*/"\"main\"", "The target function to be pipelined">
|
||||
];
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ void LegalizeToHLSCpp::runOnOperation() {
|
|||
if (!func->getAttr("dataflow"))
|
||||
func->setAttr("dataflow", builder.getBoolAttr(false));
|
||||
|
||||
if (func.getName() == topFunction)
|
||||
if (func.getName() == topFunc)
|
||||
func->setAttr("top_function", builder.getBoolAttr(true));
|
||||
else
|
||||
func->setAttr("top_function", builder.getBoolAttr(false));
|
||||
|
|
|
@ -18,7 +18,7 @@ struct FuncPipelining : public FuncPipeliningBase<FuncPipelining> {
|
|||
auto func = getOperation();
|
||||
auto builder = OpBuilder(func);
|
||||
|
||||
if (func.getName() == targetFunction) {
|
||||
if (func.getName() == targetFunc) {
|
||||
applyFuncPipelining(func, builder);
|
||||
|
||||
// Canonicalize the IR after function pipelining.
|
||||
|
@ -35,7 +35,14 @@ struct FuncPipelining : public FuncPipeliningBase<FuncPipelining> {
|
|||
/// Apply function pipelining to the input function, all contained loops are
|
||||
/// automatically fully unrolled.
|
||||
bool scalehls::applyFuncPipelining(FuncOp func, OpBuilder &builder) {
|
||||
func.walk([&](AffineForOp loop) { loopUnrollFull(loop); });
|
||||
bool hasFullyUnrolled = false;
|
||||
while (hasFullyUnrolled == false) {
|
||||
hasFullyUnrolled = true;
|
||||
func.walk([&](AffineForOp loop) {
|
||||
if (failed(loopUnrollFull(loop)))
|
||||
hasFullyUnrolled = false;
|
||||
});
|
||||
}
|
||||
|
||||
func->setAttr("pipeline", builder.getBoolAttr(true));
|
||||
func->setAttr("dataflow", builder.getBoolAttr(false));
|
||||
|
|
|
@ -63,10 +63,15 @@ bool scalehls::applyLoopPipelining(AffineForOp targetLoop, OpBuilder &builder) {
|
|||
targetLoop->setAttr("pipeline", builder.getBoolAttr(true));
|
||||
|
||||
// All inner loops of the pipelined loop are automatically unrolled.
|
||||
targetLoop.walk([&](AffineForOp loop) {
|
||||
if (loop != targetLoop)
|
||||
loopUnrollFull(loop);
|
||||
});
|
||||
bool hasFullyUnrolled = false;
|
||||
while (hasFullyUnrolled == false) {
|
||||
hasFullyUnrolled = true;
|
||||
targetLoop.walk([&](AffineForOp loop) {
|
||||
if (loop != targetLoop)
|
||||
if (failed(loopUnrollFull(loop)))
|
||||
hasFullyUnrolled = false;
|
||||
});
|
||||
}
|
||||
|
||||
// All outer loops that perfect nest the pipelined loop can be flattened.
|
||||
SmallVector<AffineForOp, 4> flattenedLoops;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: scalehls-opt -legalize-to-hlscpp="top-function=test_assign" %s | FileCheck %s
|
||||
// RUN: scalehls-opt -legalize-to-hlscpp="top-func=test_assign" %s | FileCheck %s
|
||||
|
||||
// CHECK-LABEL: func @test_assign(
|
||||
// CHECK-SAME: %arg0: f32, %arg1: memref<16xf32, 1>) -> (f32, memref<16xf32, 1>, i32, memref<2x2xi32, 1>) attributes {dataflow = false, top_function = true} {
|
||||
|
|
Loading…
Reference in New Issue