12#include "mlir/IR/Builders.h"
13#include "mlir/IR/DialectImplementation.h"
14#include "llvm/ADT/DenseSet.h"
15#include "llvm/ADT/TypeSwitch.h"
18#include "circt/Dialect/Sim/SimEnums.h.inc"
30 case DPIDirection::Input:
32 case DPIDirection::Output:
34 case DPIDirection::InOut:
36 case DPIDirection::Return:
38 case DPIDirection::Ref:
41 llvm_unreachable(
"unknown DPIDirection");
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);
55 return dir == DPIDirection::Input || dir == DPIDirection::InOut ||
56 dir == DPIDirection::Ref;
59#define GET_TYPEDEF_CLASSES
60#include "circt/Dialect/Sim/SimTypes.cpp.inc"
62void SimDialect::registerTypes() {
64#define GET_TYPEDEF_LIST
65#include "circt/Dialect/Sim/SimTypes.cpp.inc"
74 ArrayRef<DPIArgument> dpiArgs)
76 for (
auto [idx, a] : llvm::enumerate(
arguments)) {
77 if (a.dir == DPIDirection::Input || a.dir == DPIDirection::InOut ||
78 a.dir == DPIDirection::Ref)
80 if (a.dir == DPIDirection::Output || a.dir == DPIDirection::InOut ||
81 a.dir == DPIDirection::Return)
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);
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");
107 storage->cachedFuncType = FunctionType::get(ctx, inputs, results);
115ArrayRef<DPIArgument> DPIFunctionType::getArguments()
const {
116 return getImpl()->getArguments();
119size_t DPIFunctionType::getNumArguments()
const {
120 return getImpl()->arguments.size();
123SmallVector<DPIArgument> DPIFunctionType::getInputArguments()
const {
124 SmallVector<DPIArgument> result;
125 for (
auto idx : getImpl()->inputToAbs)
126 result.push_back(getImpl()->arguments[idx]);
130SmallVector<DPIArgument> DPIFunctionType::getResultArguments()
const {
131 SmallVector<DPIArgument> result;
132 for (
auto idx : getImpl()->resultToAbs)
133 result.push_back(getImpl()->arguments[idx]);
137const DPIArgument *DPIFunctionType::getReturnArgument()
const {
138 auto &args = getImpl()->arguments;
139 if (!args.empty() && args.back().dir == DPIDirection::Return)
144FunctionType DPIFunctionType::getFunctionType()
const {
145 auto cached = getImpl()->getCachedFunctionType();
149 return FunctionType::get(getContext(), {}, {});
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) {
159 if (i != dpiArgs.size() - 1)
160 return emitError() <<
"'return' argument must be the last argument";
164 return emitError() <<
"must have at most one 'return' argument";
173Type DPIFunctionType::parse(AsmParser &parser) {
174 SmallVector<DPIArgument> args;
175 if (parser.parseLess())
179 if (succeeded(parser.parseOptionalGreater()))
180 return get(parser.getContext(), args);
182 auto parseOneArg = [&]() -> ParseResult {
183 StringRef dirKeyword;
184 if (parser.parseKeyword(&dirKeyword))
188 parser.emitError(parser.getCurrentLocation(),
189 "expected DPI argument direction keyword");
193 if (parser.parseString(&name))
196 if (parser.parseColonType(type))
198 args.push_back({StringAttr::get(parser.getContext(), name), type, *dir});
202 if (parser.parseCommaSeparatedList(parseOneArg) || parser.parseGreater())
204 return get(parser.getContext(), args);
208void DPIFunctionType::print(AsmPrinter &printer)
const {
210 llvm::interleaveComma(getArguments(), printer, [&](
const DPIArgument &arg) {
212 printer <<
'"' << arg.name.getValue() <<
'"';
214 printer.printType(arg.type);
224Type VariantType::parse(AsmParser &p) {
225 SmallVector<Alternative, 4> alternatives;
226 SmallVector<std::pair<llvm::SMLoc, StringAttr>> 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())
233 return get(p.getContext(), alternatives);
237void VariantType::print(AsmPrinter &p)
const {
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) {
249 emitError() <<
"duplicate alternative name '"
250 << alternative.name.getValue() <<
"' in sim.variant type";
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)
264std::optional<uint32_t> VariantType::getAlternativeIndex(StringRef name) {
265 return getAlternativeIndex(StringAttr::get(getContext(), name));
268VariantType::Alternative VariantType::getAlternative(StringRef name) {
269 if (
auto index = getAlternativeIndex(name))
270 return getAlternatives()[*index];
271 return Alternative();
274Type VariantType::getAlternativeType(StringRef name) {
275 return getAlternative(name).type;
assert(baseType &&"element must be base type")
false return failure()
Parse an optional keyword or string and set instance into 'result'.
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.
bool isCallOperandDir(DPIDirection dir)
True if an argument with this direction is a call operand (input/inout/ref).
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.
void printFieldList(AsmPrinter &p, ArrayRef< FieldInfo > fields)
Print a list of fields within <>, e.g. <foo: i7, bar: i8>.
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