[HLSCppDialect] add pipeline & unroll & array_partition pragma operation

This commit is contained in:
Hanchen Ye 2020-09-13 01:02:15 -05:00
parent 1a6491b4fd
commit a31192405d
4 changed files with 129 additions and 26 deletions

View File

@ -5,7 +5,9 @@
#ifndef SCALEHLS_DIALECT_HLSCPP_OPS_H #ifndef SCALEHLS_DIALECT_HLSCPP_OPS_H
#define SCALEHLS_DIALECT_HLSCPP_OPS_H #define SCALEHLS_DIALECT_HLSCPP_OPS_H
#include "mlir/IR/Builders.h"
#include "mlir/IR/Dialect.h" #include "mlir/IR/Dialect.h"
#include "mlir/IR/StandardTypes.h"
#include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Interfaces/SideEffectInterfaces.h"
namespace mlir { namespace mlir {

View File

@ -8,45 +8,139 @@
include "Interfaces.td" include "Interfaces.td"
include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/Interfaces/SideEffectInterfaces.td"
def HLSCppApplyPragmasOp : HLSCppOp<"apply_pragmas", def ApplyPragmasOp : HLSCppOp<"apply_pragmas", [
[NoSideEffect, PragmaOpInterface]> { PragmaOpInterface,
let summary = "apply_pragmas operation"; SingleBlockImplicitTerminator<"EndOp">
]> {
let summary = "hlscpp.apply_pragmas operation";
let description = [{ let description = [{
This hlscpp.apply_pragmas operation owns one region containing one or more 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., concrete pragmas, and applies all of them to its parent operation (e.g.,
functions, loops, or other regions). This operation should always be functions, loops, or other regions). This operation should always be
inserted to the front of its parent operation. inserted to the front of its parent operation. For detailed description of
each concrete pragma, please refer to:
This operations takes nothing and returns nothing. https://www.xilinx.com/html_docs/xilinx2020_1/vitis_doc/hlspragmas.html
}]; }];
let regions = (region SizedRegion<1> : $pragmaRegion); let regions = (region SizedRegion<1> : $pragmaRegion);
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,
def HLSCppFooOp : HLSCppOp<"foo", [NoSideEffect, SameOperandsAndResultType]> { HasParent<"ApplyPragmasOp">
let summary = "Illustrates how to define an operation."; ]> {
let summary = "hlscpp.pragma_pipeline operation";
let description = [{ let description = [{
The `hlscpp.foo` operation illustrates how to define a new operation in a This hlscpp.pragma_pipeline operation represent the "#pragma HLS PIPELINE"
dialect. directive in HLS C++.
This operation takes an integer argument and returns an integer.
Example:
```mlir
%0 = constant 2 : i32
// Apply the foo operation to %0
%1 = hlscpp.foo %0 : i32
```
}]; }];
let arguments = (ins I32:$input); let arguments = (ins
let results = (outs I32:$res); Confined<UI32Attr, [IntPositive]> : $II,
BoolAttr : $enable_flush,
BoolAttr : $rewind,
BoolAttr : $off
);
let assemblyFormat = [{ let extraClassDeclaration = [{
$input attr-dict `:` type($input) 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 = "hlscpp.pragma_unroll operation";
let description = [{
This hlscpp.pragma_unroll operation represent the "#pragma HLS UNROLL"
directive in HLS C++.
}];
let arguments = (ins
Confined<UI32Attr, [IntPositive]> : $factor,
BoolAttr : $region,
BoolAttr : $skip_exit_check
);
let extraClassDeclaration = [{
unsigned getFactor() {
return getAttrOfType<IntegerAttr>("factor").getUInt();
}
bool isRegion() {
return getAttrOfType<BoolAttr>("region").getValue();
}
bool isSkipExitCheck() {
return getAttrOfType<BoolAttr>("skip_exit_check").getValue();
}
}];
}
def LegalPartitionType : AttrConstraint<Or<[
CPred<"$_self.cast<StringAttr>().getValue() == \"cyclic\"">,
CPred<"$_self.cast<StringAttr>().getValue() == \"block\"">,
CPred<"$_self.cast<StringAttr>().getValue() == \"complete\"">
]>>;
def PragmaArrayPartitionOp : HLSCppOp<"pragma_array_partition", [
PragmaOpInterface
]> {
let summary = "hlscpp.pragma_array_partition operation";
let description = [{
This hlscpp.pragma_array_partition operation represent the "#pragma HLS
ARRAY_PARTITION" directive in HLS C++.
}];
let arguments = (ins
Type<IsShapedTypePred> : $variable,
Confined<StrAttr, [LegalPartitionType]> : $type,
Confined<UI32Attr, [IntPositive]> : $factor,
Confined<UI32Attr, [IntNonNegative]> : $dim
);
let extraClassDeclaration = [{
StringRef getPartitionType() {
return getAttrOfType<StringAttr>("type").getValue();
}
unsigned getFactor() {
return getAttrOfType<IntegerAttr>("factor").getUInt();
}
unsigned getDim() {
return getAttrOfType<IntegerAttr>("dim").getUInt();
}
}];
}
def EndOp : HLSCppOp<"end", [Terminator]> {
let summary = "hlscpp.end operation";
let description = [{
This hlscpp.end operation marks the end of a region in the HLSCpp dialect.
}]; }];
} }

View File

@ -0,0 +1,6 @@
// RUN: scalehls-opt %s | FileCheck %s
// CHECK-LABEL: func @test_pragma()
func @test_pragma() {
}

View File

@ -53,6 +53,7 @@ llvm_config.with_environment('PATH', config.llvm_tools_dir, append_path=True)
tool_dirs = [config.scalehls_tools_dir, config.mlir_tools_dir, config.llvm_tools_dir] tool_dirs = [config.scalehls_tools_dir, config.mlir_tools_dir, config.llvm_tools_dir]
tools = [ tools = [
'scalehls-opt',
'scalehls-translate' 'scalehls-translate'
] ]