Skip to content

Commit

Permalink
[DC] Add ops and types (#5157)
Browse files Browse the repository at this point in the history
  • Loading branch information
mortbopet authored May 11, 2023
1 parent de03ab5 commit 967b93f
Show file tree
Hide file tree
Showing 12 changed files with 588 additions and 1 deletion.
2 changes: 2 additions & 0 deletions include/circt/Dialect/DC/DC.td
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@
include "mlir/IR/OpBase.td"

include "circt/Dialect/DC/DCDialect.td"
include "circt/Dialect/DC/DCTypes.td"
include "circt/Dialect/DC/DCOps.td"

#endif // CIRCT_DIALECT_DC_DC_TD
6 changes: 6 additions & 0 deletions include/circt/Dialect/DC/DCDialect.td
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ def DCDialect : Dialect {
handshaking semantics.
}];
let cppNamespace = "circt::dc";

let useDefaultTypePrinterParser = 1;

let extraClassDeclaration = [{
void registerTypes();
}];
}

#endif // CIRCT_DIALECT_DC_DIALECT_TD
36 changes: 36 additions & 0 deletions include/circt/Dialect/DC/DCOps.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===- DCOps.h - DC dialect operations --------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef CIRCT_DIALECT_DC_DCOPS_H
#define CIRCT_DIALECT_DC_DCOPS_H

#include "mlir/IR/FunctionInterfaces.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/RegionKindInterface.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/Interfaces/CallInterfaces.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"
#include "mlir/Interfaces/InferTypeOpInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"

#include "circt/Dialect/DC/DCDialect.h"
#include "circt/Dialect/DC/DCTypes.h"

namespace circt {
namespace dc {

// Returns true if 't'is a `dc.value<i1>` type.
bool isI1ValueType(Type t);

} // namespace dc
} // namespace circt

#define GET_OP_CLASSES
#include "circt/Dialect/DC/DC.h.inc"

#endif // CIRCT_DIALECT_DC_DCOPS_H
224 changes: 224 additions & 0 deletions include/circt/Dialect/DC/DCOps.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
//===- DCOps.td - DC dialect operations --------------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef CIRCT_DIALECT_DC_OPS_TD
#define CIRCT_DIALECT_DC_OPS_TD

include "mlir/Interfaces/InferTypeOpInterface.td"
include "circt/Dialect/DC/DCDialect.td"
include "circt/Dialect/DC/DCTypes.td"
include "mlir/IR/FunctionInterfaces.td"
include "mlir/IR/OpAsmInterface.td"
include "mlir/IR/RegionKindInterface.td"
include "mlir/IR/SymbolInterfaces.td"
include "mlir/Interfaces/CallInterfaces.td"
include "mlir/Interfaces/ControlFlowInterfaces.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/IR/BuiltinAttributes.td"
include "mlir/IR/FunctionInterfaces.td"

class DCOp<string mnemonic, list<Trait> traits = []> :
Op<DCDialect, mnemonic, !listconcat(traits, [
Pure
])>;

class SameTypeConstraint<string lhs, string rhs>
: TypesMatchWith<"lhs and rhs types should be equivalent",
lhs, rhs, [{ $_self }]>;

def BufferOp : DCOp<"buffer",
[SameTypeConstraint<"input", "output">]> {
let summary = "Buffer operation";
let description = [{
The buffer operation may buffer a `dc.value` or `dc.token` typed SSA value.
In practice, this provides a mechanism to buffer data-side values in a
control-sensitive manner.

Example:
```mlir
%value_out = dc.buffer [2] %value : !dc.value<i32, i1, i4>
```
}];

let arguments = (ins
ValueOrTokenType:$input,
ConfinedAttr<I64Attr, [IntMinValue<1>]>:$size,
OptionalAttr<ArrayAttr>:$initValues
);
let results = (outs ValueOrTokenType:$output);

let assemblyFormat = "`[` $size `]` $input ($initValues^)? attr-dict `:` type($input)";
let hasVerifier = 1;
let builders = [OpBuilder<(
ins "Value":$input, "size_t":$size), [{
build($_builder, $_state, input.getType(), input, $_builder.getI64IntegerAttr(size), {});
}]>];

let extraClassDeclaration = [{
// Returns the data type of this buffer, if any.
std::optional<TypeRange> getInnerTypes() {
if(auto type = getInput().getType().dyn_cast<ValueType>())
return type.getInnerTypes();
return std::nullopt;
}

// Returns the initial values of this buffer as a vector of int64's.
FailureOr<SmallVector<int64_t>> getInitValueArray();
}];
}

