19 #include "mlir/Pass/Pass.h"
23 #include "llvm/ADT/StringExtras.h"
27 #define GEN_PASS_DEF_SCHEDULE
28 #include "circt/Dialect/SSP/SSPPasses.h.inc"
32 using namespace circt;
33 using namespace scheduling;
42 static OperationOp
getLastOp(InstanceOp instOp, StringRef options) {
43 StringRef lastOpName =
"";
44 for (StringRef option : llvm::split(options,
',')) {
45 if (option.consume_front(
"last-op-name=")) {
51 auto graphOp = instOp.getDependenceGraph();
52 if (lastOpName.empty() && !graphOp.getBodyBlock()->empty())
53 return cast<OperationOp>(graphOp.getBodyBlock()->back());
54 return graphOp.lookupSymbol<OperationOp>(lastOpName);
59 for (StringRef option : llvm::split(options,
',')) {
60 if (option.consume_front(
"cycle-time="))
61 return std::stof(option.str());
71 auto problemName = instOp.getProblemName();
72 if (problemName !=
"Problem") {
73 llvm::errs() <<
"ssp-schedule: Unsupported problem '" << problemName
74 <<
"' for ASAP scheduler\n";
78 auto prob = loadProblem<Problem>(instOp);
80 failed(prob.verify()))
89 template <
typename ProblemT>
93 auto prob = loadProblem<ProblemT>(instOp);
94 if (failed(prob.check()) ||
96 failed(prob.verify()))
104 OpBuilder &builder) {
105 auto prob = loadProblem<scheduling::ChainingProblem>(instOp);
106 if (failed(prob.check()) ||
108 failed(prob.verify()))
116 OpBuilder &builder) {
117 auto prob = loadProblem<scheduling::ChainingCyclicProblem>(instOp);
118 if (failed(prob.check()) ||
120 failed(prob.verify()))
126 OpBuilder &builder) {
127 auto lastOp =
getLastOp(instOp, options);
129 auto instName = instOp.getSymName().value_or(
"unnamed");
131 <<
"ssp-schedule: Ambiguous objective for simplex scheduler: Instance '"
132 << instName <<
"' has no designated last operation\n";
136 auto problemName = instOp.getProblemName();
137 if (problemName ==
"Problem")
138 return scheduleProblemTWithSimplex<Problem>(instOp, lastOp, builder);
139 if (problemName ==
"CyclicProblem")
140 return scheduleProblemTWithSimplex<CyclicProblem>(instOp, lastOp, builder);
141 if (problemName ==
"SharedOperatorsProblem")
142 return scheduleProblemTWithSimplex<SharedOperatorsProblem>(instOp, lastOp,
144 if (problemName ==
"ModuloProblem")
145 return scheduleProblemTWithSimplex<ModuloProblem>(instOp, lastOp, builder);
146 if (problemName ==
"ChainingProblem") {
149 cycleTime.value(), builder);
150 llvm::errs() <<
"ssp-schedule: Missing option 'cycle-time' for "
151 "ChainingProblem simplex scheduler\n";
154 if (problemName ==
"ChainingCyclicProblem") {
157 instOp, lastOp, cycleTime.value(), builder);
158 llvm::errs() <<
"ssp-schedule: Missing option 'cycle-time' for "
159 "ChainingCyclicProblem simplex scheduler\n";
163 llvm::errs() <<
"ssp-schedule: Unsupported problem '" << problemName
164 <<
"' for simplex scheduler\n";
168 #ifdef SCHEDULING_OR_TOOLS
174 template <
typename ProblemT>
175 static InstanceOp scheduleProblemTWithLP(InstanceOp instOp, Operation *lastOp,
176 OpBuilder &builder) {
177 auto prob = loadProblem<ProblemT>(instOp);
179 failed(prob.verify()))
184 static InstanceOp scheduleWithLP(InstanceOp instOp, StringRef options,
185 OpBuilder &builder) {
186 auto lastOp =
getLastOp(instOp, options);
188 auto instName = instOp.getSymName().value_or(
"unnamed");
190 <<
"ssp-schedule: Ambiguous objective for LP scheduler: Instance '"
191 << instName <<
"' has no designated last operation\n";
195 auto problemName = instOp.getProblemName();
196 if (problemName ==
"Problem")
197 return scheduleProblemTWithLP<Problem>(instOp, lastOp, builder);
198 if (problemName ==
"CyclicProblem")
199 return scheduleProblemTWithLP<CyclicProblem>(instOp, lastOp, builder);
201 llvm::errs() <<
"ssp-schedule: Unsupported problem '" << problemName
202 <<
"' for LP scheduler\n";
210 static InstanceOp scheduleWithCPSAT(InstanceOp instOp, StringRef options,
211 OpBuilder &builder) {
212 auto lastOp =
getLastOp(instOp, options);
214 auto instName = instOp.getSymName().value_or(
"unnamed");
216 <<
"ssp-schedule: Ambiguous objective for CPSAT scheduler: Instance '"
217 << instName <<
"' has no designated last operation\n";
221 auto problemName = instOp.getProblemName();
222 if (problemName !=
"SharedOperatorsProblem") {
223 llvm::errs() <<
"ssp-schedule: Unsupported problem '" << problemName
224 <<
"' for CPSAT scheduler\n";
228 auto prob = loadProblem<SharedOperatorsProblem>(instOp);
230 failed(prob.verify()))
242 StringRef options, OpBuilder &builder) {
243 if (scheduler.empty() || scheduler ==
"simplex")
245 if (scheduler ==
"asap")
247 #ifdef SCHEDULING_OR_TOOLS
248 if (scheduler ==
"lp")
249 return scheduleWithLP(instOp, options, builder);
250 if (scheduler ==
"cpsat")
251 return scheduleWithCPSAT(instOp, options, builder);
254 llvm::errs() <<
"ssp-schedule: Unsupported scheduler '" << scheduler
264 struct SchedulePass :
public circt::ssp::impl::ScheduleBase<SchedulePass> {
265 void runOnOperation()
override;
269 void SchedulePass::runOnOperation() {
270 auto moduleOp = getOperation();
272 SmallVector<InstanceOp> instanceOps;
273 OpBuilder builder(&getContext());
274 for (
auto instOp : moduleOp.getOps<InstanceOp>()) {
275 builder.setInsertionPoint(instOp);
276 auto scheduledOp =
scheduleWith(instOp, scheduler.getValue(),
277 schedulerOptions.getValue(), builder);
279 return signalPassFailure();
280 instanceOps.push_back(instOp);
283 llvm::for_each(instanceOps, [](InstanceOp op) { op.erase(); });
287 return std::make_unique<SchedulePass>();
static InstanceOp scheduleProblemTWithSimplex(InstanceOp instOp, Operation *lastOp, OpBuilder &builder)
static InstanceOp scheduleWithASAP(InstanceOp instOp, OpBuilder &builder)
static OperationOp getLastOp(InstanceOp instOp, StringRef options)
static std::optional< float > getCycleTime(StringRef options)
static InstanceOp scheduleWithSimplex(InstanceOp instOp, StringRef options, OpBuilder &builder)
static InstanceOp scheduleChainingCyclicProblemWithSimplex(InstanceOp instOp, Operation *lastOp, float cycleTime, OpBuilder &builder)
static InstanceOp scheduleChainingProblemWithSimplex(InstanceOp instOp, Operation *lastOp, float cycleTime, OpBuilder &builder)
static InstanceOp scheduleWith(InstanceOp instOp, StringRef scheduler, StringRef options, OpBuilder &builder)
LogicalResult scheduleLP(Problem &prob, Operation *lastOp)
Solve the basic problem using linear programming and an external LP solver.
LogicalResult scheduleCPSAT(SharedOperatorsProblem &prob, Operation *lastOp)
Solve the acyclic problem with shared operators using constraint programming and an external SAT solv...
LogicalResult scheduleSimplex(Problem &prob, Operation *lastOp)
Solve the basic problem using linear programming and a handwritten implementation of the simplex algo...
LogicalResult scheduleASAP(Problem &prob)
This is a simple list scheduler for solving the basic scheduling problem.
std::unique_ptr< mlir::Pass > createSchedulePass()
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...
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.