[ConvertToHLSCpp] support to recursively convert for loop body
This commit is contained in:
parent
f3c40918e3
commit
a2934a09a9
|
@ -19,13 +19,69 @@ public:
|
|||
};
|
||||
} // namespace
|
||||
|
||||
static void convertBlock(Block &block) {
|
||||
for (auto &op : block) {
|
||||
if (isa<ArrayOp>(op))
|
||||
continue;
|
||||
auto b = OpBuilder(&op);
|
||||
|
||||
// ArrayOp will be inserted after each ShapedType value from declaration
|
||||
// or function signature.
|
||||
for (auto operand : op.getOperands()) {
|
||||
if (auto arrayType = operand.getType().dyn_cast<ShapedType>()) {
|
||||
bool insertArrayOp = false;
|
||||
if (operand.getKind() == Value::Kind::BlockArgument)
|
||||
insertArrayOp = true;
|
||||
else if (!isa<ArrayOp>(operand.getDefiningOp())) {
|
||||
insertArrayOp = true;
|
||||
if (!arrayType.hasStaticShape())
|
||||
operand.getDefiningOp()->emitError(
|
||||
"is unranked or has dynamic shape which is illegal.");
|
||||
}
|
||||
|
||||
if (insertArrayOp) {
|
||||
// Insert array operation and set attributes.
|
||||
b.setInsertionPointAfterValue(operand);
|
||||
auto arrayOp =
|
||||
b.create<ArrayOp>(op.getLoc(), operand.getType(), operand);
|
||||
operand.replaceAllUsesExcept(arrayOp.getResult(),
|
||||
SmallPtrSet<Operation *, 1>{arrayOp});
|
||||
|
||||
// Set array pragma attributes, default array instance is ram_1p
|
||||
// bram. Other attributes are not set here since they requires more
|
||||
// analysis to be determined.
|
||||
arrayOp.setAttr("interface", b.getBoolAttr(false));
|
||||
arrayOp.setAttr("storage_type", b.getStringAttr("ram_1p"));
|
||||
arrayOp.setAttr("storage_impl", b.getStringAttr("bram"));
|
||||
arrayOp.setAttr("partition", b.getBoolAttr(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto forOp = dyn_cast<AffineForOp>(op)) {
|
||||
if (forOp.getLoopBody().getBlocks().size() != 1)
|
||||
forOp.emitError("has zero or more than one basic blocks");
|
||||
|
||||
// Set loop pragma attributes.
|
||||
forOp.setAttr("pipeline", b.getBoolAttr(false));
|
||||
forOp.setAttr("pipeline_II", b.getUI32IntegerAttr(1));
|
||||
forOp.setAttr("unroll_factor", b.getUI32IntegerAttr(1));
|
||||
|
||||
convertBlock(forOp.getLoopBody().front());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertToHLSCppPass::runOnOperation() {
|
||||
for (auto func : getOperation().getOps<FuncOp>()) {
|
||||
if (func.getBlocks().size() != 1)
|
||||
func.emitError("has zero or more than one basic blocks");
|
||||
|
||||
auto b = OpBuilder(func);
|
||||
|
||||
if (func.getBlocks().size() != 1)
|
||||
func.emitError("has zero or more than one basic blocks.");
|
||||
|
||||
// Set function pragma attributes.
|
||||
func.setAttr("dataflow", b.getBoolAttr(false));
|
||||
|
||||
// Insert AssignOp.
|
||||
if (auto returnOp = dyn_cast<ReturnOp>(func.front().getTerminator())) {
|
||||
b.setInsertionPoint(returnOp);
|
||||
|
@ -45,51 +101,8 @@ void ConvertToHLSCppPass::runOnOperation() {
|
|||
} else
|
||||
func.emitError("doesn't have a return as terminator.");
|
||||
|
||||
// Set function pragma attributes.
|
||||
func.setAttr("dataflow", b.getBoolAttr(false));
|
||||
|
||||
for (auto &op : func.front()) {
|
||||
if (auto forOp = dyn_cast<AffineForOp>(op)) {
|
||||
if (forOp.getLoopBody().getBlocks().size() != 1)
|
||||
forOp.emitError("has zero or more than one basic blocks");
|
||||
|
||||
// Set loop pragma attributes.
|
||||
forOp.setAttr("pipeline", b.getBoolAttr(false));
|
||||
forOp.setAttr("pipeline_II", b.getUI32IntegerAttr(1));
|
||||
forOp.setAttr("unroll_factor", b.getUI32IntegerAttr(1));
|
||||
}
|
||||
|
||||
for (auto operand : op.getOperands()) {
|
||||
if (auto arrayType = operand.getType().dyn_cast<ShapedType>()) {
|
||||
bool insertArrayOp = false;
|
||||
if (operand.getKind() == Value::Kind::BlockArgument)
|
||||
insertArrayOp = true;
|
||||
else if (!isa<ArrayOp>(operand.getDefiningOp())) {
|
||||
insertArrayOp = true;
|
||||
if (!arrayType.hasStaticShape())
|
||||
operand.getDefiningOp()->emitError(
|
||||
"is unranked or has dynamic shape which is illegal.");
|
||||
}
|
||||
|
||||
if (insertArrayOp) {
|
||||
// Insert array operation and set attributes.
|
||||
b.setInsertionPointAfterValue(operand);
|
||||
auto arrayOp =
|
||||
b.create<ArrayOp>(op.getLoc(), operand.getType(), operand);
|
||||
operand.replaceAllUsesExcept(arrayOp.getResult(),
|
||||
SmallPtrSet<Operation *, 1>{arrayOp});
|
||||
|
||||
// Set array pragma attributes, default array instance is ram_1p
|
||||
// bram. Other attributes are not set here since they requires more
|
||||
// analysis to be determined.
|
||||
arrayOp.setAttr("interface", b.getBoolAttr(false));
|
||||
arrayOp.setAttr("storage_type", b.getStringAttr("ram_1p"));
|
||||
arrayOp.setAttr("storage_impl", b.getStringAttr("bram"));
|
||||
arrayOp.setAttr("partition", b.getBoolAttr(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Recursively convert every for loop body blocks.
|
||||
convertBlock(func.front());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
// RUN: scalehls-opt -qor-estimation %s | FileCheck %s
|
||||
|
||||
// CHECK-LABEL: func @test_for
|
||||
func @test_for(%arg0: memref<16x4x4xindex>, %arg1: memref<16x4x4xindex>) {
|
||||
"hlscpp.array_pragma" (%arg0) {partition=true, partition_type=["cyclic", "cyclic", "cyclic"], partition_factor=[4 : ui32, 2 : ui32, 4 : ui32], storage_type="ram_2p", interface=true, interface_mode="bram"} : (memref<16x4x4xindex>) -> ()
|
||||
"hlscpp.array_pragma" (%arg1) {partition=true, partition_type=["cyclic", "cyclic", "cyclic"], partition_factor=[4 : ui32, 2 : ui32, 4 : ui32], storage_type="ram_2p", interface=true, interface_mode="bram"} : (memref<16x4x4xindex>) -> ()
|
||||
func @test_for(%arg0: memref<16x4x4xindex>, %arg1: memref<16x4x4xindex>) attributes {dataflow = false} {
|
||||
%array0 = "hlscpp.array"(%arg0) {interface = false, partition = false, storage_impl = "bram", storage_type = "ram_1p"} : (memref<16x4x4xindex>) -> memref<16x4x4xindex>
|
||||
%array1 = "hlscpp.array"(%arg1) {interface = false, partition = false, storage_impl = "bram", storage_type = "ram_1p"} : (memref<16x4x4xindex>) -> memref<16x4x4xindex>
|
||||
//"hlscpp.array_pragma" (%arg0) {partition=true, partition_type=["cyclic", "cyclic", "cyclic"], partition_factor=[4 : ui32, 2 : ui32, 4 : ui32], storage_type="ram_2p", interface=true, interface_mode="bram"} : (memref<16x4x4xindex>) -> ()
|
||||
//"hlscpp.array_pragma" (%arg1) {partition=true, partition_type=["cyclic", "cyclic", "cyclic"], partition_factor=[4 : ui32, 2 : ui32, 4 : ui32], storage_type="ram_2p", interface=true, interface_mode="bram"} : (memref<16x4x4xindex>) -> ()
|
||||
affine.for %i = 0 to 16 {
|
||||
affine.for %j = 0 to 4 {
|
||||
affine.for %k = 0 to 4 {
|
||||
%0 = affine.load %arg0[%i, %j, %k] : memref<16x4x4xindex>
|
||||
%1 = affine.load %arg1[%i, %j, %k] : memref<16x4x4xindex>
|
||||
%0 = affine.load %array0[%i, %j, %k] : memref<16x4x4xindex>
|
||||
%1 = affine.load %array1[%i, %j, %k] : memref<16x4x4xindex>
|
||||
%2 = muli %0, %1 : index
|
||||
affine.store %2, %arg0[%i, %j, %k] : memref<16x4x4xindex>
|
||||
}
|
||||
}
|
||||
}
|
||||
affine.store %2, %array1[%i, %j, %k] : memref<16x4x4xindex>
|
||||
} {pipeline = false, pipeline_II = 1 : ui32, unroll_factor = 1 : ui32}
|
||||
} {pipeline = false, pipeline_II = 1 : ui32, unroll_factor = 1 : ui32}
|
||||
} {pipeline = false, pipeline_II = 1 : ui32, unroll_factor = 1 : ui32}
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue