[Handshake] Change join to accept all input types (#3860)

This commit lifts the unnecessary limitation of `JoinOp`'s only having one input type.
This commit is contained in:
Christian Ulmann 2022-09-12 10:11:54 +02:00 committed by GitHub
parent 4f74ca8ec8
commit d75838177a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 96 additions and 20 deletions

View File

@ -805,10 +805,10 @@ def JoinOp : Handshake_Op<"join", [
Example:
```mlir
%0 = join %a, %b, %c : i32
%0 = join %a, %b, %c : i32, i1, none
```
}];
let arguments = (ins Variadic<NoneType> : $data);
let arguments = (ins Variadic<AnyType> : $data);
let results = (outs NoneType : $result);
let skipDefaultBuilders = 1;

View File

@ -29,7 +29,7 @@
module {
handshake.func @top(%arg0: none, ...) -> (none) attributes {argNames = ["inCtrl"], resNames = ["outCtrl"]}{
%3 = buffer [1] seq %f#1 {initValues = [0]}: none
%ctrlOut = join %3, %arg0 : none
%ctrlOut = join %3, %arg0 : none, none
%f:2 = fork [2] %ctrlOut : none
return %f#0 : none
}

View File

@ -1428,28 +1428,34 @@ void JoinOp::build(OpBuilder &builder, OperationState &result,
result.types.push_back(type);
result.addOperands(operands);
sost::addAttributes(result, operands.size(), type);
result.addAttribute("control", BoolAttr::get(result.getContext(), true));
}
ParseResult JoinOp::parse(OpAsmParser &parser, OperationState &result) {
SmallVector<OpAsmParser::UnresolvedOperand, 4> allOperands;
Type type;
ArrayRef<Type> operandTypes(type);
SmallVector<Type, 1> dataOperandsTypes;
SmallVector<OpAsmParser::UnresolvedOperand, 4> operands;
SmallVector<Type> types;
llvm::SMLoc allOperandLoc = parser.getCurrentLocation();
int size;
if (sost::parseOperation(parser, allOperands, result, size, type, false))
if (parser.parseOperandList(operands) ||
parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
parser.parseTypeList(types))
return failure();
dataOperandsTypes.assign(size, type);
result.addTypes({type});
if (parser.resolveOperands(allOperands, dataOperandsTypes, allOperandLoc,
result.operands))
if (parser.resolveOperands(operands, types, allOperandLoc, result.operands))
return failure();
if (!result.attributes.get("control"))
result.addAttribute("control", BoolAttr::get(result.getContext(), true));
result.addTypes(NoneType::get(result.getContext()));
return success();
}
void JoinOp::print(OpAsmPrinter &p) { sost::printOp(p, *this, false); }
void JoinOp::print(OpAsmPrinter &p) {
p << " " << data();
p.printOptionalAttrDict((*this)->getAttrs(), {"control"});
p << " : " << data().getTypes();
}
/// Based on mlir::func::CallOp::verifySymbolUses
LogicalResult InstanceOp::verifySymbolUses(SymbolTableCollection &symbolTable) {

View File

@ -66,6 +66,6 @@ handshake.func @main(%arg0: index, %arg1: index, %v: i32, %mem : memref<10xi32>,
%loadData, %loadAddr = load [%arg0] %ldData, %fCtrl#0 : index, i32
%storeData, %storeAddr = store [%arg1] %v, %fCtrl#1 : index, i32
sink %loadData : i32
%finCtrl = join %stCtrl, %ldCtrl : none
%finCtrl = join %stCtrl, %ldCtrl : none, none
return %finCtrl : none
}

View File

@ -1,4 +1,4 @@
// RUN: circt-opt -lower-handshake-to-firrtl %s | FileCheck %s
// RUN: circt-opt -split-input-file -lower-handshake-to-firrtl %s | FileCheck %s
// CHECK-LABEL: firrtl.circuit "test_join" {
// CHECK: firrtl.module @handshake_join_2ins_1outs_ctrl(in %[[VAL_0:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>, in %[[VAL_1:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>, out %[[VAL_2:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>) {
@ -17,6 +17,37 @@
// CHECK: firrtl.module @test_join(in %[[VAL_11:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>, in %[[VAL_12:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>, in %[[VAL_13:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>, out %[[VAL_14:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>, out %[[VAL_15:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>, in %[[VAL_16:.*]]: !firrtl.clock, in %[[VAL_17:.*]]: !firrtl.uint<1>) {
// CHECK: %[[VAL_18:.*]], %[[VAL_19:.*]], %[[VAL_20:.*]] = firrtl.instance handshake_join0 @handshake_join_2ins_1outs_ctrl(in [[ARG0:.+]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>, in [[ARG1:.+]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>, out [[ARG2:.+]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>)
handshake.func @test_join(%arg0: none, %arg1: none, %arg2: none, ...) -> (none, none) {
%0 = join %arg0, %arg1 : none
%0 = join %arg0, %arg1 : none, none
return %0, %arg2 : none, none
}
// -----
// CHECK-LABEL: firrtl.module @handshake_join_in_ui32_ui1_3ins_1outs_ctrl(
// CHECK-SAME: in %[[VAL_0:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>, data: uint<32>>,
// CHECK-SAME: in %[[VAL_1:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>, data: uint<1>>,
// CHECK-SAME: in %[[VAL_2:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>,
// CHECK-SAME: out %[[VAL_3:.*]]: !firrtl.bundle<valid: uint<1>, ready flip: uint<1>>) {
// CHECK: %[[VAL_4:.*]] = firrtl.subfield %[[VAL_0]](0) : (!firrtl.bundle<valid: uint<1>, ready flip: uint<1>, data: uint<32>>) -> !firrtl.uint<1>
// CHECK: %[[VAL_5:.*]] = firrtl.subfield %[[VAL_0]](1) : (!firrtl.bundle<valid: uint<1>, ready flip: uint<1>, data: uint<32>>) -> !firrtl.uint<1>
// CHECK: %[[VAL_6:.*]] = firrtl.subfield %[[VAL_0]](2) : (!firrtl.bundle<valid: uint<1>, ready flip: uint<1>, data: uint<32>>) -> !firrtl.uint<32>
// CHECK: %[[VAL_7:.*]] = firrtl.subfield %[[VAL_1]](0) : (!firrtl.bundle<valid: uint<1>, ready flip: uint<1>, data: uint<1>>) -> !firrtl.uint<1>
// CHECK: %[[VAL_8:.*]] = firrtl.subfield %[[VAL_1]](1) : (!firrtl.bundle<valid: uint<1>, ready flip: uint<1>, data: uint<1>>) -> !firrtl.uint<1>
// CHECK: %[[VAL_9:.*]] = firrtl.subfield %[[VAL_1]](2) : (!firrtl.bundle<valid: uint<1>, ready flip: uint<1>, data: uint<1>>) -> !firrtl.uint<1>
// CHECK: %[[VAL_10:.*]] = firrtl.subfield %[[VAL_2]](0) : (!firrtl.bundle<valid: uint<1>, ready flip: uint<1>>) -> !firrtl.uint<1>
// CHECK: %[[VAL_11:.*]] = firrtl.subfield %[[VAL_2]](1) : (!firrtl.bundle<valid: uint<1>, ready flip: uint<1>>) -> !firrtl.uint<1>
// CHECK: %[[VAL_12:.*]] = firrtl.subfield %[[VAL_3]](0) : (!firrtl.bundle<valid: uint<1>, ready flip: uint<1>>) -> !firrtl.uint<1>
// CHECK: %[[VAL_13:.*]] = firrtl.subfield %[[VAL_3]](1) : (!firrtl.bundle<valid: uint<1>, ready flip: uint<1>>) -> !firrtl.uint<1>
// CHECK: %[[VAL_14:.*]] = firrtl.and %[[VAL_7]], %[[VAL_4]] : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
// CHECK: %[[VAL_15:.*]] = firrtl.and %[[VAL_10]], %[[VAL_14]] : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
// CHECK: firrtl.connect %[[VAL_12]], %[[VAL_15]] : !firrtl.uint<1>, !firrtl.uint<1>
// CHECK: %[[VAL_16:.*]] = firrtl.and %[[VAL_13]], %[[VAL_15]] : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
// CHECK: firrtl.connect %[[VAL_5]], %[[VAL_16]] : !firrtl.uint<1>, !firrtl.uint<1>
// CHECK: firrtl.connect %[[VAL_8]], %[[VAL_16]] : !firrtl.uint<1>, !firrtl.uint<1>
// CHECK: firrtl.connect %[[VAL_11]], %[[VAL_16]] : !firrtl.uint<1>, !firrtl.uint<1>
// CHECK: }
handshake.func @test_join_multi_types(%arg0: i32, %arg1: i1, %arg2: none, ...) -> (none) {
%0 = join %arg0, %arg1, %arg2 : i32, i1, none
return %0: none
}

View File

@ -31,7 +31,7 @@
handshake.func @main(%arg0: index, %arg1: none, ...) -> none {
%0:2 = memory [ld = 1, st= 0] (%addressResults) {id = 0 : i32, lsq = false} : memref<10xi8>, (index) -> (i8, none)
%1:2 = fork [2] %arg1 : none
%2 = join %1#1, %0#1 : none
%2 = join %1#1, %0#1 : none, none
%3, %addressResults = load [%arg0] %0#0, %1#0 : index, i8
sink %3 : i8
return %2 : none

View File

@ -72,6 +72,6 @@ handshake.func @main(%ldAddr: index, %stAddr: index, %v: i32, %mem : memref<10xi
%loadData, %loadAddr = load [%ldAddr] %ldData, %fCtrl#0 : index, i32
%storeData, %storeAddr = store [%stAddr] %v, %fCtrl#1 : index, i32
sink %loadData : i32
%finCtrl = join %stCtrl, %ldCtrl : none
%finCtrl = join %stCtrl, %ldCtrl : none, none
return %finCtrl : none
}

View File

@ -0,0 +1,39 @@
// RUN: circt-opt -split-input-file %s | circt-opt | FileCheck %s
// CHECK-LABEL: handshake.func @simple_multi_input(
// CHECK-SAME: %[[VAL_0:.*]]: none, %[[VAL_1:.*]]: none, %[[VAL_2:.*]]: none, ...) -> none
// CHECK: %[[VAL_3:.*]] = join %[[VAL_0]], %[[VAL_1]], %[[VAL_2]] : none, none, none
// CHECK: return %[[VAL_3]] : none
// CHECK: }
handshake.func @simple_multi_input(%in0: none, %in1: none, %in2: none, ...) -> (none) {
%ctrlOut = join %in0, %in1, %in2 : none, none, none
return %ctrlOut : none
}
// -----
// CHECK-LABEL: handshake.func @different_in_types(
// CHECK-SAME: %[[VAL_0:.*]]: tuple<i64, i32, i64>,
// CHECK-SAME: %[[VAL_1:.*]]: none, ...) -> none
// CHECK: %[[VAL_2:.*]] = join %[[VAL_0]], %[[VAL_1]] : tuple<i64, i32, i64>, none
// CHECK: return %[[VAL_2]] : none
// CHECK: }
handshake.func @different_in_types(%in: tuple<i64, i32, i64>, %arg1: none, ...) -> (none) {
%ctrlOut = join %in, %arg1 : tuple<i64, i32, i64>, none
return %ctrlOut : none
}
// -----
// CHECK-LABEL: handshake.func @superfluous_ctrl_attr(
// CHECK-SAME: %[[VAL_0:.*]]: none, %[[VAL_1:.*]]: none, ...) -> none
// CHECK: %[[VAL_2:.*]] = join %[[VAL_0]], %[[VAL_1]] : none, none
// CHECK: return %[[VAL_2]] : none
// CHECK: }
handshake.func @superfluous_ctrl_attr(%in: none, %arg1: none, ...) -> (none) {
%ctrlOut = join %in, %arg1 {control = true} : none, none
return %ctrlOut : none
}