def JoinOp : DCOp<"join"> {
let summary = "Synchronizes the incoming tokens with the outgoing token";
let description = [{
This operator synchronizes all incoming tokens. Synchronization implies applying
join semantics in between all in- and output ports.

Example:
```mlir
%0 = dc.join %a, %b
```
}];

let arguments = (ins Variadic<TokenType>:$tokens);
let results = (outs TokenType:$output);

let assemblyFormat = "$tokens attr-dict";
let hasCanonicalizer = 1;
let builders = [OpBuilder<(
ins "ValueRange":$tokens), [{
build($_builder, $_state, $_builder.getType<dc::TokenType>(), tokens);
}]>];
}

def ForkOp : DCOp<"fork"> {
let summary = "Splits the incoming token into multiple outgoing tokens";
let description = [{
This operator splits the incoming token into multiple outgoing tokens.

Example:
```mlir
%0, %1 = dc.fork [2] %a : !dc.token, !dc.token
```
}];

let arguments = (ins TokenType:$token);
let results = (outs Variadic<TokenType>:$outputs);
let hasCustomAssemblyFormat = 1;
let hasCanonicalizer = 1;

let builders = [OpBuilder<(
ins "Value":$token, "size_t":$numOutputs), [{
llvm::SmallVector<mlir::Type, 4> outputTypes(numOutputs, $_builder.getType<dc::TokenType>());
build($_builder, $_state, outputTypes, token);
}]>];
}

def BranchOp : DCOp<"branch"> {
let summary = "Branch operation";
let description = [{
The incoming select token is propagated to the selected output based on
the value of the condition.
}];

let arguments = (ins I1ValueType:$condition);
let results = (outs TokenType:$trueToken, TokenType:$falseToken);

let assemblyFormat = "$condition attr-dict";
}

def SelectOp : DCOp<"select"> {
let summary = "Select operation";
let description = [{
An input token is selected based on the value of the incoming select
signal, and propagated to the single output. Only the condition value,
the selected input, and the output will be transacted.
}];

let arguments = (ins I1ValueType:$condition, TokenType:$trueToken, TokenType:$falseToken);
let results = (outs TokenType:$output);
let assemblyFormat = "$condition `,` $trueToken `,` $falseToken attr-dict";
let hasCanonicalizer = 1;
}

def SinkOp : DCOp<"sink"> {
let summary = "Sink operation";
let description = [{
The sink operation will always accept any incoming tokens, and
discard them.
}];

let arguments = (ins TokenType:$token);
let results = (outs);
let assemblyFormat = "$token attr-dict";
}

def SourceOp : DCOp<"source"> {
let summary = "Source operation";
let description = [{
The source operation will always produce a token.
}];

let arguments = (ins);
let results = (outs TokenType:$output);
let assemblyFormat = "attr-dict";
let builders = [OpBuilder<(ins), [{
build($_builder, $_state, $_builder.getType<dc::TokenType>());
}]>];
}

def PackOp : DCOp<"pack", [InferTypeOpInterface]> {
let summary = "Pack operation";
let description = [{
An operation which packs together a !dc.token value with some other
value.
}];

let arguments = (ins TokenType:$token, Variadic<AnyType>:$inputs);
let results = (outs ValueType:$output);
let assemblyFormat = "$token `[` $inputs `]` attr-dict `:` type($inputs)";
let hasCanonicalizer = 1;
let hasFolder = 1;

let extraClassDeclaration = [{
/// Infer the return types of this operation.
static LogicalResult inferReturnTypes(MLIRContext *context,
std::optional<Location> loc,
ValueRange operands,
DictionaryAttr attrs,
mlir::OpaqueProperties properties,
mlir::RegionRange regions,
SmallVectorImpl<Type> &results);
}];
}

