Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Scheduling] add a header to simplex scheduler #7466

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
16 changes: 16 additions & 0 deletions docs/Scheduling.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,22 @@ order not to pollute the infrastructure. For example, the `ChainingProblem` may
be of limited use standalone, but can serve as a parent class for a future
chaining-enabled modulo scheduling problem.

## Extensible scheduler model

See
[Schedulers.h](https://github.com/llvm/circt/blob/main/include/circt/Scheduling/Schedulers.h)

The `Scheduler` class serves as the base class of all schedulers. It is an interface that use template parameters to declare the list of `Problem` classes that can be scheduled by a specific scheduler. A scheduler that can handle a problem `ProblemX` must implement a method `LogicalResult schedule(ProblemX &problem, Operation *lastOp)`, which is responsible for scheduling the `problem` instance of the `ProblemX` problem.

### Template parameters

The `Scheduler` class is declared as follow:
```c++
template <typename... Ps>
class Scheduler;
```
In this declaration, `Ps` is a **non-empty** variadic template parameter pack. `Ps` represents the list of `Problem` types that the scheduler can handle. Therefore, every element of `Ps` must be a subclass of `Problem`.

## Available schedulers

- ASAP list scheduler
Expand Down
18 changes: 18 additions & 0 deletions include/circt/Scheduling/ASAPScheduler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===- ASAPchedulers.h - Linear programming-based schedulers --------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "circt/Scheduling/Schedulers.h"

namespace circt::scheduling {

class ASAPScheduler : public Scheduler<Problem> {
public:
LogicalResult schedule(Problem &problem, Operation *lastOp) override;
};

}; // namespace circt::scheduling
17 changes: 7 additions & 10 deletions include/circt/Scheduling/Algorithms.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,22 @@ LogicalResult scheduleSimplex(SharedOperatorsProblem &prob, Operation *lastOp);
LogicalResult scheduleSimplex(ModuloProblem &prob, Operation *lastOp);

/// Solve the acyclic, chaining-enabled problem using linear programming and a
/// handwritten implementation of the simplex algorithm. This approach strictly
/// adheres to the given maximum \p cycleTime. The objective is to minimize the
/// start time of the given \p lastOp. Fails if the dependence graph contains
/// cycles, or individual operator types have delays larger than \p cycleTime,
/// or \p prob does not include \p lastOp.
LogicalResult scheduleSimplex(ChainingProblem &prob, Operation *lastOp,
float cycleTime);
/// handwritten implementation of the simplex algorithm. The objective is to
/// minimize the start time of the given \p lastOp. Fails if the dependence
/// graph contains cycles, or individual operator types have delays larger than
/// \p cycleTime, or \p prob does not include \p lastOp.
LogicalResult scheduleSimplex(ChainingProblem &prob, Operation *lastOp);

/// Solve the resource-free cyclic, chaining-enabled problem using a linear
/// programming-based and a handwritten implementation of the simplex algorithm.
/// This approach is an hybrid approach of the ChainingProblem simplex scheduler
/// and the CyclicProblem simplex scheduler. The objectives include determining
/// the smallest feasible initiation interval, and to minimize the start time of
/// a given \p lastOp. Fails if the dependence graph contains cycles that does
/// a given \p lastOp. Fails if the dependence graph contains cycles that does
/// not include at least one edge with a non-zero distance, individual operator
/// types have delays larger than \p cycleTime, or \p prob does not include
/// \p lastOp.
LogicalResult scheduleSimplex(ChainingCyclicProblem &prob, Operation *lastOp,
float cycleTime);
LogicalResult scheduleSimplex(ChainingCyclicProblem &prob, Operation *lastOp);

/// Solve the basic problem using linear programming and an external LP solver.
/// The objective is to minimize the start time of the given \p lastOp. Fails if
Expand Down
20 changes: 20 additions & 0 deletions include/circt/Scheduling/CPSATSchedulers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===- CPSATSchedulers.h - Schedulers using external CPSAT solvers --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "circt/Scheduling/Problems.h"
#include "circt/Scheduling/Schedulers.h"

namespace circt::scheduling {

class CPSATScheduler : public Scheduler<SharedOperatorsProblem> {
public:
LogicalResult schedule(SharedOperatorsProblem &problem,
Operation *lastOp) override;
};

}; // namespace circt::scheduling
20 changes: 20 additions & 0 deletions include/circt/Scheduling/LPSchedulers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===- LPSchedulers.ch - Schedulers using external LP solvers -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "circt/Scheduling/Problems.h"
#include "circt/Scheduling/Schedulers.h"

namespace circt::scheduling {

class LPScheduler : public Scheduler<Problem, CyclicProblem> {
public:
LogicalResult schedule(Problem &problem, Operation *lastOp) override;
LogicalResult schedule(CyclicProblem &problem, Operation *lastOp) override;
};

}; // namespace circt::scheduling
13 changes: 13 additions & 0 deletions include/circt/Scheduling/Problems.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,12 @@ class CyclicProblem : public virtual Problem {
/// This class models the accumulation of physical propagation delays on
/// combinational paths along SSA dependences.
///
/// This class contains a field `targetCycleTime` which corresponds to the
/// desired clock period after scheduling. The schedulers implemented use the
/// target cycle time as a strict limit. Alternative approaches may be
/// considered; some commercial HLS tools may may exceed this limit under
/// certain circumstances.
///
/// Each operator type is annotated with estimated values for incoming and
/// outgoing delays. Combinational operators (zero-latency, no internal
/// registers) have only a single delay; this important special case is modeled
Expand All @@ -348,6 +354,8 @@ class ChainingProblem : public virtual Problem {
OperatorTypeProperty<float> incomingDelay, outgoingDelay;
OperationProperty<float> startTimeInCycle;

float targetCycleTime;

public:
/// The incoming delay denotes the propagation time from the operand inputs to
/// either the result outputs (combinational operators) or the first internal
Expand Down Expand Up @@ -379,6 +387,11 @@ class ChainingProblem : public virtual Problem {
}
void clearStartTimeInCycle() { startTimeInCycle.clear(); }

/// The target cycle time corresponds to the desired clock period after
/// scheduling.
float getTargetCycleTime() { return targetCycleTime; }
void setTargetCycleTime(float cycleTime) { targetCycleTime = cycleTime; }

virtual PropertyStringVector getProperties(Operation *op) override;
virtual PropertyStringVector getProperties(OperatorType opr) override;

Expand Down
65 changes: 65 additions & 0 deletions include/circt/Scheduling/Schedulers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//===- Schedulers.h - Scheduler trait -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef CIRCT_SCHEDULERS_H
#define CIRCT_SCHEDULERS_H

#include "circt/Scheduling/Problems.h"
#include "circt/Scheduling/Utilities.h"
#include "mlir/IR/Operation.h"
#include "llvm/Support/LogicalResult.h"
#include <type_traits>

namespace circt::scheduling {

/// This class provides an interface for schedulers. Schedulers are used to
/// schedule subclasses of `Problem`. A `Scheduler` can handle any number of
/// `Problem` types and declare these problem classes as template parameters.
/// For example: `class MyScheduler : public Scheduler<ChainingProblem,
/// CyclicProblem>` can schedule instances of both `ChainingProblem` and
/// `CyclicProblem`. A `Scheduler` must be able to handle at least one type of
/// `Problem`.
///
/// For every `Problem` class `P` managed by a `Scheduler`, the `Scheduler`
/// must define a method `LogicalResult schedule(P &problem, Operation *lastOp)`
/// to schedule an instance of `P`. The `lastOp` parameter represents the last
/// operation of the `Problem` instance and is used by predefined schedulers
/// in their schedule objectives.
///
/// Implementations of `Scheduler` are free to add additional parameters to the
/// `schedule` method if needed, for example, to support custom objective
/// functions. However, a common method signature is used for interoperability.
/// Functions that schedule a specific problem can accept the `Scheduler` as an
/// argument and be specialized accordingly. For example:
/// ```cpp
/// LogicalResult MyFunction(Scheduler<MyProblem> &scheduler) { ... }
/// ```
/// In this function, the `scheduler` argument can be used to schedule any
/// instance of `MyProblem` and can be called with any `Scheduler` that handles
/// `MyProblem`.
template <typename... Ps>
class Scheduler : public Scheduler<Ps>... {
static_assert(
sizeof...(Ps) > 0,
"A scheduler must be able to schedule at least one class of Problem.");
};

template <typename P>
class Scheduler<P> {
static_assert((std::is_base_of_v<Problem, P>),
"Elements scheduled by a Scheduler must be deried from the "
"Problem class.");

public:
virtual ~Scheduler() = default;
virtual LogicalResult schedule(P &problem, Operation *lastOp) = 0;
};

}; // namespace circt::scheduling

#endif
Loading
Loading