12#include "mlir/IR/Builders.h"
13#include "mlir/IR/DialectImplementation.h"
14#include "llvm/ADT/TypeSwitch.h"
17#include "circt/Dialect/Sim/SimEnums.h.inc"
27StringRef sim::stringifyDPIDirectionKeyword(DPIDirection dir) {
29 case DPIDirection::Input:
31 case DPIDirection::Output:
33 case DPIDirection::InOut:
35 case DPIDirection::Return:
37 case DPIDirection::Ref:
40 llvm_unreachable(
"unknown DPIDirection");
43std::optional<DPIDirection> sim::parseDPIDirectionKeyword(StringRef keyword) {
44 return llvm::StringSwitch<std::optional<DPIDirection>>(keyword)
45 .Case(
"in", DPIDirection::Input)
46 .Case(
"out", DPIDirection::Output)
47 .Case(
"inout", DPIDirection::InOut)
48 .Case(
"return", DPIDirection::Return)
49 .Case(
"ref", DPIDirection::Ref)
50 .Default(std::nullopt);
53bool sim::isCallOperandDir(DPIDirection dir) {
54 return dir == DPIDirection::Input || dir == DPIDirection::InOut ||
55 dir == DPIDirection::Ref;
58#define GET_TYPEDEF_CLASSES
59#include "circt/Dialect/Sim/SimTypes.cpp.inc"
61void SimDialect::registerTypes() {
63#define GET_TYPEDEF_LIST
64#include "circt/Dialect/Sim/SimTypes.cpp.inc"
73 ArrayRef<DPIArgument> dpiArgs)
74 : arguments(dpiArgs) {
75 for (
auto [idx, a] : llvm::enumerate(
arguments)) {
76 if (a.dir == DPIDirection::Input || a.dir == DPIDirection::InOut ||
77 a.dir == DPIDirection::Ref)
79 if (a.dir == DPIDirection::Output || a.dir == DPIDirection::InOut ||
80 a.dir == DPIDirection::Return)
91 SmallVector<Type> inputs, results;
92 for (
auto &arg : storage->arguments) {
93 if (arg.dir == DPIDirection::Input || arg.dir == DPIDirection::InOut ||
94 arg.dir == DPIDirection::Ref)
95 inputs.push_back(arg.type);
96 if (arg.dir == DPIDirection::Output || arg.dir == DPIDirection::InOut ||
97 arg.dir == DPIDirection::Return)
98 results.push_back(arg.type);
100 MLIRContext *ctx =
nullptr;
101 if (!storage->arguments.empty()) {
102 ctx = storage->arguments[0].type.getContext();
103 assert(ctx &&
"DPIArgument types must have a valid MLIRContext");
106 storage->cachedFuncType = FunctionType::get(ctx, inputs, results);
114ArrayRef<DPIArgument> DPIFunctionType::getArguments()
const {
115 return getImpl()->getArguments();
118size_t DPIFunctionType::getNumArguments()
const {
119 return getImpl()->arguments.size();
122SmallVector<DPIArgument> DPIFunctionType::getInputArguments()
const {
123 SmallVector<DPIArgument> result;
124 for (
auto idx : getImpl()->inputToAbs)
125 result.push_back(getImpl()->arguments[idx]);
129SmallVector<DPIArgument> DPIFunctionType::getResultArguments()
const {
130 SmallVector<DPIArgument> result;
131 for (
auto idx : getImpl()->resultToAbs)
132 result.push_back(getImpl()->arguments[idx]);
136const DPIArgument *DPIFunctionType::getReturnArgument()
const {
137 auto &args = getImpl()->arguments;
138 if (!args.empty() && args.back().dir == DPIDirection::Return)
143FunctionType DPIFunctionType::getFunctionType()
const {
144 auto cached = getImpl()->getCachedFunctionType();
148 return FunctionType::get(getContext(), {}, {});
152DPIFunctionType::verify(function_ref<InFlightDiagnostic()> emitError)
const {
153 auto dpiArgs = getArguments();
154 unsigned returnCount = 0;
155 for (
auto [i, arg] :
llvm::enumerate(dpiArgs)) {
156 if (arg.dir == DPIDirection::Return) {
158 if (i != dpiArgs.size() - 1)
159 return emitError() <<
"'return' argument must be the last argument";
163 return emitError() <<
"must have at most one 'return' argument";
172Type DPIFunctionType::parse(AsmParser &parser) {
173 SmallVector<DPIArgument> args;
174 if (parser.parseLess())
178 if (succeeded(parser.parseOptionalGreater()))
179 return get(parser.getContext(), args);
181 auto parseOneArg = [&]() -> ParseResult {
182 StringRef dirKeyword;
183 if (parser.parseKeyword(&dirKeyword))
187 parser.emitError(parser.getCurrentLocation(),
188 "expected DPI argument direction keyword");
192 if (parser.parseString(&name))
195 if (parser.parseColonType(type))
197 args.push_back({StringAttr::get(parser.getContext(), name), type, *dir});
201 if (parser.parseCommaSeparatedList(parseOneArg) || parser.parseGreater())
203 return get(parser.getContext(), args);
207void DPIFunctionType::print(AsmPrinter &printer)
const {
209 llvm::interleaveComma(getArguments(), printer, [&](
const DPIArgument &arg) {
211 printer <<
'"' << arg.name.getValue() <<
'"';
213 printer.printType(arg.type);
assert(baseType &&"element must be base type")
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
llvm::StringRef stringifyDPIDirectionKeyword(DPIDirection dir)
Return the keyword string for a DPIDirection (e.g. "in", "return").
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.
llvm::SmallVector< DPIArgument > arguments
DPIFunctionTypeStorage(llvm::ArrayRef< DPIArgument > args)
llvm::SmallVector< size_t > inputToAbs
llvm::SmallVector< size_t > resultToAbs
static DPIFunctionTypeStorage * construct(mlir::TypeStorageAllocator &allocator, const KeyTy &key)
llvm::ArrayRef< DPIArgument > KeyTy