From 01baa10c9767d1a4b8e92b1beff9393bfefbeec0 Mon Sep 17 00:00:00 2001 From: Hanchen Ye Date: Wed, 26 Aug 2020 23:23:22 -0500 Subject: [PATCH] [EmitHLSCpp] some basic classes; hlsld-translate entry; add testcase --- .clang-format | 2 + CMakeLists.txt | 1 - README.md | 7 +- include/EmitHLSCpp.h | 9 ++ lib/EmitHLSCpp/EmitHLSCpp.cpp | 119 ++++++++++++++++++++++ test/EmitHLSCpp/test_standard.mlir | 3 +- tools/hlsld-translate/hlsld-translate.cpp | 21 ++-- 7 files changed, 143 insertions(+), 19 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..392e201 --- /dev/null +++ b/.clang-format @@ -0,0 +1,2 @@ +BasedOnStyle: LLVM +AlwaysBreakTemplateDeclarations: Yes \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f5110f..3c73827 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,6 @@ set(HLSLD_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(HLSLD_BINARY_DIR ${CMAKE_BINARY_DIR}/bin) set(HLSLD_TOOLS_DIR ${CMAKE_BINARY_DIR}/bin) - list(APPEND CMAKE_MODULE_PATH "${MLIR_CMAKE_DIR}") list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") include(TableGen) diff --git a/README.md b/README.md index bebf5e0..1900a2d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # HLS Large Design Project (HLSLD) -## High Level Description of Project This project aims to create a framework that ultimately converts an algorithm written in a high level language into an efficient hardware implementation. Out of all of the existing deep learning compiler related projects, TVM and MLIR present existing tools that we can leverage in our proposed framework. With multiple levels of intermediate representations (IRs), MLIR appears to be the ideal tool for exploring ways to optimize the eventual design at various levels of abstraction (e.g. various levels of parallelism). Our framework will be based on MLIR, but it will incorporate a frontend for Sitao's powerful domain specific language (DSL) and a backend for high level synthesis (HLS) C/C++ code. However, the key contribution will be our parametrization and optimization of a tremendously large design space. So far, we are familiarizing ourselves with the existing MLIR flow using a toy example (simple neural network for MNIST digit classification) and figure out how to do this parametrization and optimization. ## Quick Start @@ -16,6 +15,6 @@ cmake --build . --target check-hlsld ## References 1. [MLIR Documents](https://mlir.llvm.org) -2. [github mlir-npcomp](https://github.com/llvm/mlir-npcomp) -3. [github circt](https://github.com/llvm/circt) -4. [github onnx-mlir](https://github.com/onnx/onnx-mlir) +2. [mlir-npcomp github](https://github.com/llvm/mlir-npcomp) +3. [circt github](https://github.com/llvm/circt) +4. [onnx-mlir github](https://github.com/onnx/onnx-mlir) diff --git a/include/EmitHLSCpp.h b/include/EmitHLSCpp.h index 767e2fc..4f18d0b 100644 --- a/include/EmitHLSCpp.h +++ b/include/EmitHLSCpp.h @@ -1,3 +1,12 @@ //===------------------------------------------------------------*- C++ -*-===// // //===----------------------------------------------------------------------===// + +#ifndef HLSLD_EMIT_HLSCPP_H +#define HLSLD_EMIT_HLSCPP_H + +namespace hlsld { +void registerHLSCppEmitterTranslation(); +} // namespace hlsld + +#endif // HLSLD_EMIT_HLSCPP_H diff --git a/lib/EmitHLSCpp/EmitHLSCpp.cpp b/lib/EmitHLSCpp/EmitHLSCpp.cpp index 767e2fc..c15385f 100644 --- a/lib/EmitHLSCpp/EmitHLSCpp.cpp +++ b/lib/EmitHLSCpp/EmitHLSCpp.cpp @@ -1,3 +1,122 @@ //===------------------------------------------------------------*- C++ -*-===// // //===----------------------------------------------------------------------===// + +#include "EmitHLSCpp.h" +#include "mlir/IR/Function.h" +#include "mlir/IR/Module.h" +#include "mlir/IR/StandardTypes.h" +#include "mlir/Translation.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/raw_ostream.h" + +using namespace mlir; + +//===----------------------------------------------------------------------===// +// Utilities +//===----------------------------------------------------------------------===// + +namespace { +/// This class maintains the mutable state that cross-cuts and is shared by the +/// various emitters. +class HLSCppEmitterState { +public: + explicit HLSCppEmitterState(raw_ostream &os) : os(os) {} + + /// The stream to emit to. + raw_ostream &os; + + bool encounteredError = false; + unsigned currentIndent = 0; + +private: + HLSCppEmitterState(const HLSCppEmitterState &) = delete; + void operator=(const HLSCppEmitterState &) = delete; +}; +} // namespace + +namespace { +/// This is the base class for all of the HLSCpp Emitter components. +class HLSCppEmitterBase { +public: + explicit HLSCppEmitterBase(HLSCppEmitterState &state) + : state(state), os(state.os) {} + + InFlightDiagnostic emitError(Operation *op, const Twine &message) { + state.encounteredError = true; + return op->emitError(message); + } + + InFlightDiagnostic emitOpError(Operation *op, const Twine &message) { + state.encounteredError = true; + return op->emitOpError(message); + } + + raw_ostream &indent() { return os.indent(state.currentIndent); } + + void addIndent() { state.currentIndent += 2; } + void reduceIndent() { state.currentIndent -= 2; } + + // All of the mutable state we are maintaining. + HLSCppEmitterState &state; + + /// The stream to emit to. + raw_ostream &os; + +private: + HLSCppEmitterBase(const HLSCppEmitterBase &) = delete; + void operator=(const HLSCppEmitterBase &) = delete; +}; +} // namespace + +//===----------------------------------------------------------------------===// +// FuncEmitter +//===----------------------------------------------------------------------===// + +namespace { +class FuncEmitter : public HLSCppEmitterBase { +public: + explicit FuncEmitter(HLSCppEmitterState &state) : HLSCppEmitterBase(state) {} + + void emitFunc(FuncOp func); +}; +} // namespace + +void FuncEmitter::emitFunc(FuncOp func) { os << "new function\n"; }; + +//===----------------------------------------------------------------------===// +// HLSCppEmitter +//===----------------------------------------------------------------------===// + +namespace { +class HLSCppEmitter : public HLSCppEmitterBase { +public: + explicit HLSCppEmitter(HLSCppEmitterState &state) + : HLSCppEmitterBase(state) {} + + void emitMLIRModule(ModuleOp module); +}; +} // namespace + +void HLSCppEmitter::emitMLIRModule(ModuleOp module) { + for (auto &op : *module.getBody()) { + if (auto func = dyn_cast(op)) + FuncEmitter(state).emitFunc(func); + else if (!isa(op)) + op.emitError("unknown operation"); + } +} + +//===----------------------------------------------------------------------===// +// hlsld-translate Entry +//===----------------------------------------------------------------------===// + +static LogicalResult emitHLSCpp(ModuleOp module, llvm::raw_ostream &os) { + HLSCppEmitterState state(os); + HLSCppEmitter(state).emitMLIRModule(module); + return failure(state.encounteredError); +} + +void hlsld::registerHLSCppEmitterTranslation() { + static TranslateFromMLIRRegistration toHLSCpp("emit-hlscpp", emitHLSCpp); +} diff --git a/test/EmitHLSCpp/test_standard.mlir b/test/EmitHLSCpp/test_standard.mlir index 3b1ac61..06dc9e1 100644 --- a/test/EmitHLSCpp/test_standard.mlir +++ b/test/EmitHLSCpp/test_standard.mlir @@ -1,5 +1,6 @@ -// RUN: hlsld-translate %s | FileCheck %s +// RUN: hlsld-translate -emit-hlscpp %s | FileCheck %s +// CHECK: new function func @test_standard() { } \ No newline at end of file diff --git a/tools/hlsld-translate/hlsld-translate.cpp b/tools/hlsld-translate/hlsld-translate.cpp index e6c3d76..1996067 100644 --- a/tools/hlsld-translate/hlsld-translate.cpp +++ b/tools/hlsld-translate/hlsld-translate.cpp @@ -38,11 +38,12 @@ static llvm::cl::opt verifyDiagnostics( "expected-* lines on the corresponding line"), llvm::cl::init(false)); -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { mlir::registerAllDialects(); mlir::registerAllTranslations(); + hlsld::registerHLSCppEmitterTranslation(); + llvm::InitLLVM y(argc, argv); // Add flags for all the registered translations. @@ -55,15 +56,13 @@ int main(int argc, char **argv) std::string errorMessage; auto input = mlir::openInputFile(inputFilename, &errorMessage); - if (!input) - { + if (!input) { llvm::errs() << errorMessage << "\n"; return 1; } auto output = mlir::openOutputFile(outputFilename, &errorMessage); - if (!output) - { + if (!output) { llvm::errs() << errorMessage << "\n"; return 1; } @@ -77,8 +76,7 @@ int main(int argc, char **argv) llvm::SourceMgr sourceMgr; sourceMgr.AddNewSourceBuffer(std::move(ownedBuffer), llvm::SMLoc()); - if (!verifyDiagnostics) - { + if (!verifyDiagnostics) { mlir::SourceMgrDiagnosticHandler sourceMgrHandler(sourceMgr, &context); return (*translationRequested)(sourceMgr, os, &context); } @@ -92,14 +90,11 @@ int main(int argc, char **argv) return sourceMgrHandler.verify(); }; - if (splitInputFile) - { + if (splitInputFile) { if (failed(mlir::splitAndProcessBuffer(std::move(input), processBuffer, output->os()))) return 1; - } - else - { + } else { if (failed(processBuffer(std::move(input), output->os()))) return 1; }