CIRCT 20.0.0git
Loading...
Searching...
No Matches
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
17using namespace circt;
18using namespace circt::interop;
19
20//===----------------------------------------------------------------------===//
21// ProceduralInitOp
22//===----------------------------------------------------------------------===//
23
24void 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
35LogicalResult 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
46void 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
70LogicalResult 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
90void 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
105LogicalResult 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
121LogicalResult 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"
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.