[LegalizeDataflow] impl of this pass, currently only support HLSKernel CNNOps

This commit is contained in:
Hanchen Ye 2020-12-13 11:51:10 -06:00
parent 4e163d6edc
commit 7cfd343dd4
1 changed files with 60 additions and 1 deletions

View File

@ -16,7 +16,66 @@ struct LegalizeDataflow : public LegalizeDataflowBase<LegalizeDataflow> {
};
} // namespace
void LegalizeDataflow::runOnOperation() { return; }
void LegalizeDataflow::runOnOperation() {
auto module = getOperation();
auto builder = OpBuilder(module);
for (auto func : module.getOps<FuncOp>()) {
// TODO: support non-HLSKernel operations, such as loops.
// TODO: support non-CNNOps.
for (auto kernelOp :
func.front().getOps<hlskernel::HLSKernelOpInterface>()) {
auto op = kernelOp.getOperation();
// Walk through all operands to establish an ASAP dataflow schedule.
int64_t dataflowLevel = 0;
for (auto operand : op->getOperands()) {
if (operand.getKind() == Value::Kind::BlockArgument)
continue;
else {
auto predOp = operand.getDefiningOp();
if (auto attr = predOp->getAttrOfType<IntegerAttr>("dataflow_level"))
dataflowLevel = max(dataflowLevel, attr.getInt());
else
op->emitError("has unexpected dominator");
}
}
// Set an attribute for indicating the scheduled dataflow level.
op->setAttr("dataflow_level", builder.getIntegerAttr(builder.getI64Type(),
dataflowLevel + 1));
}
// Eliminate bypass paths between non-successive dataflow levels. Dummy
// nodes will be inserted into the bypass paths.
for (auto kernelOp :
func.front().getOps<hlskernel::HLSKernelOpInterface>()) {
auto op = kernelOp.getOperation();
auto dataflowLevel =
op->getAttrOfType<IntegerAttr>("dataflow_level").getInt();
auto result = op->getResult(0);
for (auto &use : result.getUses()) {
if (auto attr =
use.getOwner()->getAttrOfType<IntegerAttr>("dataflow_level")) {
if (attr.getInt() != dataflowLevel + 1) {
// Insert a dummy CopyOp if required.
builder.setInsertionPointAfter(op);
auto copyOp = builder.create<hlskernel::CopyOp>(
op->getLoc(), result.getType(), result);
copyOp.setAttr("dataflow_level",
builder.getIntegerAttr(builder.getI64Type(),
dataflowLevel + 1));
// Replace the operand with the result of CopyOp.
use.getOwner()->setOperand(use.getOperandNumber(),
copyOp.getResult(0));
}
}
}
}
}
}
std::unique_ptr<mlir::Pass> scalehls::createLegalizeDataflowPass() {
return std::make_unique<LegalizeDataflow>();