[EmitHLSCpp] fix an error of EmitSelectOp; update from val{n} to v{n}

This commit is contained in:
Hanchen Ye 2021-04-06 18:25:45 -05:00
parent d14f8718d0
commit a5cd433029
10 changed files with 115 additions and 101 deletions

View File

@ -17,6 +17,41 @@
using namespace mlir;
using namespace scalehls;
//===----------------------------------------------------------------------===//
// Utils
//===----------------------------------------------------------------------===//
static SmallString<16> getTypeName(Value val) {
// Handle memref, tensor, and vector types.
auto valType = val.getType();
if (auto arrayType = val.getType().dyn_cast<ShapedType>())
valType = arrayType.getElementType();
// Handle float types.
if (valType.isa<Float32Type>())
return SmallString<16>("float");
else if (valType.isa<Float64Type>())
return SmallString<16>("double");
// Handle integer types.
else if (valType.isa<IndexType>())
return SmallString<16>("int");
else if (auto intType = valType.dyn_cast<IntegerType>()) {
if (intType.getWidth() == 1)
return SmallString<16>("bool");
else {
std::string name = "ap_";
if (intType.getSignedness() == IntegerType::SignednessSemantics::Unsigned)
name += "u";
name += "int<" + std::to_string(intType.getWidth()) + ">";
return SmallString<16>(name);
}
} else
val.getDefiningOp()->emitError("has unsupported type.");
return SmallString<16>();
}
//===----------------------------------------------------------------------===//
// Some Base Classes
//===----------------------------------------------------------------------===//
@ -94,7 +129,7 @@ SmallString<8> ScaleHLSEmitterBase::addName(Value val, bool isPtr) {
if (isPtr)
valName += "*";
valName += StringRef("val" + std::to_string(state.nameTable.size()));
valName += StringRef("v" + std::to_string(state.nameTable.size()));
state.nameTable[val] = valName;
return valName;
@ -116,6 +151,7 @@ SmallString<8> ScaleHLSEmitterBase::getName(Value val) {
if (auto defOp = val.getDefiningOp()) {
if (auto constOp = dyn_cast<ConstantOp>(defOp)) {
auto constAttr = constOp.getValue();
if (auto floatAttr = constAttr.dyn_cast<FloatAttr>()) {
auto value = floatAttr.getValueAsDouble();
if (std::isfinite(value))
@ -1097,8 +1133,10 @@ void ModuleEmitter::emitSelect(SelectOp op) {
os << " = ";
emitValue(op.getCondition(), conditionRank);
os << " ? ";
os << "(" << getTypeName(op.getTrueValue()) << ")";
emitValue(op.getTrueValue(), rank);
os << " : ";
os << "(" << getTypeName(op.getFalseValue()) << ")";
emitValue(op.getFalseValue(), rank);
os << ";";
emitInfoAndNewLine(op);
@ -1222,40 +1260,16 @@ void ModuleEmitter::emitValue(Value val, unsigned rank, bool isPtr) {
if (isDeclared(val)) {
os << getName(val);
for (unsigned i = 0; i < rank; ++i)
os << "[idx" << i << "]";
os << "[iv" << i << "]";
return;
}
// Handle memref, tensor, and vector types.
auto valType = val.getType();
if (auto arrayType = val.getType().dyn_cast<ShapedType>())
valType = arrayType.getElementType();
// Handle float types.
if (valType.isa<Float32Type>())
os << "float ";
else if (valType.isa<Float64Type>())
os << "double ";
// Handle integer types.
else if (valType.isa<IndexType>())
os << "int ";
else if (auto intType = valType.dyn_cast<IntegerType>()) {
if (intType.getWidth() == 1)
os << "bool ";
else {
os << "ap_";
if (intType.getSignedness() == IntegerType::SignednessSemantics::Unsigned)
os << "u";
os << "int<" << intType.getWidth() << "> ";
}
} else
emitError(val.getDefiningOp(), "has unsupported type.");
os << getTypeName(val) << " ";
// Add the new value to nameTable and emit its name.
os << addName(val, isPtr);
for (unsigned i = 0; i < rank; ++i)
os << "[idx" << i << "]";
os << "[iv" << i << "]";
}
void ModuleEmitter::emitArrayDecl(Value array) {
@ -1290,9 +1304,9 @@ unsigned ModuleEmitter::emitNestedLoopHead(Value val) {
unsigned dimIdx = 0;
for (auto &shape : type.getShape()) {
indent();
os << "for (int idx" << dimIdx << " = 0; ";
os << "idx" << dimIdx << " < " << shape << "; ";
os << "++idx" << dimIdx++ << ") {\n";
os << "for (int iv" << dimIdx << " = 0; ";
os << "iv" << dimIdx << " < " << shape << "; ";
os << "++iv" << dimIdx++ << ") {\n";
addIndent();
}

View File

@ -50,7 +50,7 @@ graph_O5=-legalize-dataflow="min-gran=4 insert-copy=true"
graph_O6=-legalize-dataflow="min-gran=3 insert-copy=true"
# Split and canonicalize function, convert to HLSCpp, and loop perfection.
split="-split-function -convert-linalg-to-affine-loops -canonicalize"
split="-split-function -convert-linalg-to-affine-loops -quantize-dnn-model -canonicalize"
hlscpp=-legalize-to-hlscpp="top-func=main_graph"
perfect="-affine-loop-perfection"

View File

@ -5,14 +5,14 @@
func @test_affine_if(%arg0: index, %arg1: memref<16xindex>) -> index {
%c11 = constant 11 : index
// CHECK: int val3;
// CHECK: int val4[16];
// CHECK: if ((val0 + 11) >= 0 && (val0 * 11) == 0) {
// CHECK: int v3;
// CHECK: int v4[16];
// CHECK: if ((v0 + 11) >= 0 && (v0 * 11) == 0) {
%0:2 = affine.if #set0 (%arg0)[%c11] -> (index, memref<16xindex>) {
// CHECK: val3 = val0;
// CHECK: for (int idx0 = 0; idx0 < 16; ++idx0) {
// CHECK: val4[idx0] = val1[idx0];
// CHECK: v3 = v0;
// CHECK: for (int iv0 = 0; iv0 < 16; ++iv0) {
// CHECK: v4[iv0] = v1[iv0];
// CHECK: }
affine.yield %arg0, %arg1 : index, memref<16xindex>

View File

@ -6,22 +6,22 @@
func @test_affine_for(%arg0: memref<16xindex>, %arg1: index) {
%c11 = constant 11 : index
// CHECK: for (int val2 = 0; val2 < min(val1, (val1 + 11)); val2 += 2) {
// CHECK: for (int v2 = 0; v2 < min(v1, (v1 + 11)); v2 += 2) {
affine.for %i = 0 to min #two (%arg1)[%c11] step 2 {
// CHECK: for (int val3 = max(max((val1 - 11), val1), (val1 + 11)); val3 < 16; val3 += 1) {
// CHECK: for (int v3 = max(max((v1 - 11), v1), (v1 + 11)); v3 < 16; v3 += 1) {
affine.for %j = max #three (%arg1)[%c11] to 16 {
// CHECK: for (int val4 = 0; val4 < 16; val4 += 2) {
// CHECK: for (int v4 = 0; v4 < 16; v4 += 2) {
affine.for %k = 0 to 16 step 2 {
// CHECK: int val5 = val0[val2];
// CHECK: int v5 = v0[v2];
%0 = memref.load %arg0[%i] : memref<16xindex>
// CHECK: int val6 = val5 + val3;
// CHECK: int v6 = v5 + v3;
%1 = addi %0, %j : index
// CHECK: val0[val4] = val6;
// CHECK: v0[v4] = v6;
memref.store %1, %arg0[%k] : memref<16xindex>
// CHECK: }
@ -35,28 +35,28 @@ func @test_affine_for(%arg0: memref<16xindex>, %arg1: index) {
func @test_affine_parallel(%arg0: memref<16xindex>) {
// CHECK: int val8;
// CHECK: int val9;
// CHECK: for (int val10 = 0; val10 < 2; val10 += 1) {
// CHECK: for (int val11 = 0; val11 < 4; val11 += 2) {
// CHECK: for (int val12 = 0; val12 < 8; val12 += 3) {
// CHECK: int v8;
// CHECK: int v9;
// CHECK: for (int v10 = 0; v10 < 2; v10 += 1) {
// CHECK: for (int v11 = 0; v11 < 4; v11 += 2) {
// CHECK: for (int v12 = 0; v12 < 8; v12 += 3) {
%0:2 = affine.parallel (%x, %y, %z) = (0, 0, 0) to (2, 4, 8) step (1, 2, 3) reduce ("maxs", "addi") -> (index, index){
// CHECK: int val13 = val7[val10];
// CHECK: int v13 = v7[v10];
%1 = memref.load %arg0[%x] : memref<16xindex>
// CHECK: int val14 = val13 + val11;
// CHECK: int v14 = v13 + v11;
%2 = addi %1, %y : index
// CHECK: int val15 = val14 - val12;
// CHECK: int v15 = v14 - v12;
%3 = subi %2, %z : index
// CHECK: if (val10 == 0 && val11 == 0 && val12 == 0) {
// CHECK: val8 = val14;
// CHECK: val9 = val15;
// CHECK: if (v10 == 0 && v11 == 0 && v12 == 0) {
// CHECK: v8 = v14;
// CHECK: v9 = v15;
// CHECK: } else {
// CHECK: val8 = max(val8, val14);
// CHECK: val9 += val15;
// CHECK: v8 = max(v8, v14);
// CHECK: v9 += v15;
// CHECK: }
affine.yield %2, %3 : index, index

View File

@ -2,9 +2,9 @@
func @callee(%arg0: index, %arg1: memref<16xindex>) -> (index, index, memref<16xindex>, memref<16xindex>) attributes {top_function = false} {
// CHECK-NOT: #pragma HLS interface s_axilite port=return bundle=ctrl
// CHECK-NOT: #pragma HLS interface s_axilite port=val0 bundle=ctrl
// CHECK-NOT: #pragma HLS interface s_axilite port=val2 bundle=ctrl
// CHECK-NOT: #pragma HLS interface s_axilite port=val3 bundle=ctrl
// CHECK-NOT: #pragma HLS interface s_axilite port=v0 bundle=ctrl
// CHECK-NOT: #pragma HLS interface s_axilite port=v2 bundle=ctrl
// CHECK-NOT: #pragma HLS interface s_axilite port=v3 bundle=ctrl
%0 = affine.load %arg1[%arg0] : memref<16xindex>
%1 = affine.load %arg1[%arg0 + 1] : memref<16xindex>
@ -15,12 +15,12 @@ func @callee(%arg0: index, %arg1: memref<16xindex>) -> (index, index, memref<16x
func @test_call(%arg0: index, %arg1: memref<16xindex>) -> (index, memref<16xindex>) attributes {top_function = true} {
// CHECK: #pragma HLS interface s_axilite port=return bundle=ctrl
// CHECK: #pragma HLS interface s_axilite port=val6 bundle=ctrl
// CHECK: #pragma HLS interface s_axilite port=val8 bundle=ctrl
// CHECK: #pragma HLS interface s_axilite port=v6 bundle=ctrl
// CHECK: #pragma HLS interface s_axilite port=v8 bundle=ctrl
// CHECK: int val10;
// CHECK: int val11[16];
// CHECK: callee(val6, val7, &*val8, &val10, val9, val11);
// CHECK: int v10;
// CHECK: int v11[16];
// CHECK: callee(v6, v7, &*v8, &v10, v9, v11);
%0:4 = call @callee(%arg0, %arg1) : (index, memref<16xindex>) -> (index, index, memref<16xindex>, memref<16xindex>)
return %0#0, %0#2 : index, memref<16xindex>
}

View File

@ -24,13 +24,13 @@ func @test_constant(%arg0: i32) -> (i32, tensor<2x2xi32>, vector<2xi32>, i32) {
%c11 = constant 11 : i32
%6 = addi %c11, %arg0 : i32
// CHECK: for (int idx0 = 0; idx0 < 2; ++idx0) {
// CHECK: for (int idx1 = 0; idx1 < 2; ++idx1) {
// CHECK: [[ARG_2:.*]][idx0][idx1] = [[VAL_0:.*]][idx0][idx1];
// CHECK: for (int iv0 = 0; iv0 < 2; ++iv0) {
// CHECK: for (int iv1 = 0; iv1 < 2; ++iv1) {
// CHECK: [[ARG_2:.*]][iv0][iv1] = [[VAL_0:.*]][iv0][iv1];
// CHECK: }
// CHECK: }
// CHECK: for (int idx0 = 0; idx0 < 2; ++idx0) {
// CHECK: [[ARG_3:.*]][idx0] = [[VAL_3:.*]][idx0];
// CHECK: for (int iv0 = 0; iv0 < 2; ++iv0) {
// CHECK: [[ARG_3:.*]][iv0] = [[VAL_3:.*]][iv0];
// CHECK: }
// CHECK: *[[ARG_4:.*]] = 11;
return %6, %0, %3, %c11 : i32, tensor<2x2xi32>, vector<2xi32>, i32

View File

@ -4,18 +4,18 @@ func @test_scf_if(%arg0: index, %arg1: memref<16xindex>) {
%c11 = constant 11 : index
%c0 = constant 0 : index
// CHECK: int val2 = val0 + 11;
// CHECK: bool val3 = val2 > 0;
// CHECK: int val4;
// CHECK: int val5[16];
// CHECK: if (val3) {
// CHECK: int v2 = v0 + 11;
// CHECK: bool v3 = v2 > 0;
// CHECK: int v4;
// CHECK: int v5[16];
// CHECK: if (v3) {
%add = std.addi %arg0, %c11 : index
%condition = std.cmpi "sgt", %add, %c0 : index
%0:2 = scf.if %condition -> (index, memref<16xindex>) {
// CHECK: val4 = val0;
// CHECK: for (int idx0 = 0; idx0 < 16; ++idx0) {
// CHECK: val5[idx0] = val1[idx0];
// CHECK: v4 = v0;
// CHECK: for (int iv0 = 0; iv0 < 16; ++iv0) {
// CHECK: v5[iv0] = v1[iv0];
// CHECK: }
scf.yield %arg0, %arg1 : index, memref<16xindex>

View File

@ -7,27 +7,27 @@ func @test_scf_for(%arg0: memref<16xindex>, %arg1: index) {
%c2 = constant 2 : index
%c16 = constant 16 : index
// CHECK: int val2 = val1 + 11;
// CHECK: int val3 = val1 - 11;
// CHECK: int v2 = v1 + 11;
// CHECK: int v3 = v1 - 11;
%ub = std.addi %arg1, %c11 : index
%lb = std.subi %arg1, %c11 : index
// CHECK: for (int val4 = 0; val4 < val2; val4 += 2) {
// CHECK: for (int v4 = 0; v4 < v2; v4 += 2) {
scf.for %i = %c0 to %ub step %c2 {
// CHECK: for (int val5 = val3; val5 < 16; val5 += 1) {
// CHECK: for (int v5 = v3; v5 < 16; v5 += 1) {
scf.for %j = %lb to %c16 step %c1 {
// CHECK: for (int val6 = 0; val6 < 16; val6 += 2) {
// CHECK: for (int v6 = 0; v6 < 16; v6 += 2) {
scf.for %k = %c0 to %c16 step %c2 {
// CHECK: int val7 = val0[val4];
// CHECK: int v7 = v0[v4];
%0 = memref.load %arg0[%i] : memref<16xindex>
// CHECK: int val8 = val7 + val5;
// CHECK: int v8 = v7 + v5;
%1 = addi %0, %j : index
// CHECK: val0[val6] = val8;
// CHECK: v0[v6] = v8;
memref.store %1, %arg0[%k] : memref<16xindex>
// CHECK: }

View File

@ -53,9 +53,9 @@ func @test_signature(
%4 = rank %arg8 : tensor<16x8xf32>
// CHECK: *[[VAL_13:.*]] = [[VAL_0:.*]];
// CHECK: for (int idx0 = 0; idx0 < 16; ++idx0) {
// CHECK: for (int idx1 = 0; idx1 < 8; ++idx1) {
// CHECK: [[VAL_20:.*]][idx0][idx1] = [[VAL_7:.*]][idx0][idx1];
// CHECK: for (int iv0 = 0; iv0 < 16; ++iv0) {
// CHECK: for (int iv1 = 0; iv1 < 8; ++iv1) {
// CHECK: [[VAL_20:.*]][iv0][iv1] = [[VAL_7:.*]][iv0][iv1];
// CHECK: }
// CHECK: }
return

View File

@ -3,21 +3,21 @@
func @test_tensor_expr(%arg0: tensor<16x8xi1>, %arg1: i1, %arg2: tensor<16x8xf32>, %arg3: tensor<16x8xf32>) -> tensor<16x8xf32> {
// CHECK: float [[VAL_0:.*]][16][8];
// CHECK: for (int idx0 = 0; idx0 < 16; ++idx0) {
// CHECK: for (int idx1 = 0; idx1 < 8; ++idx1) {
// CHECK: [[VAL_0:.*]][idx0][idx1] = [[ARG_0:.*]][idx0][idx1] ? [[ARG_2:.*]][idx0][idx1] : [[ARG_3:.*]][idx0][idx1];
// CHECK: for (int iv0 = 0; iv0 < 16; ++iv0) {
// CHECK: for (int iv1 = 0; iv1 < 8; ++iv1) {
// CHECK: [[VAL_0:.*]][iv0][iv1] = [[ARG_0:.*]][iv0][iv1] ? [[ARG_2:.*]][iv0][iv1] : [[ARG_3:.*]][iv0][iv1];
// CHECK: }
// CHECK: }
%0 = select %arg0, %arg2, %arg3 : tensor<16x8xi1>, tensor<16x8xf32>
// CHECK: [[VAL_1:.*]][idx0][idx1] = [[ARG_1:.*]] ? [[ARG_2:.*]][idx0][idx1] : [[ARG_3:.*]][idx0][idx1];
// CHECK: [[VAL_1:.*]][iv0][iv1] = [[ARG_1:.*]] ? [[ARG_2:.*]][iv0][iv1] : [[ARG_3:.*]][iv0][iv1];
%1 = select %arg1, %arg2, %arg3 : i1, tensor<16x8xf32>
// CHECK: [[VAL_2:.*]][idx0][idx1] = [[ARG_2:.*]][idx0][idx1] + [[VAL_1:.*]][idx0][idx1];
// CHECK: [[VAL_2:.*]][iv0][iv1] = [[ARG_2:.*]][iv0][iv1] + [[VAL_1:.*]][iv0][iv1];
%2 = addf %arg2, %1 : tensor<16x8xf32>
// CHECK-NOT: float [[VAL_3:.*]][16][8];
// CHECK: [[VAL_3:.*]][idx0][idx1] = abs([[VAL_2:.*]][idx0][idx1]);
// CHECK: [[VAL_3:.*]][iv0][iv1] = abs([[VAL_2:.*]][iv0][iv1]);
%3 = absf %2 : tensor<16x8xf32>
return %3 : tensor<16x8xf32>
}
@ -25,16 +25,16 @@ func @test_tensor_expr(%arg0: tensor<16x8xi1>, %arg1: i1, %arg2: tensor<16x8xf32
func @test_tensor_load_store(%arg0: memref<16x8xi32>) {
// CHECK: ap_int<32> [[VAL_0:.*]][16][8];
// CHECK: for (int idx0 = 0; idx0 < 16; ++idx0) {
// CHECK: for (int idx1 = 0; idx1 < 8; ++idx1) {
// CHECK: [[VAL_0:.*]][idx0][idx1] = [[ARG_0:.*]][idx0][idx1];
// CHECK: for (int iv0 = 0; iv0 < 16; ++iv0) {
// CHECK: for (int iv1 = 0; iv1 < 8; ++iv1) {
// CHECK: [[VAL_0:.*]][iv0][iv1] = [[ARG_0:.*]][iv0][iv1];
// CHECK: }
// CHECK: }
%0 = memref.tensor_load %arg0 : memref<16x8xi32>
// CHECK: for (int idx0 = 0; idx0 < 16; ++idx0) {
// CHECK: for (int idx1 = 0; idx1 < 8; ++idx1) {
// CHECK: [[ARG_0:.*]][idx0][idx1] = [[VAL_0:.*]][idx0][idx1];
// CHECK: for (int iv0 = 0; iv0 < 16; ++iv0) {
// CHECK: for (int iv1 = 0; iv1 < 8; ++iv1) {
// CHECK: [[ARG_0:.*]][iv0][iv1] = [[VAL_0:.*]][iv0][iv1];
// CHECK: }
// CHECK: }
memref.tensor_store %0, %arg0 : memref<16x8xi32>