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"
28StringRef sim::stringifyDPIDirectionKeyword(DPIDirection dir) {
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");
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);
54bool sim::isCallOperandDir(DPIDirection dir) {
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)
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)
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")
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.
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