16 #include "mlir/IR/Builders.h"
18 using namespace circt;
27 auto libraryOps = body->getOps<OperatorLibraryOp>();
28 auto graphOps = body->getOps<DependenceGraphOp>();
30 if (std::distance(libraryOps.begin(), libraryOps.end()) != 1 ||
31 std::distance(graphOps.begin(), graphOps.end()) != 1)
33 <<
"must contain exactly one 'library' op and one 'graph' op";
35 if ((*graphOps.begin())->isBeforeInBlock(*libraryOps.begin()))
37 <<
"must contain the 'library' op followed by the 'graph' op";
43 OperatorLibraryOp InstanceOp::getOperatorLibrary() {
44 return *getOps<OperatorLibraryOp>().begin();
47 DependenceGraphOp InstanceOp::getDependenceGraph() {
48 return *getOps<DependenceGraphOp>().begin();
55 ParseResult OperationOp::parse(OpAsmParser &parser, OperationState &result) {
56 auto &builder = parser.getBuilder();
59 SmallVector<Attribute> alreadyParsed;
61 if (parser.parseLess())
65 auto parseSymbolResult = parser.parseOptionalAttribute(oprRef);
66 if (parseSymbolResult.has_value()) {
67 assert(succeeded(*parseSymbolResult));
68 alreadyParsed.push_back(builder.getAttr<LinkedOperatorTypeAttr>(oprRef));
71 if (parser.parseGreater())
76 (void)parser.parseOptionalSymbolName(opName, SymbolTable::getSymbolAttrName(),
80 SmallVector<OpAsmParser::UnresolvedOperand> unresolvedOperands;
81 SmallVector<Attribute> dependences;
82 unsigned operandIdx = 0;
83 auto parseDependenceSourceWithAttrDict = [&]() -> ParseResult {
84 llvm::SMLoc loc = parser.getCurrentLocation();
85 FlatSymbolRefAttr sourceRef;
89 auto parseSymbolResult = parser.parseOptionalAttribute(sourceRef);
90 if (parseSymbolResult.has_value())
91 assert(succeeded(*parseSymbolResult));
94 OpAsmParser::UnresolvedOperand operand;
95 if (parser.parseOperand(operand))
96 return parser.emitError(loc,
"expected SSA value or symbol reference");
98 unresolvedOperands.push_back(operand);
105 if (sourceRef || properties)
106 dependences.push_back(
107 builder.getAttr<DependenceAttr>(operandIdx, sourceRef, properties));
113 if (parser.parseCommaSeparatedList(AsmParser::Delimiter::Paren,
114 parseDependenceSourceWithAttrDict))
117 if (!dependences.empty())
118 result.addAttribute(builder.getStringAttr(
"dependences"),
119 builder.getArrayAttr(dependences));
122 ArrayAttr properties;
123 auto parsePropertiesResult =
125 if (parsePropertiesResult.has_value()) {
126 if (failed(*parsePropertiesResult))
128 result.addAttribute(builder.getStringAttr(
"sspProperties"), properties);
132 if (parser.parseOptionalAttrDict(result.attributes))
136 SmallVector<Value> operands;
137 if (parser.resolveOperands(unresolvedOperands, builder.getNoneType(),
140 result.addOperands(operands);
143 SmallVector<Type> types(parser.getNumResults(), builder.getNoneType());
144 result.addTypes(types);
149 void OperationOp::print(OpAsmPrinter &p) {
151 SmallVector<Attribute> alreadyPrinted;
154 if (
auto linkedOpr = getLinkedOperatorTypeAttr()) {
155 p.printAttribute(linkedOpr.getValue());
156 alreadyPrinted.push_back(linkedOpr);
160 // (Scheduling) operation's name
161 if (StringAttr symName = getSymNameAttr()) {
163 p.printSymbolName(symName);
170 SmallVector<DependenceAttr> defUseDeps(getNumOperands()), auxDeps;
171 if (ArrayAttr dependences = getDependencesAttr()) {
172 for (
auto dep : dependences.getAsRange<DependenceAttr>()) {
173 if (dep.getSourceRef())
174 auxDeps.push_back(dep);
176 defUseDeps[dep.getOperandIdx()] = dep;
181 llvm::interleaveComma((*this)->getOpOperands(), p, [&](OpOperand &operand) {
182 p.printOperand(operand.get());
183 if (DependenceAttr dep = defUseDeps[operand.getOperandNumber()]) {
185 p.printAttribute(dep.getProperties());
188 if (!auxDeps.empty()) {
189 if (!defUseDeps.empty())
191 llvm::interleaveComma(auxDeps, p, [&](DependenceAttr dep) {
192 p.printAttribute(dep.getSourceRef());
193 if (ArrayAttr depProps = dep.getProperties()) {
195 printPropertyArray(depProps, p);
202 if (ArrayAttr properties = getSspPropertiesAttr()) {
208 SmallVector<StringRef> elidedAttrs = {
209 SymbolTable::getSymbolAttrName(),
210 OperationOp::getDependencesAttrName().getValue(),
211 OperationOp::getSspPropertiesAttrName().getValue()};
212 p.printOptionalAttrDict((*this)->getAttrs(), elidedAttrs);
216 ArrayAttr dependences = getDependencesAttr();
220 int nOperands = getNumOperands();
222 for (
auto dep : dependences.getAsRange<DependenceAttr>()) {
223 int idx = dep.getOperandIdx();
224 FlatSymbolRefAttr sourceRef = dep.getSourceRef();
228 if (idx >= nOperands)
230 "Operand index is out of bounds for def-use dependence attribute");
234 return emitError(
"Def-use operand indices in dependence attribute are "
235 "not monotonically increasing");
240 return emitError() <<
"Auxiliary dependence from " << sourceRef
241 <<
" is interleaved with SSA operands";
244 if (!((idx == lastIdx + 1) || (idx > lastIdx && idx == nOperands)))
245 return emitError(
"Auxiliary operand indices in dependence attribute "
246 "are not consecutive");
255 OperationOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
256 auto instanceOp = (*this)->getParentOfType<InstanceOp>();
257 auto libraryOp = instanceOp.getOperatorLibrary();
258 auto graphOp = instanceOp.getDependenceGraph();
262 if (ArrayAttr dependences = getDependencesAttr())
263 for (
auto dep : dependences.getAsRange<DependenceAttr>()) {
264 FlatSymbolRefAttr sourceRef = dep.getSourceRef();
268 Operation *sourceOp = symbolTable.lookupSymbolIn(graphOp, sourceRef);
269 if (!sourceOp || !isa<OperationOp>(sourceOp)) {
271 "Auxiliary dependence references invalid source operation: ")
278 if (
auto linkedOpr = getLinkedOperatorTypeAttr()) {
279 SymbolRefAttr oprRef = linkedOpr.getValue();
282 oprOp = symbolTable.lookupSymbolIn(libraryOp, oprRef);
285 oprOp = symbolTable.lookupSymbolIn(instanceOp, oprRef);
288 oprOp = symbolTable.lookupNearestSymbolFrom(instanceOp->getParentOp(),
291 if (!oprOp || !isa<OperatorTypeOp>(oprOp))
292 return emitError(
"Linked operator type property references invalid "
300 LinkedOperatorTypeAttr OperationOp::getLinkedOperatorTypeAttr() {
301 if (ArrayAttr properties = getSspPropertiesAttr()) {
302 const auto *it = llvm::find_if(
303 properties, [](Attribute a) {
return isa<LinkedOperatorTypeAttr>(a); });
304 if (it != properties.end())
305 return cast<LinkedOperatorTypeAttr>(*it);
316 if (!result.has_value() || succeeded(*result))
331 #define GET_OP_CLASSES
332 #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)
static LogicalResult verify(Value clock, bool eventExists, mlir::Location loc)
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.