Create the sketch of a FIRRTL dialect, with a single type (firrtl.uint) and a

single registered operations (firrtl.add).  Add a testcase showing that these
are now being properly checked.
This commit is contained in:
Chris Lattner 2020-03-07 15:47:08 -08:00
parent 71b7e2cb93
commit 24c3b33447
16 changed files with 220 additions and 66 deletions

View File

@ -9,10 +9,12 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
## Should get this from MLIR build files somehow?
set(MLIR_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../llvm-project/mlir/include )
set(MLIR_TABLEGEN_EXE mlir-tblgen)
set(MLIR_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../llvm-project/mlir)
set(MLIR_MAIN_SRC_DIR ${MLIR_SOURCE_DIR})
set(MLIR_INCLUDE_DIR ${MLIR_SOURCE_DIR}/include )
set(MLIR_BINARY_INCLUDE_DIR ${LLVM_TOOLS_BINARY_DIR}/../tools/mlir/include )
include(AddSPT)
# Installing the headers and docs needs to depend on generating any public
# tablegen'd targets.
@ -23,9 +25,10 @@ add_custom_target(spt-doc)
include_directories( ${MLIR_INCLUDE_DIR})
include_directories( ${MLIR_BINARY_INCLUDE_DIR})
include_directories( ${SPT_INCLUDE_DIR})
include_directories( ${SPT_MAIN_SRC_DIR})
#add_subdirectory(include/spt)
#add_subdirectory(lib)
add_subdirectory(include/spt)
add_subdirectory(lib)
add_subdirectory(tools)
#add_subdirectory(unittests)
add_subdirectory(test)

View File

@ -1,62 +0,0 @@
#function(spt_tablegen ofn)
# tablegen(SPT ${ARGV} "-I${SPT_MAIN_SRC_DIR}" "-I${SPT_INCLUDE_DIR}")
# set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
# PARENT_SCOPE)
#endfunction()
# TODO: This is to handle the current static registration, but should be
# factored out a bit.
#function(whole_archive_link target)
# add_dependencies(${target} ${ARGN})
# if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
# set(link_flags "-L${CMAKE_BINARY_DIR}/lib ")
# FOREACH(LIB ${ARGN})
# string(CONCAT link_flags ${link_flags} "-Wl,-force_load ${CMAKE_BINARY_DIR}/lib/lib${LIB}.a ")
# ENDFOREACH(LIB)
# elseif(MSVC)
# FOREACH(LIB ${ARGN})
# string(CONCAT link_flags ${link_flags} "/WHOLEARCHIVE:${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib/${LIB}.lib ")
# ENDFOREACH(LIB)
# else()
# set(link_flags "-L${CMAKE_BINARY_DIR}/lib -Wl,--whole-archive,")
# FOREACH(LIB ${ARGN})
# string(CONCAT link_flags ${link_flags} "-l${LIB},")
# ENDFOREACH(LIB)
# string(CONCAT link_flags ${link_flags} "--no-whole-archive")
# endif()
# set_target_properties(${target} PROPERTIES LINK_FLAGS ${link_flags})
#endfunction(whole_archive_link)
# Declare a dialect in the include directory
#function(add_mlir_dialect dialect dialect_doc_filename)
# set(LLVM_TARGET_DEFINITIONS ${dialect}.td)
# mlir_tablegen(${dialect}.h.inc -gen-op-decls)
# mlir_tablegen(${dialect}.cpp.inc -gen-op-defs)
# add_public_tablegen_target(MLIR${dialect}IncGen)
# add_dependencies(mlir-headers MLIR${dialect}IncGen)
# # Generate Dialect Documentation
# set(LLVM_TARGET_DEFINITIONS ${dialect_doc_filename}.td)
# tablegen(MLIR ${dialect_doc_filename}.md -gen-op-doc "-I${MLIR_MAIN_SRC_DIR}" "-I${MLIR_INCLUDE_DIR}")
# set(GEN_DOC_FILE ${MLIR_BINARY_DIR}/docs/Dialects/${dialect_doc_filename}.md)
# add_custom_command(
# OUTPUT ${GEN_DOC_FILE}
# COMMAND ${CMAKE_COMMAND} -E copy
# ${CMAKE_CURRENT_BINARY_DIR}/${dialect_doc_filename}.md
# ${GEN_DOC_FILE}
# DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${dialect_doc_filename}.md)
# add_custom_target(${dialect_doc_filename}DocGen DEPENDS ${GEN_DOC_FILE})
# add_dependencies(mlir-doc ${dialect_doc_filename}DocGen)
#endfunction()
# Declare the library associated with a dialect.
#function(add_mlir_dialect_library name)
# set_property(GLOBAL APPEND PROPERTY MLIR_DIALECT_LIBS ${name})
# add_llvm_library(${ARGV})
#endfunction(add_mlir_dialect_library)
# Declare the library associated with a conversion.
#function(add_mlir_conversion_library name)
# set_property(GLOBAL APPEND PROPERTY MLIR_CONVERSION_LIBS ${name})
# add_llvm_library(${ARGV})
#endfunction(add_mlir_conversion_library)

