Implement the build and integeration outline of an spt-translate tool,

and stub out a .fir parser (which doesn't do anything yet) that is driven
from it.
This commit is contained in:
Chris Lattner 2020-03-16 15:14:56 -07:00
parent dfac4c84db
commit 2fe028d811
13 changed files with 230 additions and 10 deletions

View File

@ -35,9 +35,13 @@ reasonably fast and is good to provide a sanity check that things are working):
$ cd ~/Projects/llvm-project
$ mkdir build
$ cd build
$ cmake -G Ninja ../llvm -DLLVM_EXTERNAL_PROJECTS="spt" -DLLVM_EXTERNAL_SPT_SOURCE_DIR=/Users/chrisl/Projects/spt -DLLVM_ENABLE_PROJECTS="mlir;spt" -DLLVM_TARGETS_TO_BUILD="X86" -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON
$ cmake -G Ninja ../llvm -DLLVM_EXTERNAL_PROJECTS="spt" -DLLVM_EXTERNAL_SPT_SOURCE_DIR=/Users/chrisl/Projects/spt -DLLVM_ENABLE_PROJECTS="mlir;spt" -DLLVM_TARGETS_TO_BUILD="X86" -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON -DCMAKE_BUILD_TYPE=DEBUG
```
The "-DCMAKE_BUILD_TYPE=DEBUG" flag enables debug information, which makes the
whole tree compile slower, but allows you to step through code into the LLVM
and MLIR frameworks.
5) Build MLIR and run MLIR tests as a smoketest:
```

View File

@ -0,0 +1,18 @@
//===- FIRRTL/FIRToMLIR.h - .fir to FIRRTL dialect parser -------*- C++ -*-===//
//
// Defines the interface to the .fir file parser.
//
//===----------------------------------------------------------------------===//
#ifndef SPT_DIALECT_FIRRTL_FIRTOMLIR_H
#define SPT_DIALECT_FIRRTL_FIRTOMLIR_H
namespace spt {
namespace firrtl {
void registerFIRRTLToMLIRTranslation();
} // namespace firrtl
} // namespace spt
#endif // SPT_DIALECT_FIRRTL_FIRTOMLIR_H

View File

