14 #include "mlir/IR/Builders.h"
15 #include "mlir/IR/DialectImplementation.h"
16 #include "mlir/Interfaces/FunctionImplementation.h"
18 using namespace circt;
31 SmallVectorImpl<Attribute> &resultNames,
32 SmallVectorImpl<Type> &resultTypes,
33 SmallVectorImpl<DictionaryAttr> &resultAttrs,
34 SmallVectorImpl<Attribute> &resultLocs) {
36 auto parseElt = [&]() -> ParseResult {
38 auto irLoc = parser.getCurrentLocation();
42 if (parser.parseKeywordOrString(&portName))
47 resultTypes.emplace_back();
48 if (parser.parseColonType(resultTypes.back()))
53 if (failed(parser.parseOptionalAttrDict(attrs)))
55 resultAttrs.push_back(attrs.getDictionary(parser.getContext()));
58 std::optional<Location> maybeLoc;
59 if (failed(parser.parseOptionalLocationSpecifier(maybeLoc)))
61 Location loc = maybeLoc ? *maybeLoc : parser.getEncodedSourceLoc(irLoc);
62 resultLocs.push_back(loc);
67 return parser.parseCommaSeparatedList(OpAsmParser::Delimiter::Paren,
73 if (
auto mod = dyn_cast<HWModuleLike>(module)) {
74 if (argNo < mod.getNumInputPorts())
75 return mod.getInputName(argNo);
78 auto argNames = module->getAttrOfType<ArrayAttr>(
"argNames");
80 if (argNames && argNo < argNames.size())
81 return argNames[argNo].cast<StringAttr>().getValue();
86 if (
auto mod = dyn_cast<HWModuleLike>(module)) {
87 if (resultNo < mod.getNumOutputPorts())
88 return mod.getOutputName(resultNo);
91 auto resultNames = module->getAttrOfType<ArrayAttr>(
"resultNames");
93 if (resultNames && resultNo < resultNames.size())
94 return resultNames[resultNo].cast<StringAttr>().getValue();
99 ArrayRef<Type> argTypes,
101 ArrayRef<Type> resultTypes,
102 bool &needArgNamesAttr) {
103 using namespace mlir::function_interface_impl;
105 Region &body = op->getRegion(0);
106 bool isExternal = body.empty();
107 SmallString<32> resultNameStr;
108 mlir::OpPrintingFlags flags;
113 auto modOp = dyn_cast<hw::HWModuleLike>(op);
114 auto funcOp = dyn_cast<mlir::FunctionOpInterface>(op);
115 SmallVector<Attribute> inputAttrs, outputAttrs;
117 if (
auto args = funcOp.getAllArgAttrs())
118 for (
auto a : args.getValue())
119 inputAttrs.push_back(a);
120 inputAttrs.resize(funcOp.getNumArguments());
121 if (
auto results = funcOp.getAllResultAttrs())
122 for (
auto a : results.getValue())
123 outputAttrs.push_back(a);
124 outputAttrs.resize(funcOp.getNumResults());
126 inputAttrs = modOp.getAllInputAttrs();
127 outputAttrs = modOp.getAllOutputAttrs();
131 for (
unsigned i = 0, e = argTypes.size(); i < e; ++i) {
138 resultNameStr.clear();
139 llvm::raw_svector_ostream tmpStream(resultNameStr);
140 p.printOperand(body.front().getArgument(i), tmpStream);
143 if (tmpStream.str().drop_front() != argName)
144 needArgNamesAttr =
true;
146 p << tmpStream.str() <<
": ";
147 }
else if (!argName.empty()) {
148 p <<
'%' << argName <<
": ";
151 p.printType(argTypes[i]);
152 auto inputAttr = inputAttrs[i];
153 p.printOptionalAttrDict(inputAttr
154 ? cast<DictionaryAttr>(inputAttr).getValue()
155 : ArrayRef<NamedAttribute>());
160 if (flags.shouldPrintDebugInfo()) {
161 auto loc = modOp.getInputLoc(i);
162 if (!isa<UnknownLoc>(loc))
163 p.printOptionalLocationSpecifier(loc);
168 if (!argTypes.empty())
176 if (!resultTypes.empty()) {
178 for (
size_t i = 0, e = resultTypes.size(); i < e; ++i) {
183 p.printType(resultTypes[i]);
184 auto outputAttr = outputAttrs[i];
185 p.printOptionalAttrDict(outputAttr
186 ? cast<DictionaryAttr>(outputAttr).getValue()
187 : ArrayRef<NamedAttribute>());
192 if (flags.shouldPrintDebugInfo()) {
193 auto loc = modOp.getOutputLoc(i);
194 if (!isa<UnknownLoc>(loc))
195 p.printOptionalLocationSpecifier(loc);
203 OpAsmParser &parser,
bool &isVariadic,
204 SmallVectorImpl<OpAsmParser::Argument> &args,
205 SmallVectorImpl<Attribute> &argNames, SmallVectorImpl<Attribute> &argLocs,
206 SmallVectorImpl<Attribute> &resultNames,
207 SmallVectorImpl<DictionaryAttr> &resultAttrs,
208 SmallVectorImpl<Attribute> &resultLocs, TypeAttr &type) {
210 using namespace mlir::function_interface_impl;
211 auto *context = parser.getContext();
214 if (parser.parseArgumentList(args, OpAsmParser::Delimiter::Paren,
219 SmallVector<Type> resultTypes;
220 if (succeeded(parser.parseOptionalArrow()))
222 resultAttrs, resultLocs)))
226 SmallVector<Type> argTypes;
227 for (
auto &arg : args) {
229 argTypes.push_back(arg.type);
231 arg.sourceLoc = parser.getEncodedSourceLoc(arg.ssaName.location);
232 argLocs.push_back(*arg.sourceLoc);
251 if (succeeded(p.parseOptionalKeyword(&keyword))) {
252 result = keyword.str();
257 if (succeeded(p.parseOptionalString(&result)))
264 if (failed(p.parseKeyword(&key)))
265 return p.emitError(p.getCurrentLocation(),
"expected port direction");
268 else if (key ==
"out")
270 else if (key ==
"inout")
273 return p.emitError(p.getCurrentLocation(),
"unknown port direction '")
280 if (parser.parseOperand(result.ssaName,
false))
297 if (parser.parseColonType(result.type) ||
298 parser.parseOptionalAttrDict(attrs) ||
299 parser.parseOptionalLocationSpecifier(result.sourceLoc))
301 result.attrs = attrs.getDictionary(parser.getContext());
308 auto irLoc = parser.getCurrentLocation();
311 if (parser.parseKeywordOrString(&result.
rawName))
315 if (parser.parseColonType(result.type))
320 if (failed(parser.parseOptionalAttrDict(attrs)))
322 result.attrs = attrs.getDictionary(parser.getContext());
325 std::optional<Location> maybeLoc;
326 if (failed(parser.parseOptionalLocationSpecifier(maybeLoc)))
328 result.sourceLoc = maybeLoc ? *maybeLoc : parser.getEncodedSourceLoc(irLoc);
350 SmallVectorImpl<module_like_impl::PortParse> &result) {
351 auto parseOnePort = [&]() -> ParseResult {
352 return parsePort(p, result.emplace_back());
354 return p.parseCommaSeparatedList(OpAsmParser::Delimiter::Paren, parseOnePort,
359 OpAsmParser &parser, SmallVectorImpl<PortParse> &args, TypeAttr &modType) {
361 auto *context = parser.getContext();
368 SmallVector<ModulePort> ports;
369 for (
auto &arg : args) {
376 arg.sourceLoc = parser.getEncodedSourceLoc(arg.ssaName.location);
390 assert(0 &&
"Unknown port direction");
397 Region &body = op->getRegion(0);
398 bool isExternal = body.empty();
399 SmallString<32> resultNameStr;
400 mlir::OpPrintingFlags flags;
403 auto typeAttr = op->getAttrOfType<TypeAttr>(
"module_type");
404 auto modType = cast<ModuleType>(typeAttr.getValue());
405 auto portAttrs = op->getAttrOfType<ArrayAttr>(
"per_port_attrs");
406 auto locAttrs = op->getAttrOfType<ArrayAttr>(
"port_locs");
409 for (
auto [i, port] : llvm::enumerate(modType.getPorts())) {
415 p.printKeywordOrString(port.name);
419 resultNameStr.clear();
420 llvm::raw_svector_ostream tmpStream(resultNameStr);
421 p.printOperand(body.front().getArgument(curArg), tmpStream);
422 p <<
" " << tmpStream.str();
425 if (tmpStream.str().drop_front() != port.name) {
427 p.printKeywordOrString(port.name);
430 p <<
" %" << port.name.getValue();
435 p.printType(port.type);
436 if (portAttrs && !portAttrs.empty())
437 if (
auto attr = dyn_cast<DictionaryAttr>(portAttrs[i]))
438 p.printOptionalAttrDict(attr.getValue());
443 if (flags.shouldPrintDebugInfo() && locAttrs)
444 if (
auto loc = locAttrs[i])
445 if (!isa<UnknownLoc>(loc))
446 p.printOptionalLocationSpecifier(cast<Location>(loc));
assert(baseType &&"element must be base type")
static ParseResult parseDirection(OpAsmParser &p, ModulePort::Direction &dir)
static const char * directionAsString(ModulePort::Direction dir)
static ParseResult parsePortList(OpAsmParser &p, SmallVectorImpl< module_like_impl::PortParse > &result)
ParseResult parseOptionalKeywordOrOptionalString(OpAsmParser &p, std::string &result, bool &found)
Parse an optional keyword or string and set instance into 'result'.
static StringRef getModuleResultName(Operation *module, size_t resultNo)
static ParseResult parseInputPort(OpAsmParser &parser, module_like_impl::PortParse &result)
static ParseResult parseOutputPort(OpAsmParser &parser, module_like_impl::PortParse &result)
static ParseResult parsePort(OpAsmParser &p, module_like_impl::PortParse &result)
Parse a single argument with the following syntax:
static StringRef getModuleArgumentName(Operation *module, size_t argNo)
Return the port name for the specified argument or result.
static ParseResult parseFunctionResultList(OpAsmParser &parser, SmallVectorImpl< Attribute > &resultNames, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs, SmallVectorImpl< Attribute > &resultLocs)
Parse a function result list.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
void printModuleSignature(OpAsmPrinter &p, Operation *op, ArrayRef< Type > argTypes, bool isVariadic, ArrayRef< Type > resultTypes, bool &needArgNamesAttr)
Print a module signature with named results.
ParseResult parseModuleSignature(OpAsmParser &parser, SmallVectorImpl< PortParse > &args, TypeAttr &modType)
New Style parsing.
ParseResult parseModuleFunctionSignature(OpAsmParser &parser, bool &isVariadic, SmallVectorImpl< OpAsmParser::Argument > &args, SmallVectorImpl< Attribute > &argNames, SmallVectorImpl< Attribute > &argLocs, SmallVectorImpl< Attribute > &resultNames, SmallVectorImpl< DictionaryAttr > &resultAttrs, SmallVectorImpl< Attribute > &resultLocs, TypeAttr &type)
This is a variant of mlir::parseFunctionSignature that allows names on result arguments.
void printModuleSignatureNew(OpAsmPrinter &p, Operation *op)
static StringAttr getNameFromSSA(MLIRContext *context, StringRef name)
Get a name from an SSA value string, if said value name is not a number.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
ModulePort::Direction direction