Skip to content

Commit

Permalink
[Ibis] Add ibis.method.df operation (#6163)
Browse files Browse the repository at this point in the history
Ibis dataflow methods share the same interface as an `ibis.method` but without imperative CFG-based control flow. Instead, this method implements a graph region, and control flow is expected to be defined by dataflow operations.
  • Loading branch information
mortbopet authored Sep 21, 2023
1 parent e6989c8 commit 77630d5
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 26 deletions.
1 change: 1 addition & 0 deletions include/circt/Dialect/Ibis/IbisOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef CIRCT_DIALECT_IBIS_IBISOPS_H
#define CIRCT_DIALECT_IBIS_IBISOPS_H

#include "circt/Dialect/Handshake/HandshakeInterfaces.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Support/InstanceGraphInterface.h"
Expand Down
59 changes: 44 additions & 15 deletions include/circt/Dialect/Ibis/IbisOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Interfaces/InferTypeOpInterface.td"
include "mlir/IR/BuiltinAttributeInterfaces.td"

include "circt/Dialect/Handshake/HandshakeInterfaces.td"
include "circt/Dialect/HW/HWOpInterfaces.td"
include "circt/Dialect/Ibis/IbisInterfaces.td"
include "circt/Dialect/Ibis/IbisTypes.td"
Expand Down Expand Up @@ -136,30 +137,23 @@ def InstanceOp : InstanceOpBase<"instance"> {
}];
}