View File

@ -0,0 +1,2 @@
add_subdirectory(Dialect)

View File

@ -0,0 +1,2 @@
add_subdirectory(FIRRTL)

View File

@ -0,0 +1 @@
add_subdirectory(IR)

View File

@ -0,0 +1,3 @@
add_mlir_dialect(FIRRTL FIRRTL)

View File

@ -0,0 +1,60 @@
//===- FIRRTL.td - FIRRTL dialect definition ---------------*- tablegen -*-===//
//
// This is the operation definition file for FIRRTL dialect operations.
//
//===----------------------------------------------------------------------===//
#ifndef FIRRTL_OPS
#define FIRRTL_OPS
include "mlir/IR/OpBase.td"
def FIRRTLDialect : Dialect {
let name = "firrtl";
let summary = "Types and operations for firrtl dialect";
let description = [{
This dialect defines the `firrtl` dialect, which is used to lower from
Chisel code to Verilog. For more information, see the
[FIRRTL GitHub page](https://github.com/freechipsproject/firrtl).
}];
let cppNamespace = "firrtl";
}
def FIRRTL_UIntType : DialectType<FIRRTLDialect,
CPred<"$_self.isa<UIntType>()">, "UInt type"> {
let typeDescription = [{
`firrtl.UInt` is an unsigned integer of unknown width.
}];
}
//===----------------------------------------------------------------------===//
// FIRRTL op definitions
//===----------------------------------------------------------------------===//
// Base class for the operation in this dialect
class FIRRTLOp<string mnemonic, list<OpTrait> traits = []> :
Op<FIRRTLDialect, mnemonic, traits>;
// TODO: Should this be split out to addu/adds?
def FIRRTLAddOp : FIRRTLOp<"add", [Commutative]> {
let summary = "Add operations";
let description = [{
Add Operation: x = add (y, z)
The two options are:
* add(UInt, UInt) -> UInt
* add(SInt, SInt) -> SInt
The result width is max(we1, we2)+1
The add operation result is the sum of e1 and e2 without loss of precision.
}];
let arguments = (ins AnyType:$lhs, AnyType:$rhs);
let results = (outs AnyType:$result);
}
#endif // FIRRTL_OPS

View File

@ -0,0 +1,56 @@
//===- FIRRTL.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
#include "mlir/IR/Dialect.h"
#include "mlir/IR/OpDefinition.h"
namespace spt {
namespace firrtl {
using namespace mlir;
class FIRRTLDialect : public Dialect {
public:
/// Create the dialect in the given `context`.
explicit FIRRTLDialect(MLIRContext *context);
~FIRRTLDialect();
Type parseType(DialectAsmParser &parser) const override;
void printType(Type, DialectAsmPrinter &) const override;
static StringRef getDialectNamespace() { return "firrtl"; }
};
namespace FIRRTLTypes {
enum Kind {
UInt = Type::FIRST_PRIVATE_EXPERIMENTAL_0_TYPE,
};
} // namespace FIRRTLTypes
// A unsigned integer type with unknown width.
class UIntType : public Type::TypeBase<UIntType, Type> {
public:
using Base::Base;
static UIntType get(MLIRContext *context) {
return Base::get(context, FIRRTLTypes::Kind::UInt);
}
/// Support method to enable LLVM-style type casting.
static bool kindof(unsigned kind) {
return kind == FIRRTLTypes::Kind::UInt;
}
};
#define GET_OP_CLASSES
#include "spt/Dialect/FIRRTL/IR/FIRRTL.h.inc"
} // namespace firrtl
} // namespace spt
#endif // SPT_DIALECT_FIRRTL_FIRRTL_H

1
lib/CMakeLists.txt Normal file
View File

@ -0,0 +1 @@
add_subdirectory(Dialect)

View File

@ -0,0 +1 @@
add_subdirectory(FIRRTL)

View File

@ -0,0 +1,9 @@
file(GLOB globbed *.c *.cpp)
add_mlir_dialect_library(MLIRFIRRTL
${globbed}
ADDITIONAL_HEADER_DIRS
${SPT_MAIN_INCLUDE_DIR}/spt/Dialect/FIRRTL
)
add_dependencies(MLIRFIRRTL MLIRFIRRTLIncGen LLVMSupport)
target_link_libraries(MLIRFIRRTL LLVMSupport)

View File

@ -0,0 +1,47 @@
//===- Dialect.cpp - Implement the FIRRTL dialect -------------------------===//
//
//===----------------------------------------------------------------------===//
#include "spt/Dialect/FIRRTL/IR/Ops.h"
#include "mlir/IR/StandardTypes.h"
#include "mlir/IR/DialectImplementation.h"
using namespace spt;
using namespace firrtl;
FIRRTLDialect::FIRRTLDialect(MLIRContext *context)
: Dialect(getDialectNamespace(), context) {
addTypes<UIntType>();
addOperations<
#define GET_OP_LIST
#include "spt/Dialect/FIRRTL/IR/FIRRTL.cpp.inc"
>();
// Support unknown operations because not all LLVM operations are registered.
// FIXME(clattner): remove this.
allowUnknownOperations();
}
FIRRTLDialect::~FIRRTLDialect() {
}
/// Parse a type registered to this dialect.
Type FIRRTLDialect::parseType(DialectAsmParser &parser) const {
StringRef tyData = parser.getFullSymbolSpec();
if (tyData == "uint")
return UIntType::get(getContext());
parser.emitError(parser.getNameLoc(), "unknown firrtl type");
return Type();
}
void FIRRTLDialect::printType(Type type, DialectAsmPrinter &os) const {
auto uintType = type.dyn_cast<UIntType>();
assert(uintType && "printing wrong type");
os.getStream() << "uint";
}
#define GET_OP_CLASSES
#include "spt/Dialect/FIRRTL/IR/FIRRTL.cpp.inc"

View File

@ -0,0 +1,10 @@
//===- DialectRegistration.cpp - Register FIRRTL dialect ------------------===//
//
//===----------------------------------------------------------------------===//
#include "spt/Dialect/FIRRTL/IR/Ops.h"
using namespace spt;
using namespace firrtl;
// Static initialization for FIRRTL dialect registration.
static mlir::DialectRegistration<FIRRTLDialect> FIRRTLOps;

16
test/firrtl/errors.mlir Normal file
View File

@ -0,0 +1,16 @@
// RUN: spt-opt %s -split-input-file -verify-diagnostics
"firrtl.module"() ( {
// expected-error @+1 {{unknown firrtl type}}
%0 = "firrtl.input"() {name = "in"} : () -> !firrtl.unknowntype
}) {name = "MyModule"} : () -> ()
// -----
"firrtl.module"() ( {
%0 = "firrtl.output"() {name = "out"} : () -> !firrtl.uint
%1 = "firrtl.input"() {name = "b"} : () -> ui32
%2 = "firrtl.input"() {name = "d"} : () -> ui16
// expected-error @+1 {{'firrtl.add' op expected 2 operands, but found 3}}
%3 = "firrtl.add"(%1, %2, %3) : (ui32, ui16, ui32) -> ui32
}) {name = "Top"} : () -> ()

View File

@ -1,4 +1,6 @@
set(LIBS
MLIRFIRRTL
MLIRParser
MLIRSupport
MLIRIR

View File

@ -5,6 +5,7 @@
//
//===----------------------------------------------------------------------===//
#include "spt/Dialect/FIRRTL/IR/Ops.h"
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Pass/PassRegistry.h"
@ -16,6 +17,7 @@
using namespace llvm;
using namespace mlir;
using namespace spt;
static cl::opt<std::string>
inputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
@ -50,6 +52,7 @@ int main(int argc, char **argv) {
InitLLVM y(argc, argv);
registerDialect<StandardOpsDialect>();
registerDialect<firrtl::FIRRTLDialect>();
// Register any pass manager command line options.
registerPassManagerCLOptions();