16#include "mlir/IR/Builders.h"
17#include "llvm/Support/raw_ostream.h"
26LogicalResult InstanceOp::verify() {
28 auto libraryOps = body->getOps<OperatorLibraryOp>();
29 auto graphOps = body->getOps<DependenceGraphOp>();
31 if (std::distance(libraryOps.begin(), libraryOps.end()) != 1 ||
32 std::distance(graphOps.begin(), graphOps.end()) != 1)
34 <<
"must contain exactly one 'library' op and one 'graph' op";
36 if ((*graphOps.begin())->isBeforeInBlock(*libraryOps.begin()))
38 <<
"must contain the 'library' op followed by the 'graph' op";
44OperatorLibraryOp InstanceOp::getOperatorLibrary() {
45 return *getOps<OperatorLibraryOp>().begin();
48ResourceLibraryOp InstanceOp::getResourceLibrary() {
49 return *getOps<ResourceLibraryOp>().begin();
52DependenceGraphOp InstanceOp::getDependenceGraph() {
53 return *getOps<DependenceGraphOp>().begin();
60LogicalResult DependenceGraphOp::verifyRegions() {
64 for (
auto opOp : getOps<OperationOp>()) {
65 if (StringAttr name = opOp.getNameAttr()) {
66 [[maybe_unused]]
auto [it, ins] = namedOps.try_emplace(name, opOp);
68 return emitError(
"Contains multiple operations named @")
74 for (
auto opOp : getOps<OperationOp>()) {
75 if (ArrayAttr dependences = opOp.getDependencesAttr()) {
76 for (
auto dep : dependences.getAsRange<DependenceAttr>()) {
77 StringAttr sourceRef = dep.getSourceRef();
81 if (!namedOps.contains(sourceRef))
82 return opOp->emitError(
"Auxiliary dependence references invalid "
83 "source operation: @")
84 << sourceRef.getValue();
91OperationOp DependenceGraphOp::lookupNamedOperation(StringRef name) {
92 auto opOps = getOps<OperationOp>();
93 auto it = find_if(opOps, [&](OperationOp opOp) {
94 StringAttr nameAttr = opOp.getNameAttr();
95 return nameAttr && nameAttr.getValue() == name;
97 return it != opOps.end() ? *it : OperationOp{};
104ParseResult OperationOp::parse(OpAsmParser &parser, OperationState &result) {
105 auto &builder = parser.getBuilder();
108 SmallVector<Attribute> alreadyParsed;
110 if (parser.parseLess())
113 SymbolRefAttr oprRef;
114 auto parseSymbolResult = parser.parseOptionalAttribute(oprRef);
115 if (parseSymbolResult.has_value()) {
116 assert(succeeded(*parseSymbolResult));
117 alreadyParsed.push_back(builder.getAttr<LinkedOperatorTypeAttr>(oprRef));
120 if (parser.parseGreater())
125 (void)parser.parseOptionalSymbolName(opName,
"name", result.attributes);
128 SmallVector<OpAsmParser::UnresolvedOperand> unresolvedOperands;
129 SmallVector<Attribute> dependences;
130 unsigned operandIdx = 0;
131 auto parseDependenceSourceWithAttrDict = [&]() -> ParseResult {
132 llvm::SMLoc loc = parser.getCurrentLocation();
133 StringAttr sourceRef;
134 ArrayAttr properties;
137 if (parser.parseOptionalSymbolName(sourceRef)) {
139 OpAsmParser::UnresolvedOperand operand;
140 if (parser.parseOperand(operand))
141 return parser.emitError(loc,
"expected SSA value or symbol reference");
143 unresolvedOperands.push_back(operand);
150 if (sourceRef || properties)
151 dependences.push_back(
152 builder.getAttr<DependenceAttr>(operandIdx, sourceRef, properties));
158 if (parser.parseCommaSeparatedList(AsmParser::Delimiter::Paren,
159 parseDependenceSourceWithAttrDict))
162 if (succeeded(parser.parseOptionalKeyword(
"uses"))) {
163 SmallVector<Attribute> rsrcRefs;
164 auto parseOne = [&]() -> ParseResult {
165 SymbolRefAttr rsrcRef;
166 if (parser.parseAttribute(rsrcRef))
167 return parser.emitError(parser.getCurrentLocation(),
168 "expected symbol reference inside uses[...]");
169 rsrcRefs.push_back(rsrcRef);
172 if (parser.parseCommaSeparatedList(OpAsmParser::Delimiter::Square,
176 auto linkedRsrcsAttr = builder.getAttr<LinkedResourceTypesAttr>(
177 builder.getArrayAttr(rsrcRefs));
179 alreadyParsed.push_back(linkedRsrcsAttr);
182 if (!dependences.empty())
183 result.addAttribute(builder.getStringAttr(
"dependences"),
184 builder.getArrayAttr(dependences));
187 ArrayAttr properties;
188 auto parsePropertiesResult =
190 if (parsePropertiesResult.has_value()) {
191 if (failed(*parsePropertiesResult))
193 result.addAttribute(builder.getStringAttr(
"sspProperties"), properties);
197 if (parser.parseOptionalAttrDict(result.attributes))
201 SmallVector<Value> operands;
202 if (parser.resolveOperands(unresolvedOperands, builder.getNoneType(),
205 result.addOperands(operands);
208 SmallVector<Type> types(parser.getNumResults(), builder.getNoneType());
209 result.addTypes(types);
214void OperationOp::print(OpAsmPrinter &p) {
216 SmallVector<Attribute> alreadyPrinted;
219 if (
auto linkedOpr = getLinkedOperatorTypeAttr()) {
220 p.printAttribute(linkedOpr.getValue());
221 alreadyPrinted.push_back(linkedOpr);
226 if (StringAttr name = getNameAttr()) {
228 p.printSymbolName(name);
235 SmallVector<DependenceAttr> defUseDeps(getNumOperands()), auxDeps;
236 if (ArrayAttr dependences = getDependencesAttr()) {
237 for (
auto dep : dependences.getAsRange<DependenceAttr>()) {
238 if (dep.getSourceRef())
239 auxDeps.push_back(dep);
241 defUseDeps[dep.getOperandIdx()] = dep;
246 llvm::interleaveComma((*this)->getOpOperands(), p, [&](OpOperand &operand) {
247 p.printOperand(operand.get());
248 if (DependenceAttr dep = defUseDeps[operand.getOperandNumber()]) {
250 p.printAttribute(dep.getProperties());
253 if (!auxDeps.empty()) {
254 if (!defUseDeps.empty())
256 llvm::interleaveComma(auxDeps, p, [&](DependenceAttr dep) {
257 p.printSymbolName(dep.getSourceRef());
258 if (ArrayAttr depProps = dep.getProperties()) {
266 if (ArrayAttr properties = getSspPropertiesAttr()) {
267 for (
auto attr : properties) {
268 if (
auto linkedRsrcs = dyn_cast<LinkedResourceTypesAttr>(attr)) {
269 auto rsrcList = linkedRsrcs.getValue();
270 if (!rsrcList.empty()) {
272 llvm::interleaveComma(
273 rsrcList, p, [&](Attribute rsrc) { p.printAttribute(rsrc); });
276 alreadyPrinted.push_back(linkedRsrcs);
282 if (ArrayAttr properties = getSspPropertiesAttr()) {
288 SmallVector<StringRef> elidedAttrs = {
289 OperationOp::getNameAttrName().getValue(),
290 OperationOp::getDependencesAttrName().getValue(),
291 OperationOp::getSspPropertiesAttrName().getValue()};
292 p.printOptionalAttrDict((*this)->getAttrs(), elidedAttrs);
295LogicalResult OperationOp::verify() {
296 ArrayAttr dependences = getDependencesAttr();
300 int nOperands = getNumOperands();
302 for (
auto dep : dependences.getAsRange<DependenceAttr>()) {
303 int idx = dep.getOperandIdx();
304 StringAttr sourceRef = dep.getSourceRef();
308 if (idx >= nOperands)
310 "Operand index is out of bounds for def-use dependence attribute");
314 return emitError(
"Def-use operand indices in dependence attribute are "
315 "not monotonically increasing");
320 return emitError() <<
"Auxiliary dependence from @"
321 << sourceRef.getValue()
322 <<
" is interleaved with SSA operands";
325 if (!((idx == lastIdx + 1) || (idx > lastIdx && idx == nOperands)))
326 return emitError(
"Auxiliary operand indices in dependence attribute "
327 "are not consecutive");
336OperationOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
337 auto instanceOp = (*this)->getParentOfType<InstanceOp>();
338 auto libraryOp = instanceOp.getOperatorLibrary();
342 if (
auto linkedOpr = getLinkedOperatorTypeAttr()) {
343 SymbolRefAttr oprRef = linkedOpr.getValue();
346 oprOp = symbolTable.lookupSymbolIn(libraryOp, oprRef);
349 oprOp = symbolTable.lookupSymbolIn(instanceOp, oprRef);
352 oprOp = symbolTable.lookupNearestSymbolFrom(instanceOp->getParentOp(),
355 if (!oprOp || !isa<OperatorTypeOp>(oprOp))
356 return emitError(
"Linked operator type property references invalid "
364LinkedOperatorTypeAttr OperationOp::getLinkedOperatorTypeAttr() {
365 if (ArrayAttr properties = getSspPropertiesAttr()) {
366 const auto *it = llvm::find_if(
367 properties, [](Attribute a) {
return isa<LinkedOperatorTypeAttr>(a); });
368 if (it != properties.end())
369 return cast<LinkedOperatorTypeAttr>(*it);
374LinkedResourceTypesAttr OperationOp::getLinkedResourceTypesAttr() {
375 if (ArrayAttr properties = getSspPropertiesAttr()) {
376 const auto *it = llvm::find_if(properties, [](Attribute a) {
377 return isa<LinkedResourceTypesAttr>(a);
379 if (it != properties.end())
380 return cast<LinkedResourceTypesAttr>(*it);
391 if (!result.has_value() || succeeded(*result))
406#define GET_OP_CLASSES
407#include "circt/Dialect/SSP/SSP.cpp.inc"
assert(baseType &&"element must be base type")
static Block * getBodyBlock(FModuleLike mod)
static void printSSPProperties(OpAsmPrinter &p, Operation *op, ArrayAttr attr)
static ParseResult parseSSPProperties(OpAsmParser &parser, ArrayAttr &attr)
void printPropertyArray(ArrayAttr attr, AsmPrinter &p, ArrayRef< Attribute > alreadyPrinted={})
Print an array attribute, suppressing the #ssp.
mlir::OptionalParseResult parseOptionalPropertyArray(ArrayAttr &attr, AsmParser &parser, ArrayRef< Attribute > alreadyParsed={})
Parse an array of attributes while recognizing the properties of the SSP dialect even without a #ssp.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.