From a31192405d57936a2012371c7fd9f6707575fb02 Mon Sep 17 00:00:00 2001 From: Hanchen Ye Date: Sun, 13 Sep 2020 01:02:15 -0500 Subject: [PATCH] [HLSCppDialect] add pipeline & unroll & array_partition pragma operation --- include/Dialect/HLSCpp/Ops.h | 2 + include/Dialect/HLSCpp/Ops.td | 146 ++++++++++++++++++++++----- test/Dialect/HLSCpp/test_pragma.mlir | 6 ++ test/lit.cfg.py | 1 + 4 files changed, 129 insertions(+), 26 deletions(-) create mode 100644 test/Dialect/HLSCpp/test_pragma.mlir diff --git a/include/Dialect/HLSCpp/Ops.h b/include/Dialect/HLSCpp/Ops.h index c604837..e0a5df7 100644 --- a/include/Dialect/HLSCpp/Ops.h +++ b/include/Dialect/HLSCpp/Ops.h @@ -5,7 +5,9 @@ #ifndef SCALEHLS_DIALECT_HLSCPP_OPS_H #define SCALEHLS_DIALECT_HLSCPP_OPS_H +#include "mlir/IR/Builders.h" #include "mlir/IR/Dialect.h" +#include "mlir/IR/StandardTypes.h" #include "mlir/Interfaces/SideEffectInterfaces.h" namespace mlir { diff --git a/include/Dialect/HLSCpp/Ops.td b/include/Dialect/HLSCpp/Ops.td index 7b11e8c..2fcf5f5 100644 --- a/include/Dialect/HLSCpp/Ops.td +++ b/include/Dialect/HLSCpp/Ops.td @@ -8,45 +8,139 @@ include "Interfaces.td" include "mlir/Interfaces/SideEffectInterfaces.td" -def HLSCppApplyPragmasOp : HLSCppOp<"apply_pragmas", - [NoSideEffect, PragmaOpInterface]> { - let summary = "apply_pragmas operation"; +def ApplyPragmasOp : HLSCppOp<"apply_pragmas", [ + PragmaOpInterface, + SingleBlockImplicitTerminator<"EndOp"> +]> { + let summary = "hlscpp.apply_pragmas operation"; 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. - - This operations takes nothing and returns nothing. + 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 extraClassDeclaration = [{ + OpBuilder getBodyBuilder() { + assert(!pragmaRegion().empty() && "Unexpected empty pragma region."); + Block &body = pragmaRegion().front(); + return OpBuilder(&body, std::prev(body.end())); + } + }]; } - - -def HLSCppFooOp : HLSCppOp<"foo", [NoSideEffect, SameOperandsAndResultType]> { - let summary = "Illustrates how to define an operation."; +def PragmaPipelineOp : HLSCppOp<"pragma_pipeline", [ + PragmaOpInterface, + HasParent<"ApplyPragmasOp"> +]> { + let summary = "hlscpp.pragma_pipeline operation"; let description = [{ - The `hlscpp.foo` operation illustrates how to define a new operation in a - dialect. - - 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 - ``` + This hlscpp.pragma_pipeline operation represent the "#pragma HLS PIPELINE" + directive in HLS C++. }]; - let arguments = (ins I32:$input); - let results = (outs I32:$res); + let arguments = (ins + Confined : $II, + BoolAttr : $enable_flush, + BoolAttr : $rewind, + BoolAttr : $off + ); - let assemblyFormat = [{ - $input attr-dict `:` type($input) + let extraClassDeclaration = [{ + unsigned getII() { + return getAttrOfType("II").getUInt(); + } + + bool isEnableFlush() { + return getAttrOfType("enable_flush").getValue(); + } + + bool isRewind() { + return getAttrOfType("rewind").getValue(); + } + + bool isOff() { + return getAttrOfType("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 : $factor, + BoolAttr : $region, + BoolAttr : $skip_exit_check + ); + + let extraClassDeclaration = [{ + unsigned getFactor() { + return getAttrOfType("factor").getUInt(); + } + + bool isRegion() { + return getAttrOfType("region").getValue(); + } + + bool isSkipExitCheck() { + return getAttrOfType("skip_exit_check").getValue(); + } + }]; +} + +def LegalPartitionType : AttrConstraint().getValue() == \"cyclic\"">, + CPred<"$_self.cast().getValue() == \"block\"">, + CPred<"$_self.cast().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 : $variable, + Confined : $type, + Confined : $factor, + Confined : $dim + ); + + let extraClassDeclaration = [{ + StringRef getPartitionType() { + return getAttrOfType("type").getValue(); + } + + unsigned getFactor() { + return getAttrOfType("factor").getUInt(); + } + + unsigned getDim() { + return getAttrOfType("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. }]; } diff --git a/test/Dialect/HLSCpp/test_pragma.mlir b/test/Dialect/HLSCpp/test_pragma.mlir new file mode 100644 index 0000000..8fa5819 --- /dev/null +++ b/test/Dialect/HLSCpp/test_pragma.mlir @@ -0,0 +1,6 @@ +// RUN: scalehls-opt %s | FileCheck %s + +// CHECK-LABEL: func @test_pragma() +func @test_pragma() { + +} \ No newline at end of file diff --git a/test/lit.cfg.py b/test/lit.cfg.py index a8c3931..c6c2166 100644 --- a/test/lit.cfg.py +++ b/test/lit.cfg.py @@ -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] tools = [ + 'scalehls-opt', 'scalehls-translate' ]