[HLSCppDialect] update pragma operations definition, update corresponding emitters
This commit is contained in:
parent
4470f6c232
commit
77eaacd030
|
@ -5,115 +5,107 @@
|
|||
#ifndef SCALEHLS_DIALECT_HLSCPP_PRAGMAOPS_TD
|
||||
#define SCALEHLS_DIALECT_HLSCPP_PRAGMAOPS_TD
|
||||
|
||||
def ApplyPragmasOp : HLSCppOp<"apply_pragmas", [
|
||||
def LoopPragmaOp : HLSCppOp<"loop_pragma", [
|
||||
PragmaOpInterface,
|
||||
SingleBlockImplicitTerminator<"EndOp">
|
||||
HasParent<"AffineForOp">
|
||||
]> {
|
||||
let summary = "Apply pragmas to the parent operation";
|
||||
let summary = "Apply loop pragmas";
|
||||
let description = [{
|
||||
This hlscpp.apply_pragmas operation owns one region containing one or more
|
||||
concrete pragmas, and applies all of them to its parent operation (e.g.,
|
||||
functions, loops, or other regions). This operation should always be
|
||||
inserted to the front of its parent operation. For detailed description of
|
||||
each concrete pragma, please refer to:
|
||||
https://www.xilinx.com/html_docs/xilinx2020_1/vitis_doc/hlspragmas.html
|
||||
}];
|
||||
|
||||
let regions = (region SizedRegion<1> : $pragmaRegion);
|
||||
|
||||
let skipDefaultBuilders = 1;
|
||||
let builders = [OpBuilder<"OpBuilder &builder, OperationState &state", [{
|
||||
auto &pragmaRegion = *state.addRegion();
|
||||
ApplyPragmasOp::ensureTerminator(pragmaRegion, builder, state.location);
|
||||
}]>];
|
||||
|
||||
// TODO: verifier for this op:
|
||||
// (1) is in the front of its parent operation.
|
||||
// (2) only contains hlscpp pragma operation.
|
||||
|
||||
let extraClassDeclaration = [{
|
||||
OpBuilder getBodyBuilder() {
|
||||
assert(!pragmaRegion().empty() && "Unexpected empty pragma region.");
|
||||
Block &body = pragmaRegion().front();
|
||||
return OpBuilder(&body, std::prev(body.end()));
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def PragmaPipelineOp : HLSCppOp<"pragma_pipeline", [
|
||||
PragmaOpInterface,
|
||||
HasParent<"ApplyPragmasOp">
|
||||
]> {
|
||||
let summary = "Apply PIPELINE HLS pragma";
|
||||
let description = [{
|
||||
This hlscpp.pragma_pipeline operation represent the "#pragma HLS PIPELINE"
|
||||
directive in HLS C++.
|
||||
This hlscpp.loop_pragma operation represent pragmas for loops, such as
|
||||
pipeline, and unroll pragma.
|
||||
}];
|
||||
|
||||
let arguments = (ins
|
||||
// Pipeline pragma-related attributes.
|
||||
Confined<UI32Attr, [IntPositive]> : $II,
|
||||
BoolAttr : $enable_flush,
|
||||
BoolAttr : $rewind,
|
||||
BoolAttr : $off
|
||||
);
|
||||
BoolAttr : $off,
|
||||
|
||||
let extraClassDeclaration = [{
|
||||
unsigned getII() {
|
||||
return getAttrOfType<IntegerAttr>("II").getUInt();
|
||||
}
|
||||
|
||||
bool isEnableFlush() {
|
||||
return getAttrOfType<BoolAttr>("enable_flush").getValue();
|
||||
}
|
||||
|
||||
bool isRewind() {
|
||||
return getAttrOfType<BoolAttr>("rewind").getValue();
|
||||
}
|
||||
|
||||
bool isOff() {
|
||||
return getAttrOfType<BoolAttr>("off").getValue();
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def PragmaUnrollOp : HLSCppOp<"pragma_unroll", [
|
||||
PragmaOpInterface,
|
||||
HasParent<"ApplyPragmasOp">
|
||||
]> {
|
||||
let summary = "Apply UNROLL HLS pragma";
|
||||
let description = [{
|
||||
This hlscpp.pragma_unroll operation represent the "#pragma HLS UNROLL"
|
||||
directive in HLS C++.
|
||||
}];
|
||||
|
||||
let arguments = (ins
|
||||
// Unroll pragma-related attributes.
|
||||
Confined<UI32Attr, [IntPositive]> : $factor,
|
||||
BoolAttr : $region,
|
||||
BoolAttr : $skip_exit_check
|
||||
);
|
||||
|
||||
let extraClassDeclaration = [{
|
||||
// Pipeline pragma-related methods.
|
||||
unsigned getII() {
|
||||
return getAttrOfType<IntegerAttr>("II").getUInt();
|
||||
}
|
||||
bool isEnableFlush() {
|
||||
return getAttrOfType<BoolAttr>("enable_flush").getValue();
|
||||
}
|
||||
bool isRewind() {
|
||||
return getAttrOfType<BoolAttr>("rewind").getValue();
|
||||
}
|
||||
bool isOff() {
|
||||
return getAttrOfType<BoolAttr>("off").getValue();
|
||||
}
|
||||
|
||||
// Unroll pragma-related methods.
|
||||
unsigned getFactor() {
|
||||
return getAttrOfType<IntegerAttr>("factor").getUInt();
|
||||
}
|
||||
|
||||
bool isRegion() {
|
||||
return getAttrOfType<BoolAttr>("region").getValue();
|
||||
}
|
||||
|
||||
bool isSkipExitCheck() {
|
||||
return getAttrOfType<BoolAttr>("skip_exit_check").getValue();
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def PragmaArrayPartitionOp : HLSCppOp<"pragma_array_partition", [
|
||||
def FuncPragmaOp : HLSCppOp<"func_pragma", [
|
||||
PragmaOpInterface,
|
||||
HasParent<"FuncOp">
|
||||
]> {
|
||||
let summary = "Apply function pragmas";
|
||||
let description = [{
|
||||
This hlscpp.func_pragma operation represent pragmas for functions, such as
|
||||
pipeline, and dataflow pragma.
|
||||
}];
|
||||
|
||||
let arguments = (ins
|
||||
// Pipeline pragma-related attributes.
|
||||
Confined<UI32Attr, [IntPositive]> : $II,
|
||||
BoolAttr : $enable_flush,
|
||||
BoolAttr : $rewind,
|
||||
BoolAttr : $off,
|
||||
|
||||
// Dataflow pragma-related attributes.
|
||||
BoolAttr : $dataflow
|
||||
);
|
||||
|
||||
let extraClassDeclaration = [{
|
||||
// Pipeline pragma-related methods.
|
||||
unsigned getII() {
|
||||
return getAttrOfType<IntegerAttr>("II").getUInt();
|
||||
}
|
||||
bool isEnableFlush() {
|
||||
return getAttrOfType<BoolAttr>("enable_flush").getValue();
|
||||
}
|
||||
bool isRewind() {
|
||||
return getAttrOfType<BoolAttr>("rewind").getValue();
|
||||
}
|
||||
bool isOff() {
|
||||
return getAttrOfType<BoolAttr>("off").getValue();
|
||||
}
|
||||
|
||||
// Dataflow pragma-related methods.
|
||||
bool isDataflow() {
|
||||
return getAttrOfType<BoolAttr>("dataflow").getValue();
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def ArrayPragmaOp : HLSCppOp<"array_pragma", [
|
||||
PragmaOpInterface
|
||||
]> {
|
||||
let summary = "Apply ARRAY_PARTITION HLS pragma to the input value";
|
||||
let summary = "Apply array pragmas";
|
||||
let description = [{
|
||||
This hlscpp.pragma_array_partition operation represent the "#pragma HLS
|
||||
ARRAY_PARTITION" directive in HLS C++.
|
||||
This hlscpp.func_pragma operation represent pragmas for arrays, such as
|
||||
array partition, interface, and bind storage pragma.
|
||||
}];
|
||||
|
||||
let arguments = (ins
|
||||
|
@ -131,11 +123,9 @@ def PragmaArrayPartitionOp : HLSCppOp<"pragma_array_partition", [
|
|||
StringRef getPartitionType() {
|
||||
return getAttrOfType<StringAttr>("type").getValue();
|
||||
}
|
||||
|
||||
unsigned getFactor() {
|
||||
return getAttrOfType<IntegerAttr>("factor").getUInt();
|
||||
}
|
||||
|
||||
unsigned getDim() {
|
||||
return getAttrOfType<IntegerAttr>("dim").getUInt();
|
||||
}
|
||||
|
|
|
@ -49,10 +49,10 @@ public:
|
|||
SelectOp, ConstantOp, CopySignOp, TruncateIOp, ZeroExtendIOp,
|
||||
SignExtendIOp, IndexCastOp, CallOp, ReturnOp, AssignOp, EndOp,
|
||||
// Pragma operations.
|
||||
ApplyPragmasOp, PragmaPipelineOp, PragmaUnrollOp,
|
||||
PragmaArrayPartitionOp>([&](auto opNode) -> ResultType {
|
||||
return thisCast->visitOp(opNode, args...);
|
||||
})
|
||||
LoopPragmaOp, FuncPragmaOp, ArrayPragmaOp>(
|
||||
[&](auto opNode) -> ResultType {
|
||||
return thisCast->visitOp(opNode, args...);
|
||||
})
|
||||
.Default([&](auto opNode) -> ResultType {
|
||||
return thisCast->visitInvalidOp(op, args...);
|
||||
});
|
||||
|
@ -175,10 +175,9 @@ public:
|
|||
HANDLE(EndOp);
|
||||
|
||||
// Pragma operations.
|
||||
HANDLE(ApplyPragmasOp);
|
||||
HANDLE(PragmaPipelineOp);
|
||||
HANDLE(PragmaUnrollOp);
|
||||
HANDLE(PragmaArrayPartitionOp);
|
||||
HANDLE(LoopPragmaOp);
|
||||
HANDLE(FuncPragmaOp);
|
||||
HANDLE(ArrayPragmaOp);
|
||||
#undef HANDLE
|
||||
};
|
||||
} // namespace scalehls
|
||||
|
|
|
@ -86,9 +86,7 @@ bool QoREstimator::visitOp(AffineForOp op) {
|
|||
// Recursively estimate latency of sub-elements, including functions and
|
||||
// loops. These sub-elements will be considered as a normal node in the CDFG
|
||||
// for function latency estimzation.
|
||||
for (auto &op : body.front()) {
|
||||
estimateOperation(&op);
|
||||
}
|
||||
estimateBlock(body.front());
|
||||
|
||||
// Estimate iteration latency.
|
||||
unsigned iterLatency = searchLongestPath(body.front());
|
||||
|
|
|
@ -178,10 +178,9 @@ public:
|
|||
void emitAssign(AssignOp *op);
|
||||
|
||||
/// Pragma operation emitters.
|
||||
void emitApplyPragmas(ApplyPragmasOp *op);
|
||||
void emitPragmaPipeline(PragmaPipelineOp *op);
|
||||
void emitPragmaUnroll(PragmaUnrollOp *op);
|
||||
void emitPragmaArrayPartition(PragmaArrayPartitionOp *op);
|
||||
void emitLoopPragma(LoopPragmaOp *op);
|
||||
void emitFuncPragma(FuncPragmaOp *op);
|
||||
void emitArrayPragma(ArrayPragmaOp *op);
|
||||
|
||||
/// Top-level MLIR module emitter.
|
||||
void emitModule(ModuleOp module);
|
||||
|
@ -464,18 +463,9 @@ public:
|
|||
using HLSCppVisitorBase::visitOp;
|
||||
|
||||
/// Pragma operations.
|
||||
bool visitOp(ApplyPragmasOp op) {
|
||||
return emitter.emitApplyPragmas(&op), true;
|
||||
}
|
||||
bool visitOp(PragmaPipelineOp op) {
|
||||
return emitter.emitPragmaPipeline(&op), true;
|
||||
}
|
||||
bool visitOp(PragmaUnrollOp op) {
|
||||
return emitter.emitPragmaUnroll(&op), true;
|
||||
}
|
||||
bool visitOp(PragmaArrayPartitionOp op) {
|
||||
return emitter.emitPragmaArrayPartition(&op), true;
|
||||
}
|
||||
bool visitOp(LoopPragmaOp op) { return emitter.emitLoopPragma(&op), true; }
|
||||
bool visitOp(FuncPragmaOp op) { return emitter.emitFuncPragma(&op), true; }
|
||||
bool visitOp(ArrayPragmaOp op) { return emitter.emitArrayPragma(&op), true; }
|
||||
|
||||
private:
|
||||
ModuleEmitter &emitter;
|
||||
|
@ -1030,12 +1020,33 @@ void ModuleEmitter::emitAssign(AssignOp *op) {
|
|||
}
|
||||
|
||||
/// Pragma operation emitters.
|
||||
void ModuleEmitter::emitApplyPragmas(ApplyPragmasOp *op) {
|
||||
emitBlock(*op->getBody());
|
||||
|
||||
void ModuleEmitter::emitLoopPragma(LoopPragmaOp *op) {
|
||||
indent();
|
||||
os << "#pragma HLS pipeline";
|
||||
if (op->isOff())
|
||||
os << " off\n";
|
||||
else {
|
||||
os << " II=" << op->getII();
|
||||
if (op->isRewind())
|
||||
os << " rewind";
|
||||
if (op->isEnableFlush())
|
||||
os << " enable_flush";
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
indent();
|
||||
os << "#pragma HLS unroll";
|
||||
// TODO: default factor.
|
||||
os << " factor=" << op->getFactor();
|
||||
if (op->isRegion())
|
||||
os << " region";
|
||||
if (op->isSkipExitCheck())
|
||||
os << " skip_exit_check";
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void ModuleEmitter::emitPragmaPipeline(PragmaPipelineOp *op) {
|
||||
void ModuleEmitter::emitFuncPragma(FuncPragmaOp *op) {
|
||||
indent();
|
||||
os << "#pragma HLS pipeline";
|
||||
if (op->isOff())
|
||||
|
@ -1050,19 +1061,7 @@ void ModuleEmitter::emitPragmaPipeline(PragmaPipelineOp *op) {
|
|||
}
|
||||
}
|
||||
|
||||
void ModuleEmitter::emitPragmaUnroll(PragmaUnrollOp *op) {
|
||||
indent();
|
||||
os << "#pragma HLS unroll";
|
||||
// TODO: default factor.
|
||||
os << " factor=" << op->getFactor();
|
||||
if (op->isRegion())
|
||||
os << " region";
|
||||
if (op->isSkipExitCheck())
|
||||
os << " skip_exit_check";
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void ModuleEmitter::emitPragmaArrayPartition(PragmaArrayPartitionOp *op) {
|
||||
void ModuleEmitter::emitArrayPragma(ArrayPragmaOp *op) {
|
||||
indent();
|
||||
os << "#pragma HLS array_partition";
|
||||
os << " variable=";
|
||||
|
|
Loading…
Reference in New Issue