CIRCT 24.0.0git
Loading...
Searching...
No Matches
SimTypes.cpp
Go to the documentation of this file.
1//===- SimTypes.cpp -------------------------------------------------------===//
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
12#include "mlir/IR/Builders.h"
13#include "mlir/IR/DialectImplementation.h"
14#include "llvm/ADT/DenseSet.h"
15#include "llvm/ADT/TypeSwitch.h"
16
17// Include the generated enum definitions (DPIDirection).
18#include "circt/Dialect/Sim/SimEnums.h.inc"
19
20using namespace circt;
21using namespace sim;
22using namespace mlir;
23
24//===----------------------------------------------------------------------===//
25// DPIDirection helpers
26//===----------------------------------------------------------------------===//
27
28StringRef sim::stringifyDPIDirectionKeyword(DPIDirection dir) {
29 switch (dir) {
30 case DPIDirection::Input:
31 return "in";
32 case DPIDirection::Output:
33 return "out";
34 case DPIDirection::InOut:
35 return "inout";
36 case DPIDirection::Return:
37 return "return";
38 case DPIDirection::Ref:
39 return "ref";
40 }
41 llvm_unreachable("unknown DPIDirection");
42}
43
44std::optional<DPIDirection> sim::parseDPIDirectionKeyword(StringRef keyword) {
45 return llvm::StringSwitch<std::optional<DPIDirection>>(keyword)
46 .Case("in", DPIDirection::Input)
47 .Case("out", DPIDirection::Output)
48 .Case("inout", DPIDirection::InOut)
49 .Case("return", DPIDirection::Return)
50 .Case("ref", DPIDirection::Ref)
51 .Default(std::nullopt);
52}
53
54bool sim::isCallOperandDir(DPIDirection dir) {
55 return dir == DPIDirection::Input || dir == DPIDirection::InOut ||
56 dir == DPIDirection::Ref;
57}
58
59#define GET_TYPEDEF_CLASSES
60#include "circt/Dialect/Sim/SimTypes.cpp.inc"
61
62void SimDialect::registerTypes() {
63 addTypes<
64#define GET_TYPEDEF_LIST
65#include "circt/Dialect/Sim/SimTypes.cpp.inc"
66 >();
67}
68
69//===----------------------------------------------------------------------===//
70// DPIFunctionType storage
71//===----------------------------------------------------------------------===//
72
74 ArrayRef<DPIArgument> dpiArgs)
75 : arguments(dpiArgs) {
76 for (auto [idx, a] : llvm::enumerate(arguments)) {
77 if (a.dir == DPIDirection::Input || a.dir == DPIDirection::InOut ||
78 a.dir == DPIDirection::Ref)
79 inputToAbs.push_back(idx);
80 if (a.dir == DPIDirection::Output || a.dir == DPIDirection::InOut ||
81 a.dir == DPIDirection::Return)
82 resultToAbs.push_back(idx);
83 }
84}
85
87sim::detail::DPIFunctionTypeStorage::construct(TypeStorageAllocator &allocator,
88 const KeyTy &key) {
89 auto *storage = new (allocator.allocate<DPIFunctionTypeStorage>())
91 // Compute and cache the MLIR FunctionType.
92 SmallVector<Type> inputs, results;
93 for (auto &arg : storage->arguments) {
94 if (arg.dir == DPIDirection::Input || arg.dir == DPIDirection::InOut ||
95 arg.dir == DPIDirection::Ref)
96 inputs.push_back(arg.type);
97 if (arg.dir == DPIDirection::Output || arg.dir == DPIDirection::InOut ||
98 arg.dir == DPIDirection::Return)
99 results.push_back(arg.type);
100 }
101 MLIRContext *ctx = nullptr;
102 if (!storage->arguments.empty()) {
103 ctx = storage->arguments[0].type.getContext();
104 assert(ctx && "DPIArgument types must have a valid MLIRContext");
105 }
106 if (ctx)
107 storage->cachedFuncType = FunctionType::get(ctx, inputs, results);
108 return storage;
109}
110
111//===----------------------------------------------------------------------===//
112// DPIFunctionType methods
113//===----------------------------------------------------------------------===//
114
115ArrayRef<DPIArgument> DPIFunctionType::getArguments() const {
116 return getImpl()->getArguments();
117}
118
119size_t DPIFunctionType::getNumArguments() const {
120 return getImpl()->arguments.size();
121}
122
123SmallVector<DPIArgument> DPIFunctionType::getInputArguments() const {
124 SmallVector<DPIArgument> result;
125 for (auto idx : getImpl()->inputToAbs)
126 result.push_back(getImpl()->arguments[idx]);
127 return result;
128}
129
130SmallVector<DPIArgument> DPIFunctionType::getResultArguments() const {
131 SmallVector<DPIArgument> result;
132 for (auto idx : getImpl()->resultToAbs)
133 result.push_back(getImpl()->arguments[idx]);
134 return result;
135}
136
137const DPIArgument *DPIFunctionType::getReturnArgument() const {
138 auto &args = getImpl()->arguments;
139 if (!args.empty() && args.back().dir == DPIDirection::Return)
140 return &args.back();
141 return nullptr;
142}
143
144FunctionType DPIFunctionType::getFunctionType() const {
145 auto cached = getImpl()->getCachedFunctionType();
146 if (cached)
147 return cached;
148 // Empty argument list — context unavailable during storage construction.
149 return FunctionType::get(getContext(), {}, {});
150}
151
152LogicalResult
153DPIFunctionType::verify(function_ref<InFlightDiagnostic()> emitError) const {
154 auto dpiArgs = getArguments();
155 unsigned returnCount = 0;
156 for (auto [i, arg] : llvm::enumerate(dpiArgs)) {
157 if (arg.dir == DPIDirection::Return) {
158 ++returnCount;
159 if (i != dpiArgs.size() - 1)
160 return emitError() << "'return' argument must be the last argument";
161 }
162 }
163 if (returnCount > 1)
164 return emitError() << "must have at most one 'return' argument";
165 return success();
166}
167
168//===----------------------------------------------------------------------===//
169// DPIFunctionType parser/printer
170//===----------------------------------------------------------------------===//
171
172/// Parse: !sim.dpi_functy<input "a" : i32, output "b" : i32>
173Type DPIFunctionType::parse(AsmParser &parser) {
174 SmallVector<DPIArgument> args;
175 if (parser.parseLess())
176 return {};
177
178 // Handle empty argument list.
179 if (succeeded(parser.parseOptionalGreater()))
180 return get(parser.getContext(), args);
181
182 auto parseOneArg = [&]() -> ParseResult {
183 StringRef dirKeyword;
184 if (parser.parseKeyword(&dirKeyword))
185 return failure();
186 auto dir = parseDPIDirectionKeyword(dirKeyword);
187 if (!dir) {
188 parser.emitError(parser.getCurrentLocation(),
189 "expected DPI argument direction keyword");
190 return failure();
191 }
192 std::string name;
193 if (parser.parseString(&name))
194 return failure();
195 Type type;
196 if (parser.parseColonType(type))
197 return failure();
198 args.push_back({StringAttr::get(parser.getContext(), name), type, *dir});
199 return success();
200 };
201
202 if (parser.parseCommaSeparatedList(parseOneArg) || parser.parseGreater())
203 return {};
204 return get(parser.getContext(), args);
205}
206
207/// Print: !sim.dpi_functy<input "a" : i32, output "b" : i32>
208void DPIFunctionType::print(AsmPrinter &printer) const {
209 printer << '<';
210 llvm::interleaveComma(getArguments(), printer, [&](const DPIArgument &arg) {
211 printer << stringifyDPIDirectionKeyword(arg.dir) << ' ';
212 printer << '"' << arg.name.getValue() << '"';
213 printer << " : ";
214 printer.printType(arg.type);
215 });
216 printer << '>';
217}
218
219//===----------------------------------------------------------------------===//
220// VariantType
221//===----------------------------------------------------------------------===//
222
223/// Parse: !sim.variant<a: i32, b: i8>
224Type VariantType::parse(AsmParser &p) {
225 SmallVector<Alternative, 4> alternatives;
226 SmallVector<std::pair<llvm::SMLoc, StringAttr>> duplicates;
227 auto parseResult = parseFieldList(p, alternatives, duplicates);
228 for (auto [loc, name] : duplicates)
229 p.emitError(loc) << "duplicate alternative name '" << name.getValue()
230 << "' in sim.variant type";
231 if (failed(parseResult) || !duplicates.empty())
232 return Type();
233 return get(p.getContext(), alternatives);
234}
235
236/// Print: !sim.variant<a: i32, b: i8>
237void VariantType::print(AsmPrinter &p) const {
238 printFieldList(p, getAlternatives());
239}
240
241LogicalResult VariantType::verify(function_ref<InFlightDiagnostic()> emitError,
242 ArrayRef<Alternative> alternatives) {
243 llvm::SmallDenseSet<StringAttr> nameSet;
244 LogicalResult result = success();
245 nameSet.reserve(alternatives.size());
246 for (const auto &alternative : alternatives)
247 if (!nameSet.insert(alternative.name).second) {
248 result = failure();
249 emitError() << "duplicate alternative name '"
250 << alternative.name.getValue() << "' in sim.variant type";
251 }
252 return result;
253}
254
255std::optional<uint32_t> VariantType::getAlternativeIndex(StringAttr name) {
256 ArrayRef<Alternative> alternatives = getAlternatives();
257 for (size_t idx = 0, numAlternatives = alternatives.size();
258 idx < numAlternatives; ++idx)
259 if (alternatives[idx].name == name)
260 return idx;
261 return {};
262}
263
264std::optional<uint32_t> VariantType::getAlternativeIndex(StringRef name) {
265 return getAlternativeIndex(StringAttr::get(getContext(), name));
266}
267
268VariantType::Alternative VariantType::getAlternative(StringRef name) {
269 if (auto index = getAlternativeIndex(name))
270 return getAlternatives()[*index];
271 return Alternative();
272}
273
274Type VariantType::getAlternativeType(StringRef name) {
275 return getAlternative(name).type;
276}
assert(baseType &&"element must be base type")
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition CalyxOps.cpp:56
llvm::StringRef stringifyDPIDirectionKeyword(DPIDirection dir)
Return the keyword string for a DPIDirection (e.g. "in", "return").
Definition SimTypes.cpp:28
std::optional< DPIDirection > parseDPIDirectionKeyword(llvm::StringRef keyword)
Parse a keyword string to a DPIDirection. Returns std::nullopt on failure.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
ParseResult parseFieldList(AsmParser &p, SmallVectorImpl< FieldInfo > &fields, SmallVectorImpl< std::pair< llvm::SMLoc, StringAttr > > &duplicates)
Parse a list of named fields within <>, e.g.
Definition FieldInfo.cpp:15
void printFieldList(AsmPrinter &p, ArrayRef< FieldInfo > fields)
Print a list of fields within <>, e.g. <foo: i7, bar: i8>.
Definition FieldInfo.cpp:38
Definition sim.py:1
llvm::SmallVector< DPIArgument > arguments
Definition SimTypes.h:76
DPIFunctionTypeStorage(llvm::ArrayRef< DPIArgument > args)
Definition SimTypes.cpp:73
llvm::SmallVector< size_t > inputToAbs
Definition SimTypes.h:77
llvm::SmallVector< size_t > resultToAbs
Definition SimTypes.h:78
static DPIFunctionTypeStorage * construct(mlir::TypeStorageAllocator &allocator, const KeyTy &key)
Definition SimTypes.cpp:87
llvm::ArrayRef< DPIArgument > KeyTy
Definition SimTypes.h:55