def UnpackOp : DCOp<"unpack", [InferTypeOpInterface]> {
let summary = "Unpack operation";
let description = [{
An operation which unpacks a !dc.value value into a !dc.token value
and its constituent values.
}];

let arguments = (ins ValueType:$input);
let results = (outs TokenType:$token, Variadic<AnyType>:$outputs);
let assemblyFormat = "$input attr-dict `:` type($input)";
let hasCanonicalizer = 1;
let hasFolder = 1;

let extraClassDeclaration = [{
/// Infer the return types of this operation.
static LogicalResult inferReturnTypes(MLIRContext *context,
std::optional<Location> loc,
ValueRange operands,
DictionaryAttr attrs,
mlir::OpaqueProperties properties,
mlir::RegionRange regions,
SmallVectorImpl<Type> &results);
}];
}

#endif // CIRCT_DIALECT_DC_OPS_TD
18 changes: 18 additions & 0 deletions include/circt/Dialect/DC/DCTypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===- DCTypes.h - DC dialect types -----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef CIRCT_DIALECT_DC_DCTYPES_H
#define CIRCT_DIALECT_DC_DCTYPES_H

#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Types.h"

#define GET_TYPEDEF_CLASSES
#include "circt/Dialect/DC/DCTypes.h.inc"

#endif // CIRCT_DIALECT_DC_DCTYPES_H
42 changes: 42 additions & 0 deletions include/circt/Dialect/DC/DCTypes.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//===- DCTypes.td - DC dialect types -----------------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef CIRCT_DIALECT_DC_TYPES_TD
#define CIRCT_DIALECT_DC_TYPES_TD

include "circt/Dialect/DC/DCDialect.td"
include "mlir/IR/AttrTypeBase.td"

class DCTypeDef<string name> : TypeDef<DCDialect, name> { }

def TokenType : DCTypeDef<"Token"> {
let mnemonic = "token";
let parameters = (ins );
let assemblyFormat = "";
}

// A value type is a set of values which is wrapped with token semantics.
def ValueType : DCTypeDef<"Value"> {
let mnemonic = "value";
let parameters = (ins ArrayRefParameter<"Type">:$innerTypes);
let assemblyFormat = "`<`$innerTypes`>`";
}

def I1ValueType : Type<
CPred<"circt::dc::isI1ValueType($_self)">, "must be a !dc.value<i1> type">,
BuildableType<"$_builder.getType<dc::ValueType>($_builder.getI1Type())"> {
}

def ValueOrTokenType : Type<
CPred<"$_self.isa<dc::ValueType, dc::TokenType>()">,
"must be a !dc.value or !dc.token type"> {
}



#endif // CIRCT_DIALECT_DC_TYPES_TD
2 changes: 2 additions & 0 deletions lib/Dialect/DC/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
add_circt_dialect_library(CIRCTDC
DCDialect.cpp
DCOps.cpp
DCTypes.cpp

ADDITIONAL_HEADER_DIRS
${CIRCT_MAIN_INCLUDE_DIR}/circt/Dialect/DC
Expand Down
4 changes: 3 additions & 1 deletion lib/Dialect/DC/DCDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//

#include "circt/Dialect/DC/DCDialect.h"
#include "mlir/Transforms/InliningUtils.h"
#include "circt/Dialect/DC/DCOps.h"
#include "circt/Dialect/DC/DCTypes.h"

using namespace circt;
using namespace dc;

void DCDialect::initialize() {
registerTypes();
addOperations<
#define GET_OP_LIST
#include "circt/Dialect/DC/DC.cpp.inc"
Expand Down
Loading

0 comments on commit 967b93f

Please sign in to comment.