@ -147,14 +147,13 @@ def FIRRTLConnectOp : FIRRTLOp<"connect", []> {
let description = [{
Connect Operation:
```
firrt.connect %lhs, %rhs "name" : t1, t2
firrt.connect %lhs, %rhs : t1, t2
```
}];
let arguments = (ins AnyType:$lhs, AnyType:$rhs, OptionalAttr<StrAttr>:$name);
let results = (outs);
// TODO: Print '$name' more nicely. This breaks the asmparser tho.
let assemblyFormat = [{
$lhs `,` $rhs attr-dict `:` type($lhs) `,` type($rhs)
}];
@ -184,7 +183,6 @@ def FIRRTLAddOp : FIRRTLOp<"add", [Commutative, NoSideEffect]> {
let arguments = (ins AnyType:$lhs, AnyType:$rhs, OptionalAttr<StrAttr>:$name);
let results = (outs AnyType:$result);
// TODO: Print '$name' more nicely. This breaks the asmparser tho.
let assemblyFormat = [{
$lhs `,` $rhs attr-dict `:`
`(` type($lhs) `,` type($rhs) `)` `->` type($result)

View File

@ -1,11 +1,11 @@
//===- FIRRTL.h - FIRRTL dialect --------------------------------*- C++ -*-===//
//===- FIRRTL/IR/Ops.h - FIRRTL dialect -------------------------*- C++ -*-===//
//
// This file defines an MLIR dialect for the FIRRTL IR.
//
//===----------------------------------------------------------------------===//
#ifndef SPT_DIALECT_FIRRTL_FIRRTL_H
#define SPT_DIALECT_FIRRTL_FIRRTL_H
#ifndef SPT_DIALECT_FIRRTL_IR_OPS_H
#define SPT_DIALECT_FIRRTL_IR_OPS_H
#include "mlir/IR/Builders.h"
#include "mlir/IR/Dialect.h"
@ -55,4 +55,4 @@ public:
} // namespace firrtl
} // namespace spt
#endif // SPT_DIALECT_FIRRTL_FIRRTL_H
#endif // SPT_DIALECT_FIRRTL_IR_OPS_H

View File

@ -1,3 +1,5 @@
add_subdirectory(FIRToMLIR)
file(GLOB globbed *.c *.cpp)
add_mlir_dialect_library(MLIRFIRRTL
${globbed}

View File

@ -0,0 +1,10 @@
add_mlir_library(SPTFIRToMLIR
FIRToMLIR.cpp
ADDITIONAL_HEADER_DIRS
DEPENDS
intrinsics_gen
)
add_dependencies(SPTFIRToMLIR MLIRFIRRTL)
target_link_libraries(SPTFIRToMLIR MLIRFIRRTL)

View File

@ -0,0 +1,64 @@
//===- FIRToMLIR.cpp - .fir to FIRRTL dialect parser ----------------------===//
//
// This implements a .fir file parser.
//
//===----------------------------------------------------------------------===//
#include "spt/Dialect/FIRRTL/FIRToMLIR.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/Module.h"
#include "mlir/Translation.h"
#include "spt/Dialect/FIRRTL/IR/Ops.h"
#include "llvm/Support/SourceMgr.h"
using namespace spt;
using namespace firrtl;
using namespace mlir;
using llvm::SMLoc;
using llvm::SourceMgr;
namespace {
class Lexer {
public:
Lexer(const llvm::SourceMgr &sourceMgr, MLIRContext *context)
: sourceMgr(sourceMgr), context(context) {}
Location getEncodedSourceLocation(llvm::SMLoc loc);
private:
const llvm::SourceMgr &sourceMgr;
MLIRContext *context;
};
} // end anonymous namespace
/// Encode the specified source location information into a Location object
/// for attachment to the IR or error reporting.
Location Lexer::getEncodedSourceLocation(llvm::SMLoc loc) {
unsigned mainFileID = sourceMgr.getMainFileID();
auto lineAndColumn = sourceMgr.getLineAndColumn(loc, mainFileID);
auto *buffer = sourceMgr.getMemoryBuffer(mainFileID);
return FileLineColLoc::get(buffer->getBufferIdentifier(), lineAndColumn.first,
lineAndColumn.second, context);
}
// Parse the specified .fir file into the specified MLIR context.
OwningModuleRef parseFIRFile(SourceMgr &sourceMgr, MLIRContext *context) {
auto *dialect = context->getRegisteredDialect<FIRRTLDialect>();
assert(dialect && "Could not find FIRRTL dialect?");
(void)dialect;
auto *buf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
auto loc = SMLoc::getFromPointer(buf->getBufferStart());
Lexer l(sourceMgr, context);
mlir::emitError(l.getEncodedSourceLocation(loc),
"firrtl parsing not implemented");
return {};
}
void spt::firrtl::registerFIRRTLToMLIRTranslation() {
static TranslateToMLIRRegistration fromLLVM(
"import-firrtl", [](llvm::SourceMgr &sourceMgr, MLIRContext *context) {
return parseFIRFile(sourceMgr, context);
});
}

View File

@ -8,6 +8,7 @@ configure_lit_site_cfg(
set(SPT_TEST_DEPENDS
FileCheck count not
spt-opt
spt-translate
)
add_lit_testsuite(check-spt "Running the SPT regression tests"

8
test/fir/basic.fir Normal file
View File

@ -0,0 +1,8 @@
// expected-error {{firrtl parsing not implemented}}
// RUN: spt-translate -import-firrtl -verify-diagnostics %s
module MyModule :
input in: UInt<8>
output out: UInt<8>
out <= in

View File

@ -21,7 +21,7 @@ config.name = 'SPT'
config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)
# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.td', '.mlir', '.ll']
config.suffixes = ['.td', '.mlir', '.ll', '.fir']
# test_source_root: The root path where tests are located.
config.test_source_root = os.path.dirname(__file__)
@ -54,6 +54,7 @@ llvm_config.with_environment('PATH', config.llvm_tools_dir, append_path=True)
tool_dirs = [config.spt_tools_dir, config.mlir_tools_dir, config.llvm_tools_dir]
tools = [
'spt-opt',
'spt-translate',
]
llvm_config.add_tool_substitutions(tools, tool_dirs)

View File

@ -1,2 +1,3 @@
add_subdirectory(spt-opt)
add_subdirectory(spt-opt)
add_subdirectory(spt-translate)

View File

@ -0,0 +1,11 @@
set(LIBS
MLIRTranslation
MLIRSupport
SPTFIRToMLIR
)
add_llvm_tool(spt-translate
spt-translate.cpp
)
llvm_update_compile_flags(spt-translate)
target_link_libraries(spt-translate PRIVATE MLIRIR MLIRTranslateClParser ${LIBS} LLVMSupport)

View File

@ -0,0 +1,102 @@
//===- spt-translate.cpp - SPT Translate Driver ---------------------------===//
//
// This is a command line utility that translates a file from/to MLIR using one
// of the registered translations.
//
//===----------------------------------------------------------------------===//
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/Support/FileUtilities.h"
#include "mlir/Support/ToolUtilities.h"
#include "mlir/Support/TranslateClParser.h"
#include "spt/Dialect/FIRRTL/FIRToMLIR.h"
#include "spt/Dialect/FIRRTL/IR/Ops.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/ToolOutputFile.h"
using namespace mlir;
using namespace spt;
static llvm::cl::opt<std::string> inputFilename(llvm::cl::Positional,
llvm::cl::desc("<input file>"),
llvm::cl::init("-"));
static llvm::cl::opt<std::string>
outputFilename("o", llvm::cl::desc("Output filename"),
llvm::cl::value_desc("filename"), llvm::cl::init("-"));
static llvm::cl::opt<bool>
splitInputFile("split-input-file",
llvm::cl::desc("Split the input file into pieces and "
"process each chunk independently"),
llvm::cl::init(false));
static llvm::cl::opt<bool> verifyDiagnostics(
"verify-diagnostics",
llvm::cl::desc("Check that emitted diagnostics match "
"expected-* lines on the corresponding line"),
llvm::cl::init(false));
int main(int argc, char **argv) {
registerDialect<StandardOpsDialect>();
registerDialect<firrtl::FIRRTLDialect>();
firrtl::registerFIRRTLToMLIRTranslation();
llvm::InitLLVM y(argc, argv);
// Add flags for all the registered translations.
llvm::cl::opt<const TranslateFunction *, false, TranslationParser>
translationRequested("", llvm::cl::desc("Translation to perform"),
llvm::cl::Required);
llvm::cl::ParseCommandLineOptions(argc, argv, "SPT translation driver\n");
std::string errorMessage;
auto input = openInputFile(inputFilename, &errorMessage);
if (!input) {
llvm::errs() << errorMessage << "\n";
return 1;
}
auto output = openOutputFile(outputFilename, &errorMessage);
if (!output) {
llvm::errs() << errorMessage << "\n";
return 1;
}
// Processes the memory buffer with a new MLIRContext.
auto processBuffer = [&](std::unique_ptr<llvm::MemoryBuffer> ownedBuffer,
raw_ostream &os) {
MLIRContext context;
llvm::SourceMgr sourceMgr;
sourceMgr.AddNewSourceBuffer(std::move(ownedBuffer), llvm::SMLoc());
if (!verifyDiagnostics) {
SourceMgrDiagnosticHandler sourceMgrHandler(sourceMgr, &context);
return (*translationRequested)(sourceMgr, os, &context);
}
// In the diagnostic verification flow, we ignore whether the translation
// failed (in most cases, it is expected to fail). Instead, we check if the
// diagnostics were produced as expected.
SourceMgrDiagnosticVerifierHandler sourceMgrHandler(sourceMgr, &context);
(*translationRequested)(sourceMgr, os, &context);
return sourceMgrHandler.verify();
};
if (splitInputFile) {
if (failed(splitAndProcessBuffer(std::move(input), processBuffer,
output->os())))
return 1;
} else {
if (failed(processBuffer(std::move(input), output->os())))
return 1;
}
output->keep();
return 0;
}