def MethodOp : IbisOp<"method", [

class MethodOpBase<string mnemonic, list<Trait> traits = []> :
IbisOp<mnemonic, !listconcat(traits, [
IsolatedFromAbove,
Symbol, FunctionOpInterface,
AutomaticAllocationScope,
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmBlockArgumentNames"]>,
HasParent<"ClassOp">]> {

let summary = "Ibis method";
let description = [{
Ibis functions are a lot like software functions: a list of named arguments
and unnamed return values.

Can only live inside of classes.
}];
HasParent<"ClassOp">
])> {

let arguments = (ins SymbolNameAttr:$sym_name,
TypeAttrOf<FunctionType>:$function_type,
ArrayAttr:$argNames,
OptionalAttr<DictArrayAttr>:$arg_attrs,
OptionalAttr<DictArrayAttr>:$res_attrs);
let regions = (region AnyRegion:$body);
let hasCustomAssemblyFormat = 1;

let extraClassDeclaration = [{
code extraMethodClassDeclaration = "";
let extraClassDeclaration = extraMethodClassDeclaration # [{
//===------------------------------------------------------------------===//
// FunctionOpInterface Methods
//===------------------------------------------------------------------===//
Expand All @@ -179,8 +173,43 @@ def MethodOp : IbisOp<"method", [
}];
}

def MethodOp : MethodOpBase<"method", [
AutomaticAllocationScope,
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmBlockArgumentNames"]>
]> {

let summary = "Ibis method";
let description = [{
Ibis methods are a lot like software functions: a list of named arguments
and unnamed return values with imperative control flow.
}];

let regions = (region AnyRegion:$body);
}

def DataflowMethodOp : MethodOpBase<"method.df", [
SingleBlockImplicitTerminator<"ibis::ReturnOp">,
RegionKindInterface,
FineGrainedDataflowRegionOpInterface
]> {

let summary = "Ibis dataflow method";
let description = [{
Ibis dataflow methods share the same interface as an `ibis.method` but
without imperative CFG-based control flow. Instead, this method implements a
graph region, and control flow is expected to be defined by dataflow operations.
}];
let regions = (region SizedRegion<1>:$body);

let extraMethodClassDeclaration = [{
// Implement RegionKindInterface.
static RegionKind getRegionKind(unsigned index) { return RegionKind::Graph; }
}];
}

def ReturnOp : IbisOp<"return", [
Pure, ReturnLike, Terminator, HasParent<"MethodOp">]> {
Pure, ReturnLike, Terminator,
ParentOneOf<["MethodOp", "DataflowMethodOp"]>]> {
let summary = "Ibis method terminator";

let arguments = (ins Variadic<AnyType>:$retValues);
Expand Down
46 changes: 35 additions & 11 deletions lib/Dialect/Ibis/IbisOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ LogicalResult circt::ibis::detail::verifyScopeOpInterface(Operation *op) {
// MethodOp
//===----------------------------------------------------------------------===//

ParseResult MethodOp::parse(OpAsmParser &parser, OperationState &result) {
template <typename TOp>
ParseResult parseMethodLikeOp(OpAsmParser &parser, OperationState &result) {
// Parse the name as a symbol.
StringAttr nameAttr;
if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
Expand Down Expand Up @@ -163,8 +164,7 @@ ParseResult MethodOp::parse(OpAsmParser &parser, OperationState &result) {
return failure();

result.addAttribute("argNames", ArrayAttr::get(context, argNames));
result.addAttribute(MethodOp::getFunctionTypeAttrName(result.name),
functionType);
result.addAttribute(TOp::getFunctionTypeAttrName(result.name), functionType);

// Parse the function body.
auto *body = result.addRegion();
Expand All @@ -174,22 +174,29 @@ ParseResult MethodOp::parse(OpAsmParser &parser, OperationState &result) {
return success();
}

void MethodOp::print(OpAsmPrinter &p) {
FunctionType funcTy = getFunctionType();
template <typename TOp>
void printMethodLikeOp(TOp op, OpAsmPrinter &p) {
FunctionType funcTy = op.getFunctionType();
p << ' ';
p.printSymbolName(getSymName());
p.printSymbolName(op.getSymName());
function_interface_impl::printFunctionSignature(
p, *this, funcTy.getInputs(), /*isVariadic=*/false, funcTy.getResults());
p.printOptionalAttrDictWithKeyword(getOperation()->getAttrs(),
getAttributeNames());
Region &body = getBody();
p, op, funcTy.getInputs(), /*isVariadic=*/false, funcTy.getResults());
p.printOptionalAttrDictWithKeyword(op.getOperation()->getAttrs(),
op.getAttributeNames());
Region &body = op.getBody();
if (!body.empty()) {
p << ' ';
p.printRegion(body, /*printEntryBlockArgs=*/false,
/*printBlockTerminators=*/true);
}
}

ParseResult MethodOp::parse(OpAsmParser &parser, OperationState &result) {
return parseMethodLikeOp<MethodOp>(parser, result);
}

void MethodOp::print(OpAsmPrinter &p) { return printMethodLikeOp(*this, p); }

void MethodOp::getAsmBlockArgumentNames(mlir::Region &region,
OpAsmSetValueNameFn setNameFn) {
if (region.empty())
Expand All @@ -204,11 +211,28 @@ void MethodOp::getAsmBlockArgumentNames(mlir::Region &region,
setNameFn(block->getArgument(idx), argName);
}

//===----------------------------------------------------------------------===//
// DataflowMethodOp
//===----------------------------------------------------------------------===//

ParseResult DataflowMethodOp::parse(OpAsmParser &parser,
OperationState &result) {
return parseMethodLikeOp<DataflowMethodOp>(parser, result);
}

void DataflowMethodOp::print(OpAsmPrinter &p) {
return printMethodLikeOp(*this, p);
}

//===----------------------------------------------------------------------===//
// ReturnOp
//===----------------------------------------------------------------------===//

void ReturnOp::build(OpBuilder &odsBuilder, OperationState &odsState) {}

LogicalResult ReturnOp::verify() {
// Check that the return operand type matches the function return type.
auto func = cast<MethodOp>((*this)->getParentOp());
auto func = cast<FunctionOpInterface>((*this)->getParentOp());
ArrayRef<Type> resTypes = func.getResultTypes();

if (getNumOperands() != resTypes.size())
Expand Down
9 changes: 9 additions & 0 deletions test/Dialect/Ibis/round-trip.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
// CHECK-NEXT: }
// CHECK-NEXT: ibis.return %0#0, %0#1 : i32, i32
// CHECK-NEXT: }
// CHECK-NEXT: ibis.method.df @bar(%arg0: none) -> none {
// CHECK-NEXT: %0 = handshake.join %arg0 : none
// CHECK-NEXT: ibis.return %0 : none
// CHECK-NEXT: }
// CHECK-NEXT: }

ibis.class @HighLevel {
Expand All @@ -39,6 +43,11 @@ ibis.class @HighLevel {
}
ibis.return %out1, %out2 : i32, i32
}

ibis.method.df @bar(%arg0 : none) -> (none) {
%0 = handshake.join %arg0 : none
ibis.return %0 : none
}
}


Expand Down

0 comments on commit 77630d5

Please sign in to comment.