CIRCT  20.0.0git
Problems.h
Go to the documentation of this file.
1 //===- Problems.h - Modeling of scheduling problems -------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Static scheduling algorithms for use in HLS flows all solve similar problems.
10 // The classes in this file serve as an interface between clients and algorithm
11 // implementations, and model a basic scheduling problem and some commonly used
12 // extensions (e.g. modulo scheduling). This includes problem-specific
13 // verification methods.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef CIRCT_SCHEDULING_PROBLEMS_H
18 #define CIRCT_SCHEDULING_PROBLEMS_H
19 
21 #include "circt/Support/LLVM.h"
22 
23 #include "mlir/IR/BuiltinAttributes.h"
24 #include "llvm/ADT/DenseMap.h"
25 #include "llvm/ADT/SetVector.h"
26 
27 #include <optional>
28 
29 namespace circt {
30 namespace scheduling {
31 
32 /// This class models the most basic scheduling problem.
33 ///
34 /// A problem instance is comprised of:
35 ///
36 /// - *Operations*: The vertices in the data-flow graph to be scheduled.
37 /// - *Dependences*: The edges in the data-flow graph to be scheduled, modeling
38 /// a precedence relation between the involved operations.
39 /// - *Operator types*: An abstraction of the characteristics of the target
40 /// representation, e.g. modules in the HLS component library, available
41 /// functional units, etc. -- operations are executed on instances/units of
42 /// an operator type.
43 ///
44 /// Operations and operator types are stored explicitly. The registered
45 /// operations induce a subgraph of the SSA graph. We implicitly include the
46 /// dependences corresponding to its *def-use* relationships in the problem,
47 /// e.g. if operation *y*'s second operand uses the first result produced by
48 /// *x*, we'd have a dependence `x:0 --> y:1`. Clients can additionally register
49 /// explicit, *auxiliary* dependence between operations, e.g. to encode memory
50 /// dependencies or other ordering constraints. Auxiliary dependences do not
51 /// distinguish specific operands/results. The differences between the flavors
52 /// are transparent to concrete algorithms.
53 ///
54 /// All components of the problem (operations, dependences, operator types, as
55 /// well as the instance itself) can be annotated with *properties*. In this
56 /// basic problem, we model
57 ///
58 /// - `linkedOperatorType` maps operations to their operator types.
59 /// - `latency`, an operator type-property denoting the number of time steps
60 /// after which the operator's result is available.
61 /// - `startTime`, an operation-property for the time step in which an operation
62 /// is started. Together, the start times for all operations represent the
63 /// problem's solution, i.e. the schedule.
64 ///
65 /// Subclasses, i.e. corresponding to more complex scheduling problems, can
66 /// declare additional properties as needed.
67 //
68 /// The `check...` methods perform validity checks before scheduling, e.g. that
69 /// all operations have an associated operator type, etc.
70 ///
71 /// The `verify...` methods check the correctness of the solution determined by
72 /// a concrete scheduling algorithm, e.g. that there are start times available
73 /// for each registered operation, and the precedence constraints as modeled by
74 /// the dependences are satisfied.
75 class Problem {
76 public:
77  static constexpr auto name = "Problem";
78 
79  /// Construct an empty scheduling problem. \p containingOp is used for its
80  /// MLIRContext and to emit diagnostics.
81  explicit Problem(Operation *containingOp) : containingOp(containingOp) {}
82  virtual ~Problem() = default;
83 
85 
86 protected:
87  Problem() = default;
88 
89  //===--------------------------------------------------------------------===//
90  // Aliases for the problem components
91  //===--------------------------------------------------------------------===//
92 public:
93  /// A thin wrapper to allow a uniform handling of def-use and auxiliary
94  /// dependences.
96 
97  /// Operator types are distinguished by name (chosen by the client).
98  using OperatorType = mlir::StringAttr;
99 
100  //===--------------------------------------------------------------------===//
101  // Aliases for containers storing the problem components and properties
102  //===--------------------------------------------------------------------===//
103 public:
104  using OperationSet = llvm::SetVector<Operation *>;
105  using DependenceRange = llvm::iterator_range<detail::DependenceIterator>;
106  using OperatorTypeSet = llvm::SetVector<OperatorType>;
107 
108 protected:
110  llvm::DenseMap<Operation *, llvm::SmallSetVector<Operation *, 4>>;
111 
112  template <typename T>
113  using OperationProperty = llvm::DenseMap<Operation *, std::optional<T>>;
114  template <typename T>
115  using DependenceProperty = llvm::DenseMap<Dependence, std::optional<T>>;
116  template <typename T>
117  using OperatorTypeProperty = llvm::DenseMap<OperatorType, std::optional<T>>;
118  template <typename T>
119  using InstanceProperty = std::optional<T>;
120 
121  //===--------------------------------------------------------------------===//
122  // Containers for problem components and properties
123  //===--------------------------------------------------------------------===//
124 private:
125  // Operation containing the ops for this scheduling problem. Used for its
126  // MLIRContext and to emit diagnostics.
127  Operation *containingOp;
128 
129  // Problem components
133 
134  // Operation properties
137 
138  // Operator type properties
140 
141  //===--------------------------------------------------------------------===//
142  // Problem construction
143  //===--------------------------------------------------------------------===//
144 public:
145  /// Include \p op in this scheduling problem.
146  void insertOperation(Operation *op) { operations.insert(op); }
147 
148  /// Include \p dep in the scheduling problem. Return failure if \p dep does
149  /// not represent a valid def-use or auxiliary dependence between operations.
150  /// The endpoints become registered operations w.r.t. the problem.
151  LogicalResult insertDependence(Dependence dep);
152 
153  /// Include \p opr in this scheduling problem.
154  void insertOperatorType(OperatorType opr) { operatorTypes.insert(opr); }
155 
156  /// Retrieves the operator type identified by the client-specific \p name. The
157  /// operator type is automatically registered in the scheduling problem.
159 
160  //===--------------------------------------------------------------------===//
161  // Access to problem components
162  //===--------------------------------------------------------------------===//
163 public:
164  /// Return the operation containing this problem, e.g. to emit diagnostics.
165  Operation *getContainingOp() { return containingOp; }
166  /// Set the operation containing this problem, e.g. to emit diagnostics.
167  void setContainingOp(Operation *op) { containingOp = op; }
168 
169  /// Return true if \p op is part of this problem.
170  bool hasOperation(Operation *op) { return operations.contains(op); }
171  /// Return the set of operations.
172  const OperationSet &getOperations() { return operations; }
173 
174  /// Return a range object to transparently iterate over \p op's *incoming*
175  /// 1) implicit def-use dependences (backed by the SSA graph), and then
176  /// 2) explictly added auxiliary dependences.
177  ///
178  /// In other words, this yields dependences whose destination operation is
179  /// \p op, and whose source operations are \p op's predecessors in the problem
180  /// graph.
181  ///
182  /// To iterate over all of the scheduling problem's dependences, simply
183  /// process the ranges for all registered operations.
184  DependenceRange getDependences(Operation *op);
185 
186  /// Return true if \p opr is part of this problem.
187  bool hasOperatorType(OperatorType opr) { return operatorTypes.contains(opr); }
188  /// Return the set of operator types.
190 
191  //===--------------------------------------------------------------------===//
192  // Access to properties
193  //===--------------------------------------------------------------------===//
194 public:
195  /// The linked operator type provides the runtime characteristics for \p op.
196  std::optional<OperatorType> getLinkedOperatorType(Operation *op) {
197  return linkedOperatorType.lookup(op);
198  }
199  void setLinkedOperatorType(Operation *op, OperatorType opr) {
200  linkedOperatorType[op] = opr;
201  }
202 
203  /// The latency is the number of cycles \p opr needs to compute its result.
204  std::optional<unsigned> getLatency(OperatorType opr) {
205  return latency.lookup(opr);
206  }
207  void setLatency(OperatorType opr, unsigned val) { latency[opr] = val; }
208 
209  /// Return the start time for \p op, as computed by the scheduler.
210  /// These start times comprise the basic problem's solution, i.e. the
211  /// *schedule*.
212  std::optional<unsigned> getStartTime(Operation *op) {
213  return startTime.lookup(op);
214  }
215  void setStartTime(Operation *op, unsigned val) { startTime[op] = val; }
216 
217  //===--------------------------------------------------------------------===//
218  // Access to derived properties
219  //===--------------------------------------------------------------------===//
220 public:
221  /// Returns the end time for \p op, as computed by the scheduler.
222  /// This end time is derived from the start time and the operator type's
223  /// latency.
224  std::optional<unsigned> getEndTime(Operation *op);
225 
226  //===--------------------------------------------------------------------===//
227  // Optional names (for exporting and debugging instances)
228  //===--------------------------------------------------------------------===//
229 private:
232 
233 public:
234  StringAttr getInstanceName() { return instanceName; }
235  void setInstanceName(StringAttr name) { instanceName = name; }
236 
237  StringAttr getLibraryName() { return libraryName; }
238  void setLibraryName(StringAttr name) { libraryName = name; }
239 
240  StringAttr getOperationName(Operation *op) {
241  return operationNames.lookup(op);
242  }
243  void setOperationName(Operation *op, StringAttr name) {
244  operationNames[op] = name;
245  }
246 
247  //===--------------------------------------------------------------------===//
248  // Properties as string key-value pairs (e.g. for DOT graphs)
249  //===--------------------------------------------------------------------===//
250 public:
252  llvm::SmallVector<std::pair<std::string, std::string>, 2>;
253 
254  virtual PropertyStringVector getProperties(Operation *op);
258 
259  //===--------------------------------------------------------------------===//
260  // Property-specific validators
261  //===--------------------------------------------------------------------===//
262 protected:
263  /// \p op is linked to a registered operator type.
264  virtual LogicalResult checkLinkedOperatorType(Operation *op);
265  /// \p opr has a latency.
266  virtual LogicalResult checkLatency(OperatorType opr);
267  /// \p op has a start time.
268  virtual LogicalResult verifyStartTime(Operation *op);
269  /// \p dep's source operation is available before \p dep's destination
270  /// operation starts.
271  virtual LogicalResult verifyPrecedence(Dependence dep);
272 
273  //===--------------------------------------------------------------------===//
274  // Client API for problem validation
275  //===--------------------------------------------------------------------===//
276 public:
277  /// Return success if the constructed scheduling problem is valid.
278  virtual LogicalResult check();
279  /// Return success if the computed solution is valid.
280  virtual LogicalResult verify();
281 };
282 
283 /// This class models a cyclic scheduling problem. Its solution can be used to
284 /// construct a pipelined datapath with a fixed, integer initiation interval,
285 /// in which the execution of multiple iterations/samples/etc. may overlap.
286 class CyclicProblem : public virtual Problem {
287 public:
288  static constexpr auto name = "CyclicProblem";
289  using Problem::Problem;
290 
291 protected:
292  CyclicProblem() = default;
293 
294 private:
297 
298 public:
299  /// The distance determines whether a dependence has to be satisfied in the
300  /// same iteration (distance=0 or not set), or distance-many iterations later.
301  std::optional<unsigned> getDistance(Dependence dep) {
302  return distance.lookup(dep);
303  }
304  void setDistance(Dependence dep, unsigned val) { distance[dep] = val; }
305 
306  /// The initiation interval (II) is the number of time steps between
307  /// subsequent iterations, i.e. a new iteration is started every II time
308  /// steps. The best possible value is 1, meaning that a corresponding pipeline
309  /// accepts new data every cycle. This property is part of the cyclic
310  /// problem's solution.
311  std::optional<unsigned> getInitiationInterval() { return initiationInterval; }
312  void setInitiationInterval(unsigned val) { initiationInterval = val; }
313 
314  virtual PropertyStringVector getProperties(Dependence dep) override;
315  virtual PropertyStringVector getProperties() override;
316 
317 protected:
318  /// \p dep's source operation is available before \p dep's destination
319  /// operation starts (\p dep's distance iterations later).
320  virtual LogicalResult verifyPrecedence(Dependence dep) override;
321  /// This problem has a non-zero II.
322  virtual LogicalResult verifyInitiationInterval();
323 
324 public:
325  virtual LogicalResult verify() override;
326 };
327 
328 /// This class models the accumulation of physical propagation delays on
329 /// combinational paths along SSA dependences.
330 ///
331 /// Each operator type is annotated with estimated values for incoming and
332 /// outgoing delays. Combinational operators (zero-latency, no internal
333 /// registers) have only a single delay; this important special case is modeled
334 /// by setting the incoming and outgoing delays to the same value.
335 ///
336 /// A solution to this problem comprises per-operation start times in a
337 /// continuous unit, e.g. in nanoseconds, inside the discrete time steps/cycles
338 /// determined by the underlying scheduling problem.
339 class ChainingProblem : public virtual Problem {
340 public:
341  static constexpr auto name = "ChainingProblem";
342  using Problem::Problem;
343 
344 protected:
345  ChainingProblem() = default;
346 
347 private:
350 
351 public:
352  /// The incoming delay denotes the propagation time from the operand inputs to
353  /// either the result outputs (combinational operators) or the first internal
354  /// register stage.
355  std::optional<float> getIncomingDelay(OperatorType opr) {
356  return incomingDelay.lookup(opr);
357  }
358  void setIncomingDelay(OperatorType opr, float delay) {
359  incomingDelay[opr] = delay;
360  }
361 
362  /// The outgoing delay denotes the propagation time from either the operand
363  /// inputs (combinational operators) or the last internal register stage to
364  /// the result outputs.
365  std::optional<float> getOutgoingDelay(OperatorType opr) {
366  return outgoingDelay.lookup(opr);
367  }
368  void setOutgoingDelay(OperatorType opr, float delay) {
369  outgoingDelay[opr] = delay;
370  }
371 
372  /// Computed by the scheduler, this start time is relative to the beginning of
373  /// the cycle that \p op starts in.
374  std::optional<float> getStartTimeInCycle(Operation *op) {
375  return startTimeInCycle.lookup(op);
376  }
377  void setStartTimeInCycle(Operation *op, float time) {
378  startTimeInCycle[op] = time;
379  }
381 
382  virtual PropertyStringVector getProperties(Operation *op) override;
383  virtual PropertyStringVector getProperties(OperatorType opr) override;
384 
385 protected:
386  /// Incoming/outgoing delays are set for \p opr and non-negative. The delays
387  /// are equal if \p opr is a zero-latency operator type.
388  virtual LogicalResult checkDelays(OperatorType opr);
389 
390  /// \p op has a non-negative start time in its cycle.
391  virtual LogicalResult verifyStartTimeInCycle(Operation *op);
392  /// If \p dep is an SSA edge and its source operation finishes in the same
393  /// time step as the destination operation, the source's result is available
394  /// before the destination starts in that cycle.
395  virtual LogicalResult verifyPrecedenceInCycle(Dependence dep);
396 
397 public:
398  virtual LogicalResult check() override;
399  virtual LogicalResult verify() override;
400 };
401 
402 /// This class models a resource-constrained scheduling problem. An optional,
403 /// non-zero *limit* marks operator types to be *shared* by the operations using
404 /// them. In an HLS setting, this corresponds to multiplexing multiple
405 /// operations onto a pre-allocated number of operator instances. These
406 /// instances are assumed to be *fully pipelined*, meaning each instance can
407 /// accept new operands (coming from a distinct operation) in each time step.
408 ///
409 /// A solution to this problem is feasible iff the number of operations that use
410 /// a certain limited operator type, and start in the same time step, does not
411 /// exceed the operator type's limit. These constraints do not apply to operator
412 /// types without a limit (not set, or 0).
413 class SharedOperatorsProblem : public virtual Problem {
414 public:
415  static constexpr auto name = "SharedOperatorsProblem";
416  using Problem::Problem;
417 
418 protected:
420 
421 private:
423 
424 public:
425  /// The limit is the maximum number of operations using \p opr that are
426  /// allowed to start in the same time step.
427  std::optional<unsigned> getLimit(OperatorType opr) {
428  return limit.lookup(opr);
429  }
430  void setLimit(OperatorType opr, unsigned val) { limit[opr] = val; }
431 
432  virtual PropertyStringVector getProperties(OperatorType opr) override;
433 
434 protected:
435  /// If \p opr is limited, it has a non-zero latency.
436  virtual LogicalResult checkLatency(OperatorType opr) override;
437  /// \p opr is not oversubscribed in any time step.
438  virtual LogicalResult verifyUtilization(OperatorType opr);
439 
440 public:
441  virtual LogicalResult verify() override;
442 };
443 
444 /// This class models the modulo scheduling problem as the composition of the
445 /// cyclic problem and the resource-constrained problem with fully-pipelined
446 /// shared operators.
447 ///
448 /// A solution to this problem comprises an integer II and integer start times
449 /// for all registered operations, and is feasible iff:
450 /// (1) The precedence constraints implied by the `CyclicProblem`'s dependence
451 /// edges are satisfied, and
452 /// (2) The number of operations that use a certain limited operator type,
453 /// and start in the same congruence class (= start time *mod* II), does
454 /// not exceed the operator type's limit.
455 class ModuloProblem : public virtual CyclicProblem,
456  public virtual SharedOperatorsProblem {
457 public:
458  static constexpr auto name = "ModuloProblem";
460 
461 protected:
462  ModuloProblem() = default;
463 
464  /// \p opr is not oversubscribed in any congruence class modulo II.
465  virtual LogicalResult verifyUtilization(OperatorType opr) override;
466 
467 public:
468  virtual LogicalResult verify() override;
469 };
470 
471 /// This class models the accumulation of physical propagation delays on
472 /// combinational paths along SSA dependences on a cyclic scheduling problem.
473 ///
474 /// Each operator type is annotated with estimated values for incoming and
475 /// outgoing delays. Combinational operators (zero-latency, no internal
476 /// registers) have only a single delay; this important special case is modeled
477 /// by setting the incoming and outgoing delays to the same values.
478 ///
479 /// A solution to this problem comprises per-operation start times in a
480 /// continuous unit, e.g. in nanoseconds, inside the discrete time steps/cycles
481 /// determined by the underlying scheduling problem. Its solution can be used to
482 /// construct a pipelined datapath with a fixed, integer initiation interval,
483 /// in which the execution of multiple iterations/samples/etc. may overlap.
484 class ChainingCyclicProblem : public virtual ChainingProblem,
485  public virtual CyclicProblem {
486 public:
487  static constexpr auto name = "ChainingCyclicProblem";
489 
490 protected:
492 
493 public:
494  LogicalResult checkDefUse(Dependence dep);
495  LogicalResult check() override;
496  LogicalResult verify() override;
497 };
498 
499 } // namespace scheduling
500 } // namespace circt
501 
502 #endif // CIRCT_SCHEDULING_PROBLEMS_H
Problem::Dependence Dependence
This class models the accumulation of physical propagation delays on combinational paths along SSA de...
Definition: Problems.h:485
LogicalResult verify() override
Return success if the computed solution is valid.
Definition: Problems.cpp:434
LogicalResult checkDefUse(Dependence dep)
Definition: Problems.cpp:414
LogicalResult check() override
Return success if the constructed scheduling problem is valid.
Definition: Problems.cpp:422
This class models the accumulation of physical propagation delays on combinational paths along SSA de...
Definition: Problems.h:339
void setStartTimeInCycle(Operation *op, float time)
Definition: Problems.h:377
void setIncomingDelay(OperatorType opr, float delay)
Definition: Problems.h:358
OperationProperty< float > startTimeInCycle
Definition: Problems.h:349
virtual LogicalResult check() override
Return success if the constructed scheduling problem is valid.
Definition: Problems.cpp:290
virtual LogicalResult verifyPrecedenceInCycle(Dependence dep)
If dep is an SSA edge and its source operation finishes in the same time step as the destination oper...
Definition: Problems.cpp:255
std::optional< float > getStartTimeInCycle(Operation *op)
Computed by the scheduler, this start time is relative to the beginning of the cycle that op starts i...
Definition: Problems.h:374
std::optional< float > getIncomingDelay(OperatorType opr)
The incoming delay denotes the propagation time from the operand inputs to either the result outputs ...
Definition: Problems.h:355
std::optional< float > getOutgoingDelay(OperatorType opr)
The outgoing delay denotes the propagation time from either the operand inputs (combinational operato...
Definition: Problems.h:365
OperatorTypeProperty< float > incomingDelay
Definition: Problems.h:348
static constexpr auto name
Definition: Problems.h:341
void setOutgoingDelay(OperatorType opr, float delay)
Definition: Problems.h:368
virtual LogicalResult verify() override
Return success if the computed solution is valid.
Definition: Problems.cpp:301
OperatorTypeProperty< float > outgoingDelay
Definition: Problems.h:348
virtual LogicalResult verifyStartTimeInCycle(Operation *op)
op has a non-negative start time in its cycle.
Definition: Problems.cpp:248
virtual LogicalResult checkDelays(OperatorType opr)
Incoming/outgoing delays are set for opr and non-negative.
Definition: Problems.cpp:224
This class models a cyclic scheduling problem.
Definition: Problems.h:286
std::optional< unsigned > getInitiationInterval()
The initiation interval (II) is the number of time steps between subsequent iterations,...
Definition: Problems.h:311
void setDistance(Dependence dep, unsigned val)
Definition: Problems.h:304
virtual LogicalResult verifyInitiationInterval()
This problem has a non-zero II.
Definition: Problems.cpp:192
virtual PropertyStringVector getProperties() override
Definition: Problems.cpp:164
virtual LogicalResult verifyPrecedence(Dependence dep) override
dep's source operation is available before dep's destination operation starts (dep's distance iterati...
Definition: Problems.cpp:171
void setInitiationInterval(unsigned val)
Definition: Problems.h:312
InstanceProperty< unsigned > initiationInterval
Definition: Problems.h:296
static constexpr auto name
Definition: Problems.h:288
virtual LogicalResult verify() override
Return success if the computed solution is valid.
Definition: Problems.cpp:198
DependenceProperty< unsigned > distance
Definition: Problems.h:295
std::optional< unsigned > getDistance(Dependence dep)
The distance determines whether a dependence has to be satisfied in the same iteration (distance=0 or...
Definition: Problems.h:301
This class models the modulo scheduling problem as the composition of the cyclic problem and the reso...
Definition: Problems.h:456
virtual LogicalResult verify() override
Return success if the computed solution is valid.
Definition: Problems.cpp:397
static constexpr auto name
Definition: Problems.h:458
virtual LogicalResult verifyUtilization(OperatorType opr) override
opr is not oversubscribed in any congruence class modulo II.
Definition: Problems.cpp:376
This class models the most basic scheduling problem.
Definition: Problems.h:75
void setLatency(OperatorType opr, unsigned val)
Definition: Problems.h:207
virtual LogicalResult checkLatency(OperatorType opr)
opr has a latency.
Definition: Problems.cpp:88
llvm::DenseMap< Operation *, llvm::SmallSetVector< Operation *, 4 > > AuxDependenceMap
Definition: Problems.h:110
llvm::SetVector< Operation * > OperationSet
Definition: Problems.h:104
llvm::SetVector< OperatorType > OperatorTypeSet
Definition: Problems.h:106
virtual LogicalResult verify()
Return success if the computed solution is valid.
Definition: Problems.cpp:132
StringAttr getInstanceName()
Definition: Problems.h:234
virtual LogicalResult check()
Return success if the constructed scheduling problem is valid.
Definition: Problems.cpp:96
std::optional< OperatorType > getLinkedOperatorType(Operation *op)
The linked operator type provides the runtime characteristics for op.
Definition: Problems.h:196
virtual PropertyStringVector getProperties()
Definition: Problems.cpp:78
void insertOperation(Operation *op)
Include op in this scheduling problem.
Definition: Problems.h:146
llvm::iterator_range< detail::DependenceIterator > DependenceRange
Definition: Problems.h:105
OperationSet operations
Definition: Problems.h:130
bool hasOperation(Operation *op)
Return true if op is part of this problem.
Definition: Problems.h:170
StringAttr getLibraryName()
Definition: Problems.h:237
LogicalResult insertDependence(Dependence dep)
Include dep in the scheduling problem.
Definition: Problems.cpp:26
std::optional< unsigned > getEndTime(Operation *op)
Returns the end time for op, as computed by the scheduler.
Definition: Problems.cpp:145
const OperatorTypeSet & getOperatorTypes()
Return the set of operator types.
Definition: Problems.h:189
OperationProperty< OperatorType > linkedOperatorType
Definition: Problems.h:135
OperationProperty< unsigned > startTime
Definition: Problems.h:136
std::optional< T > InstanceProperty
Definition: Problems.h:119
std::optional< unsigned > getStartTime(Operation *op)
Return the start time for op, as computed by the scheduler.
Definition: Problems.h:212
void setStartTime(Operation *op, unsigned val)
Definition: Problems.h:215
OperatorTypeProperty< unsigned > latency
Definition: Problems.h:139
SmallDenseMap< Operation *, StringAttr > operationNames
Definition: Problems.h:231
llvm::DenseMap< Operation *, std::optional< T > > OperationProperty
Definition: Problems.h:113
static constexpr auto name
Definition: Problems.h:77
virtual ~Problem()=default
void setContainingOp(Operation *op)
Set the operation containing this problem, e.g. to emit diagnostics.
Definition: Problems.h:167
OperatorType getOrInsertOperatorType(StringRef name)
Retrieves the operator type identified by the client-specific name.
Definition: Problems.cpp:47
AuxDependenceMap auxDependences
Definition: Problems.h:131
llvm::DenseMap< OperatorType, std::optional< T > > OperatorTypeProperty
Definition: Problems.h:117
void setInstanceName(StringAttr name)
Definition: Problems.h:235
OperatorTypeSet operatorTypes
Definition: Problems.h:132
llvm::SmallVector< std::pair< std::string, std::string >, 2 > PropertyStringVector
Definition: Problems.h:252
virtual LogicalResult verifyStartTime(Operation *op)
op has a start time.
Definition: Problems.cpp:108
virtual LogicalResult checkLinkedOperatorType(Operation *op)
op is linked to a registered operator type.
Definition: Problems.cpp:80
llvm::DenseMap< Dependence, std::optional< T > > DependenceProperty
Definition: Problems.h:115
DependenceRange getDependences(Operation *op)
Return a range object to transparently iterate over op's incoming 1) implicit def-use dependences (ba...
Definition: Problems.cpp:53
Operation * containingOp
Definition: Problems.h:127
bool hasOperatorType(OperatorType opr)
Return true if opr is part of this problem.
Definition: Problems.h:187
const OperationSet & getOperations()
Return the set of operations.
Definition: Problems.h:172
virtual LogicalResult verifyPrecedence(Dependence dep)
dep's source operation is available before dep's destination operation starts.
Definition: Problems.cpp:114
void setLibraryName(StringAttr name)
Definition: Problems.h:238
void setLinkedOperatorType(Operation *op, OperatorType opr)
Definition: Problems.h:199
mlir::StringAttr OperatorType
Operator types are distinguished by name (chosen by the client).
Definition: Problems.h:98
void insertOperatorType(OperatorType opr)
Include opr in this scheduling problem.
Definition: Problems.h:154
void setOperationName(Operation *op, StringAttr name)
Definition: Problems.h:243
StringAttr getOperationName(Operation *op)
Definition: Problems.h:240
Problem(Operation *containingOp)
Construct an empty scheduling problem.
Definition: Problems.h:81
std::optional< unsigned > getLatency(OperatorType opr)
The latency is the number of cycles opr needs to compute its result.
Definition: Problems.h:204
Operation * getContainingOp()
Return the operation containing this problem, e.g. to emit diagnostics.
Definition: Problems.h:165
This class models a resource-constrained scheduling problem.
Definition: Problems.h:413
OperatorTypeProperty< unsigned > limit
Definition: Problems.h:422
virtual LogicalResult verify() override
Return success if the computed solution is valid.
Definition: Problems.cpp:361
virtual LogicalResult checkLatency(OperatorType opr) override
If opr is limited, it has a non-zero latency.
Definition: Problems.cpp:329
std::optional< unsigned > getLimit(OperatorType opr)
The limit is the maximum number of operations using opr that are allowed to start in the same time st...
Definition: Problems.h:427
virtual LogicalResult verifyUtilization(OperatorType opr)
opr is not oversubscribed in any time step.
Definition: Problems.cpp:341
void setLimit(OperatorType opr, unsigned val)
Definition: Problems.h:430
An iterator to transparently surface an operation's def-use dependences from the SSA subgraph (induce...
A wrapper class to uniformly handle def-use and auxiliary dependence edges.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21