14 #ifndef CIRCT_DIALECT_SSP_SSPUTILITIES_H
15 #define CIRCT_DIALECT_SSP_SSPUTILITIES_H
22 #include "mlir/IR/ImplicitLocOpBuilder.h"
23 #include "mlir/IR/SymbolTable.h"
25 #include "llvm/ADT/DenseMap.h"
26 #include "llvm/ADT/TypeSwitch.h"
40 template <
typename ProblemT>
42 template <
typename ProblemT,
typename OperationPropertyT,
43 typename... OperationPropertyTs>
47 for (
auto prop : props) {
48 TypeSwitch<Attribute>(prop)
49 .Case<OperationPropertyT, OperationPropertyTs...>(
50 [&](
auto p) { p.setInProblem(prob, op); });
54 template <
typename ProblemT>
56 template <
typename ProblemT,
typename OperatorTypePropertyT,
57 typename... OperatorTypePropertyTs>
62 for (
auto prop : props) {
63 TypeSwitch<Attribute>(prop)
64 .Case<OperatorTypePropertyT, OperatorTypePropertyTs...>(
65 [&](
auto p) { p.setInProblem(prob, opr); });
69 template <
typename ProblemT>
71 template <
typename ProblemT,
typename DependencePropertyT,
72 typename... DependencePropertyTs>
76 for (
auto prop : props) {
77 TypeSwitch<Attribute>(prop)
78 .Case<DependencePropertyT, DependencePropertyTs...>(
79 [&](
auto p) { p.setInProblem(prob, dep); });
83 template <
typename ProblemT>
85 template <
typename ProblemT,
typename InstancePropertyT,
86 typename... InstancePropertyTs>
90 for (
auto prop : props) {
91 TypeSwitch<Attribute>(prop).Case<InstancePropertyT, InstancePropertyTs...>(
92 [&](
auto p) { p.setInProblem(prob); });
100 template <
typename ProblemT,
typename... OperatorTypePropertyTs>
104 unsigned &
id = oprIds[opr];
107 opr.getValue() + Twine(
'_') + Twine(
id));
109 assert(!prob.hasOperatorType(opr));
110 prob.insertOperatorType(opr);
112 prob, opr, oprOp.getSspPropertiesAttr());
137 template <
typename ProblemT,
typename... OperationPropertyTs,
138 typename... OperatorTypePropertyTs,
typename... DependencePropertyTs,
139 typename... InstancePropertyTs>
141 std::tuple<OperationPropertyTs...> opProps,
142 std::tuple<OperatorTypePropertyTs...> oprProps,
143 std::tuple<DependencePropertyTs...> depProps,
144 std::tuple<InstancePropertyTs...> instProps) {
145 ProblemT prob(instOp);
148 prob, instOp.getSspPropertiesAttr());
149 if (
auto instName = instOp.getSymNameAttr())
150 prob.setInstanceName(instName);
160 auto libraryOp = instOp.getOperatorLibrary();
161 libraryOp.walk([&](OperatorTypeOp oprOp) {
162 operatorTypes[oprOp] =
166 if (
auto libName = libraryOp.getSymNameAttr())
167 prob.setLibraryName(libName);
170 auto graphOp = instOp.getDependenceGraph();
171 graphOp.walk([&](OperationOp opOp) {
172 prob.insertOperation(opOp);
174 prob, opOp, opOp.getSspPropertiesAttr());
175 if (
auto opName = opOp.getSymNameAttr())
176 prob.setOperationName(opOp, opName);
181 if (!prob.getLinkedOperatorType(opOp).has_value())
186 SymbolRefAttr oprRef = opOp.getLinkedOperatorTypeAttr().getValue();
190 oprOp = SymbolTable::lookupSymbolIn(libraryOp, oprRef);
193 oprOp = SymbolTable::lookupSymbolIn(instOp, oprRef);
197 SymbolTable::lookupNearestSymbolFrom(instOp->getParentOp(), oprRef);
199 assert(oprOp && isa<OperatorTypeOp>(oprOp));
202 auto &opr = operatorTypes[oprOp];
205 prob, cast<OperatorTypeOp>(oprOp), operatorTypeIds);
208 prob.setLinkedOperatorType(opOp, opr);
213 graphOp.walk([&](OperationOp opOp) {
214 ArrayAttr depsAttr = opOp.getDependencesAttr();
218 for (
auto depAttr : depsAttr.getAsRange<DependenceAttr>()) {
220 if (FlatSymbolRefAttr sourceRef = depAttr.getSourceRef()) {
221 Operation *sourceOp = SymbolTable::lookupSymbolIn(graphOp, sourceRef);
224 LogicalResult res = prob.insertDependence(dep);
228 dep =
Dependence(&opOp->getOpOperand(depAttr.getOperandIdx()));
231 prob, dep, depAttr.getProperties());
242 template <
typename ProblemT,
typename... OperationPropertyTs>
244 ImplicitLocOpBuilder &b) {
245 SmallVector<Attribute> props;
249 ((prop = OperationPropertyTs::getFromProblem(prob, op, b.getContext()),
250 prop ? props.push_back(prop) : (void)prop),
252 return props.empty() ? ArrayAttr() : b.getArrayAttr(props);
255 template <
typename ProblemT,
typename... OperatorTypePropertyTs>
257 ImplicitLocOpBuilder &b) {
258 SmallVector<Attribute> props;
262 ((prop = OperatorTypePropertyTs::getFromProblem(prob, opr, b.getContext()),
263 prop ? props.push_back(prop) : (void)prop),
265 return props.empty() ? ArrayAttr() : b.getArrayAttr(props);
268 template <
typename ProblemT,
typename... DependencePropertyTs>
270 ImplicitLocOpBuilder &b) {
271 SmallVector<Attribute> props;
275 ((prop = DependencePropertyTs::getFromProblem(prob, dep, b.getContext()),
276 prop ? props.push_back(prop) : (void)prop),
278 return props.empty() ? ArrayAttr() : b.getArrayAttr(props);
281 template <
typename ProblemT,
typename... InstancePropertyTs>
283 SmallVector<Attribute> props;
287 ((prop = InstancePropertyTs::getFromProblem(prob, b.getContext()),
288 prop ? props.push_back(prop) : (void)prop),
290 return props.empty() ? ArrayAttr() : b.getArrayAttr(props);
316 template <
typename ProblemT,
typename... OperationPropertyTs,
317 typename... OperatorTypePropertyTs,
typename... DependencePropertyTs,
318 typename... InstancePropertyTs>
320 saveProblem(ProblemT &prob, std::tuple<OperationPropertyTs...> opProps,
321 std::tuple<OperatorTypePropertyTs...> oprProps,
322 std::tuple<DependencePropertyTs...> depProps,
323 std::tuple<InstancePropertyTs...> instProps, OpBuilder &builder) {
324 ImplicitLocOpBuilder b(builder.getUnknownLoc(), builder);
327 auto instOp = b.create<InstanceOp>(
328 builder.getStringAttr(ProblemT::name),
330 if (
auto instName = prob.getInstanceName())
331 instOp.setSymNameAttr(instName);
334 b.setInsertionPointToEnd(instOp.getBodyBlock());
335 auto libraryOp = b.create<OperatorLibraryOp>();
336 if (
auto libName = prob.getLibraryName())
337 libraryOp.setSymNameAttr(libName);
338 b.setInsertionPointToStart(libraryOp.getBodyBlock());
340 for (
auto opr : prob.getOperatorTypes())
341 b.create<OperatorTypeOp>(
342 opr, saveOperatorTypeProperties<ProblemT, OperatorTypePropertyTs...>(
347 DenseMap<Operation *, StringAttr> opNames;
348 for (
auto *op : prob.getOperations()) {
349 if (
auto opName = prob.getOperationName(op))
350 opNames[op] = opName;
352 for (
auto &dep : prob.getDependences(op)) {
353 Operation *src = dep.getSource();
354 if (!dep.isAuxiliary() || opNames.count(src))
356 if (
auto srcOpName = prob.getOperationName(src)) {
357 opNames[src] = srcOpName;
360 opNames[src] = b.getStringAttr(Twine(
"Op") + Twine(opNames.size()));
365 b.setInsertionPointToEnd(instOp.getBodyBlock());
366 auto graphOp = b.create<DependenceGraphOp>();
367 b.setInsertionPointToStart(graphOp.getBodyBlock());
371 for (
auto *op : prob.getOperations()) {
374 ArrayAttr dependences;
375 SmallVector<Attribute> depAttrs;
376 unsigned auxOperandIdx = op->getNumOperands();
377 for (
auto &dep : prob.getDependences(op)) {
381 if (dep.isDefUse() && depProps) {
382 auto depAttr = b.getAttr<DependenceAttr>(*dep.getDestinationIndex(),
383 FlatSymbolRefAttr(), depProps);
384 depAttrs.push_back(depAttr);
388 if (!dep.isAuxiliary())
391 auto sourceOpName = opNames.lookup(dep.getSource());
393 auto sourceRef = b.getAttr<FlatSymbolRefAttr>(sourceOpName);
395 b.getAttr<DependenceAttr>(auxOperandIdx, sourceRef, depProps);
396 depAttrs.push_back(depAttr);
399 if (!depAttrs.empty())
400 dependences = b.getArrayAttr(depAttrs);
403 ArrayAttr properties =
410 b.create<OperationOp>(op->getNumResults(), v.
get(op->getOperands()),
411 opNames.lookup(op), dependences, properties);
412 v.
set(op->getResults(), opOp->getResults());
428 template <
typename ProblemT>
436 template <
typename ProblemT>
449 template <
typename ProblemT>
463 static constexpr
auto operationProperties =
464 std::make_tuple(LinkedOperatorTypeAttr(), StartTimeAttr());
465 static constexpr
auto operatorTypeProperties = std::make_tuple(LatencyAttr());
466 static constexpr
auto dependenceProperties = std::make_tuple();
467 static constexpr
auto instanceProperties = std::make_tuple();
472 static constexpr
auto operationProperties =
474 static constexpr
auto operatorTypeProperties =
476 static constexpr
auto dependenceProperties =
478 std::make_tuple(DistanceAttr()));
479 static constexpr
auto instanceProperties =
481 std::make_tuple(InitiationIntervalAttr()));
486 static constexpr
auto operationProperties =
488 std::make_tuple(StartTimeInCycleAttr()));
489 static constexpr
auto operatorTypeProperties =
491 std::make_tuple(IncomingDelayAttr(), OutgoingDelayAttr()));
492 static constexpr
auto dependenceProperties =
494 static constexpr
auto instanceProperties =
499 struct Default<scheduling::SharedOperatorsProblem> {
500 static constexpr
auto operationProperties =
502 static constexpr
auto operatorTypeProperties =
504 std::make_tuple(LimitAttr()));
505 static constexpr
auto dependenceProperties =
507 static constexpr
auto instanceProperties =
513 static constexpr
auto operationProperties =
515 static constexpr
auto operatorTypeProperties =
517 static constexpr
auto dependenceProperties =
519 static constexpr
auto instanceProperties =
524 struct Default<scheduling::ChainingCyclicProblem> {
525 static constexpr
auto operationProperties =
527 static constexpr
auto operatorTypeProperties =
529 static constexpr
auto dependenceProperties =
531 static constexpr
auto instanceProperties =
assert(baseType &&"element must be base type")
Instantiate one of these and use it to build typed backedges.
The ValueMapper class facilitates the definition and connection of SSA def-use chains between two loc...
void set(mlir::Value from, mlir::Value to, bool replace=false)
mlir::Value get(mlir::Value from, TypeTransformer typeTransformer=ValueMapper::identity)
detail::Dependence Dependence
A thin wrapper to allow a uniform handling of def-use and auxiliary dependences.
mlir::StringAttr OperatorType
Operator types are distinguished by name (chosen by the client).
A wrapper class to uniformly handle def-use and auxiliary dependence edges.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
scheduling::Problem::Dependence Dependence
void loadInstanceProperties(ProblemT &, ArrayAttr)
void loadOperationProperties(ProblemT &, Operation *, ArrayAttr)
ArrayAttr saveDependenceProperties(ProblemT &prob, Dependence dep, ImplicitLocOpBuilder &b)
void loadOperatorTypeProperties(ProblemT &, OperatorType, ArrayAttr)
ArrayAttr saveOperatorTypeProperties(ProblemT &prob, OperatorType opr, ImplicitLocOpBuilder &b)
ProblemT loadProblem(InstanceOp instOp, std::tuple< OperationPropertyTs... > opProps, std::tuple< OperatorTypePropertyTs... > oprProps, std::tuple< DependencePropertyTs... > depProps, std::tuple< InstancePropertyTs... > instProps)
Construct an instance of ProblemT from instOp, and attempt to set properties from the given attribute...
void loadDependenceProperties(ProblemT &, Dependence, ArrayAttr)
ArrayAttr saveInstanceProperties(ProblemT &prob, ImplicitLocOpBuilder &b)
scheduling::Problem::OperatorType OperatorType
ArrayAttr saveOperationProperties(ProblemT &prob, Operation *op, ImplicitLocOpBuilder &b)
InstanceOp saveProblem(ProblemT &prob, std::tuple< OperationPropertyTs... > opProps, std::tuple< OperatorTypePropertyTs... > oprProps, std::tuple< DependencePropertyTs... > depProps, std::tuple< InstancePropertyTs... > instProps, OpBuilder &builder)
Construct an InstanceOp from a given ProblemT instance, and create/attach attributes of the given cla...
OperatorType loadOperatorType(ProblemT &prob, OperatorTypeOp oprOp, SmallDenseMap< StringAttr, unsigned > &oprIds)
Load the operator type represented by oprOp into prob under a unique name informed by oprIds,...
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Dummy struct to query a problem's default properties (i.e.