CIRCT  20.0.0git
InteropOps.cpp
Go to the documentation of this file.
1 //===- InteropOps.cpp - Implement the Interop operations ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the Interop operations.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "mlir/IR/Builders.h"
15 #include "mlir/IR/OpImplementation.h"
16 
17 using namespace circt;
18 using namespace circt::interop;
19 
20 //===----------------------------------------------------------------------===//
21 // ProceduralInitOp
22 //===----------------------------------------------------------------------===//
23 
24 void ProceduralInitOp::build(OpBuilder &odsBuilder, OperationState &odsState,
25  ValueRange states,
26  InteropMechanism interopMechanism) {
27  Region *region = odsState.addRegion();
28  region->push_back(new Block);
29  odsState.addAttribute(
30  getInteropMechanismAttrName(odsState.name),
31  InteropMechanismAttr::get(odsBuilder.getContext(), interopMechanism));
32  odsState.addOperands(states);
33 }
34 
35 LogicalResult ProceduralInitOp::verify() {
36  if (getBody()->getNumArguments() > 0)
37  return emitOpError("region must not have any arguments");
38 
39  return success();
40 }
41 
42 //===----------------------------------------------------------------------===//
43 // ProceduralUpdateOp
44 //===----------------------------------------------------------------------===//
45 
46 void ProceduralUpdateOp::build(OpBuilder &odsBuilder, OperationState &odsState,
47  TypeRange outputs, ValueRange inputs,
48  ValueRange states,
49  InteropMechanism interopMechanism) {
50  Region *region = odsState.addRegion();
51  Block *bodyBlock = new Block;
52  bodyBlock->addArguments(
53  states.getTypes(),
54  SmallVector<Location>(states.size(), odsState.location));
55  bodyBlock->addArguments(
56  inputs.getTypes(),
57  SmallVector<Location>(inputs.size(), odsState.location));
58  region->push_back(bodyBlock);
59  odsState.addOperands(states);
60  odsState.addOperands(inputs);
61  odsState.addAttribute(getOperandSegmentSizesAttrName(odsState.name),
62  odsBuilder.getDenseI32ArrayAttr(
63  {(int32_t)states.size(), (int32_t)inputs.size()}));
64  odsState.addAttribute(
65  getInteropMechanismAttrName(odsState.name),
66  InteropMechanismAttr::get(odsBuilder.getContext(), interopMechanism));
67  odsState.addTypes(outputs);
68 }
69 
70 LogicalResult ProceduralUpdateOp::verify() {
71  if (getBody()->getNumArguments() != getStates().size() + getInputs().size())
72  return emitOpError("region must have the same number of arguments ")
73  << "as inputs and states together, but got "
74  << getBody()->getNumArguments() << " arguments and "
75  << (getStates().size() + getInputs().size())
76  << " state plus input types";
77 
78  SmallVector<Type> types{getStates().getTypes()};
79  types.append(SmallVector<Type>{getInputs().getTypes()});
80  if (getBody()->getArgumentTypes() != types)
81  return emitOpError("region argument types must match state types");
82 
83  return success();
84 }
85 
86 //===----------------------------------------------------------------------===//
87 // ProceduralDeallocOp
88 //===----------------------------------------------------------------------===//
89 
90 void ProceduralDeallocOp::build(OpBuilder &odsBuilder, OperationState &odsState,
91  ValueRange states,
92  InteropMechanism interopMechanism) {
93  Region *region = odsState.addRegion();
94  Block *bodyBlock = new Block;
95  region->push_back(bodyBlock);
96  bodyBlock->addArguments(
97  states.getTypes(),
98  SmallVector<Location>(states.size(), odsState.location));
99  odsState.addAttribute(
100  getInteropMechanismAttrName(odsState.name),
101  InteropMechanismAttr::get(odsBuilder.getContext(), interopMechanism));
102  odsState.addOperands(states);
103 }
104 
105 LogicalResult ProceduralDeallocOp::verify() {
106  if (getBody()->getNumArguments() != getStates().size())
107  return emitOpError("region must have the same number of arguments ")
108  << "as states, but got " << getBody()->getNumArguments()
109  << " arguments and " << getStates().size() << " states";
110 
111  if (getBody()->getArgumentTypes() != getStates().getTypes())
112  return emitOpError("region argument types must match state types");
113 
114  return success();
115 }
116 
117 //===----------------------------------------------------------------------===//
118 // ReturnOp
119 //===----------------------------------------------------------------------===//
120 
121 LogicalResult ReturnOp::verify() {
122  auto *parent = getOperation()->getParentOp();
123  ValueRange values;
124 
125  if (isa<ProceduralUpdateOp>(parent))
126  values = parent->getResults();
127  else
128  values = parent->getOperands();
129 
130  if (getNumOperands() != values.size())
131  return emitOpError("has ")
132  << getNumOperands()
133  << " operands, but enclosing interop operation requires "
134  << values.size() << " values";
135 
136  for (auto it :
137  llvm::enumerate(llvm::zip(getOperandTypes(), values.getTypes()))) {
138  auto [returnOperandType, parentType] = it.value();
139  if (returnOperandType != parentType)
140  return emitError() << "type of return operand " << it.index() << " ("
141  << returnOperandType
142  << ") doesn't match required type (" << parentType
143  << ")";
144  }
145 
146  return success();
147 }
148 
149 //===----------------------------------------------------------------------===//
150 // TableGen generated logic.
151 //===----------------------------------------------------------------------===//
152 
153 // Provide the autogenerated implementation guts for the Op classes.
154 #define GET_OP_CLASSES
155 #include "circt/Dialect/Interop/Interop.cpp.inc"
156 #include "circt/Dialect/Interop/InteropEnums.cpp.inc"
static LogicalResult verify(Value clock, bool eventExists, mlir::Location loc)
Definition: SVOps.cpp:2467
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:55
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21