[Samples] add ablation test script; update Readme; bug fix in InsertPipelinePragma

This commit is contained in:
Hanchen Ye 2020-12-06 23:48:20 -06:00
parent 939f01cd05
commit 7cb98f3a87
8 changed files with 127 additions and 46 deletions

2
.gitignore vendored
View File

@ -1,7 +1,9 @@
.vscode
.ipynb_checkpoints
build
samples/hls_proj
samples/cpp_src
samples/test_results
*.log

View File

@ -30,7 +30,7 @@ $ cmake -G Ninja .. \
$ ninja check-scalehls
```
### 3. Test ScaleHLS
### 3. Try ScaleHLS
After the installation and test successfully completed, you should be able to play with
```sh
$ export PATH=$SCALEHLS_DIR/build/bin:$PATH
@ -45,10 +45,11 @@ $
$ scalehls-opt -qor-estimation test/Analysis/QoREstimation/test_for.mlir
```
If Vivado HLS (2019.1 tested) is installed on your machine, running the following script will report the HLS results for some benchmarks.
### 4. Ablation test
If Vivado HLS (2019.1 tested) is installed on your machine, running the following script will report the HLS results for some benchmarks (around 2 hours on AMD Ryzen7 3800X for all 16 tests). "-n" determines the number of tests to be processed, the maximum supported value of which is 16. "-c" determines whether to run Vivado HLS C synthesis. "-r" determines whether to run report generation. The generated C++ source code will be written to $SCALEHLS_DIR/sample/cpp_src; the Vivado HLS project will be established in $SCALEHLS_DIR/sample/hls_proj; the generated report will be written to $SCALEHLS_DIR/sample/test_results.
```sh
$ cd $SCALEHLS_DIR/sample
$ source ./test_run.sh rerun
$ ./ablation_test_run.sh -n 16 -c true -r true
```
## References

View File

@ -66,10 +66,10 @@ def PartialAffineLoopTile : Pass<"partial-affine-loop-tile", "ModuleOp"> {
];
}
def RemoveVarLoopBound : Pass<"remove-val-loop-bound", "ModuleOp"> {
def RemoveVarLoopBound : Pass<"remove-var-loop-bound", "ModuleOp"> {
let summary = "Try to remove variable loop bounds";
let description = [{
This remove-val-loop-bound pass will try to remove the variable loop bounds.
This remove-var-loop-bound pass will try to remove the variable loop bounds.
Specifically, this is only possible when the variable loop bound is an
affine expression of induction variables of other loops with constant lower
or upper bound.

View File

@ -27,11 +27,11 @@ void InsertPipelinePragma::runOnOperation() {
for (auto func : module.getOps<FuncOp>()) {
for (auto forOp : func.getOps<mlir::AffineForOp>()) {
SmallVector<mlir::AffineForOp, 4> nestedLoops;
getPerfectlyNestedLoops(nestedLoops, forOp);
forOp.walk([&](mlir::AffineForOp loop) { nestedLoops.push_back(loop); });
auto targetLoop = nestedLoops.front();
auto targetLoop = nestedLoops.back();
if (nestedLoops.size() > insertLevel)
targetLoop = *std::prev(nestedLoops.end(), insertLevel);
targetLoop = *std::next(nestedLoops.begin(), insertLevel);
targetLoop.setAttr("pipeline", builder.getBoolAttr(true));
}

115
samples/ablation_test_run.sh Executable file
View File

@ -0,0 +1,115 @@
#!/bin/bash
# Script options.
while getopts 'n:c:r:' opt
do
case $opt in
n) ablation_number=$OPTARG ;;
c) rerun_csynth=$OPTARG ;;
r) rerun_report=$OPTARG ;;
esac
done
# Create directories.
if [ ! -d "cpp_src" ]
then
mkdir cpp_src
fi
if [ ! -d "hls_proj" ]
then
mkdir hls_proj
fi
if [ ! -d "test_results" ]
then
mkdir test_results
fi
# Candidate passes.
hta=-hlskernel-to-affine
pft=-affine-loop-perfection
rvb=-remove-var-loop-bound
can=-canonicalize
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"
u1=-affine-loop-unroll="unroll-full unroll-num-reps=1"
u2=-affine-loop-unroll="unroll-full unroll-num-reps=2"
u3=-affine-loop-unroll="unroll-full unroll-num-reps=3"
t1s2=-partial-affine-loop-tile="tile-level=1 tile-size=2"
t1s4=-partial-affine-loop-tile="tile-level=1 tile-size=4"
t2s2=-partial-affine-loop-tile="tile-level=2 tile-size=2"
t2s4=-partial-affine-loop-tile="tile-level=2 tile-size=4"
t3s2=-partial-affine-loop-tile="tile-level=3 tile-size=2"
t3s4=-partial-affine-loop-tile="tile-level=3 tile-size=4"
emit=-emit-hlscpp
# Ablation test.
n=0
while [ $n -lt $ablation_number ]
do
# Generate HLS C++ files.
for file in ../test/Conversion/HLSKernelToAffine/*
do
output="cpp_src/${file##*Affine/}.cpp"
case $n in
0) scalehls-opt $hta $can $file | scalehls-translate $emit -o $output ;;
# Apply pipeline.
1) scalehls-opt $hta "$p0" $can $file | scalehls-translate $emit -o $output ;;
2) scalehls-opt $hta "$p1" $can $file | scalehls-translate $emit -o $output ;;
3) scalehls-opt $hta "$p2" $can $file | scalehls-translate $emit -o $output ;;
4) scalehls-opt $hta "$p3" $can $file | scalehls-translate $emit -o $output ;;
# Apply loop perfection + pipeline.
5) scalehls-opt $hta $pft "$p0" $can $file | scalehls-translate $emit -o $output ;;
6) scalehls-opt $hta $pft "$p1" $can $file | scalehls-translate $emit -o $output ;;
7) scalehls-opt $hta $pft "$p2" $can $file | scalehls-translate $emit -o $output ;;
8) scalehls-opt $hta $pft "$p3" $can $file | scalehls-translate $emit -o $output ;;
# Apply loop perfection + remove variable bound + pipeline.
9) scalehls-opt $hta $pft $rvb "$p0" $can $file | scalehls-translate $emit -o $output ;;
10) scalehls-opt $hta $pft $rvb "$p1" $can $file | scalehls-translate $emit -o $output ;;
11) scalehls-opt $hta $pft $rvb "$p2" $can $file | scalehls-translate $emit -o $output ;;
12) scalehls-opt $hta $pft $rvb "$p3" $can $file | scalehls-translate $emit -o $output ;;
# Apply loop perfection + remove variable bound + loop tiling + pipeline.
13) scalehls-opt $hta $pft $rvb "$t1s4" "$p1" "$u1" $can $file | scalehls-translate $emit -o $output ;;
14) scalehls-opt $hta $pft $rvb "$t2s4" "$p2" "$u2" $can $file | scalehls-translate $emit -o $output ;;
15) scalehls-opt $hta $pft $rvb "$t3s4" "$p3" "$u3" $can $file | scalehls-translate $emit -o $output ;;
esac
done
if [ $rerun_csynth == "true" ]
then
# Run HLS synthesis.
cd hls_proj
vivado_hls ../hls_script.tcl
cd ..
fi
if [ $rerun_report == "true" ]
then
# Generate latency report.
echo -e "benchmark\tdsp\tlut\tcycles" > test_results/test_result$n.log
# echo "----------------------------------------" >> test_results/test_result$n.log
for file in cpp_src/*
do
name=${file##*cpp_src/}
name=${name%.mlir*}
cycles=$(awk '/<\/*Worst-caseLatency>/{gsub(/<\/*Worst-caseLatency>/,"");print $0}' hls_proj/$name/$name/syn/report/csynth.xml)
dsp=$(awk '/<\/*DSP48E>/{gsub(/<\/*DSP48E>/,"");print $0;exit;}' hls_proj/$name/$name/syn/report/csynth.xml)
lut=$(awk '/<\/*LUT>/{gsub(/<\/*LUT>/,"");print $0;exit;}' hls_proj/$name/$name/syn/report/csynth.xml)
echo -e "$name\t$dsp\t$lut\t$cycles" >> test_results/test_result$n.log
done
fi
let n++
done

View File

@ -1,37 +0,0 @@
#!/bin/bash
# Generate HLS C++ files.
if [ ! -d "cpp_src" ]
then
mkdir cpp_src
fi
for file in ../test/Conversion/HLSKernelToAffine/*
do
scalehls-opt -hlskernel-to-affine -affine-loop-perfection $file | scalehls-translate -emit-hlscpp -o "cpp_src/${file##*Affine/}.cpp"
done
if [ $1 == "rerun" ]
then
# Run HLS synthesis.
if [ ! -d "hls_proj" ]
then
mkdir hls_proj
fi
cd hls_proj
vivado_hls ../hls_script.tcl
cd ..
fi
# Generate latency report.
echo -e "testcase\tlatency" > test_result.log
echo "--------------------------------" >> test_result.log
for file in cpp_src/*
do
name=${file##*cpp_src/}
name=${name%.mlir*}
latency=$(cat hls_proj/$name/$name/syn/report/csynth.xml | grep Worst-caseLatency)
latency=${latency##<Worst-caseLatency>}
latency=${latency%</Worst-caseLatency>}
echo -e $name"\t"$latency >> test_result.log
done

View File

@ -1,4 +1,4 @@
// RUN: scalehls-opt -remove-val-loop-bound %s | FileCheck %s
// RUN: scalehls-opt -remove-var-loop-bound %s | FileCheck %s
// CHECK-LABEL: func @test_for
func @test_for() {