16 #include "mlir/IR/Operation.h"
18 #include "ortools/linear_solver/linear_solver.h"
20 using namespace circt;
22 using namespace operations_research;
27 return containingOp->emitError(
"problem does not include last operation");
29 MPSolver::OptimizationProblemType problemType;
30 if (!MPSolver::ParseSolverType(
"GLOP_LINEAR_PROGRAMMING", &problemType) ||
31 !MPSolver::SupportsProblemType(problemType))
32 return containingOp->emitError(
"GLOP is unvailable");
34 MPSolver solver(
"Problem", problemType);
35 double infinity = solver.infinity();
38 DenseMap<Operation *, MPVariable *> vars;
41 vars[op] = solver.MakeNumVar(0, infinity, (Twine(
"t_") + Twine(i)).str());
46 MPObjective *objective = solver.MutableObjective();
47 objective->SetCoefficient(vars[lastOp], 1);
48 objective->SetMinimization();
53 Operation *src = dep.getSource();
54 Operation *dst = dep.getDestination();
56 return containingOp->emitError() <<
"dependence cycle detected";
61 MPConstraint *constraint =
62 solver.MakeRowConstraint(-infinity, -((
double)latency));
63 constraint->SetCoefficient(vars[src], 1);
64 constraint->SetCoefficient(vars[dst], -1);
69 MPSolver::ResultStatus result = solver.Solve();
70 if (result == MPSolver::INFEASIBLE)
71 return containingOp->emitError() <<
"dependence cycle detected";
72 assert(result == MPSolver::OPTIMAL);
76 prob.
setStartTime(op, std::round(vars[op]->solution_value()));
84 return containingOp->emitError(
"problem does not include last operation");
86 MPSolver::OptimizationProblemType probType;
87 if (!MPSolver::ParseSolverType(
"CBC_MIXED_INTEGER_PROGRAMMING", &probType) ||
88 !MPSolver::SupportsProblemType(probType))
89 return containingOp->emitError(
"Cbc is unavailable");
91 MPSolver solver(
"CyclicProblem", probType);
92 double infinity = solver.infinity();
95 MPVariable *ii = solver.MakeIntVar(1, infinity,
"II");
99 DenseMap<Operation *, MPVariable *> t;
100 unsigned upperBound = 0;
103 t[op] = solver.MakeIntVar(0, infinity, (Twine(
"t_") + Twine(i)).str());
111 MPObjective *objective = solver.MutableObjective();
112 objective->SetCoefficient(ii, upperBound);
113 objective->SetCoefficient(t[lastOp], 1);
114 objective->SetMinimization();
119 Operation *src = dep.getSource();
120 Operation *dst = dep.getDestination();
125 MPConstraint *constraint =
126 solver.MakeRowConstraint(-infinity, -((
double)latency));
128 constraint->SetCoefficient(t[src], 1);
129 constraint->SetCoefficient(t[dst], -1);
131 constraint->SetCoefficient(ii,
138 MPSolver::ResultStatus result = solver.Solve();
139 if (result == MPSolver::INFEASIBLE)
140 return containingOp->emitError() <<
"dependence cycle detected";
141 assert(result == MPSolver::OPTIMAL);
146 prob.
setStartTime(op, std::round(t[op]->solution_value()));
assert(baseType &&"element must be base type")
This class models a cyclic scheduling problem.
void setInitiationInterval(unsigned val)
std::optional< unsigned > getDistance(Dependence dep)
The distance determines whether a dependence has to be satisfied in the same iteration (distance=0 or...
This class models the most basic scheduling problem.
std::optional< OperatorType > getLinkedOperatorType(Operation *op)
The linked operator type provides the runtime characteristics for op.
bool hasOperation(Operation *op)
Return true if op is part of this problem.
void setStartTime(Operation *op, unsigned val)
DependenceRange getDependences(Operation *op)
Return a range object to transparently iterate over op's incoming 1) implicit def-use dependences (ba...
const OperationSet & getOperations()
Return the set of operations.
std::optional< unsigned > getLatency(OperatorType opr)
The latency is the number of cycles opr needs to compute its result.
Operation * getContainingOp()
Return the operation containing this problem, e.g. to emit diagnostics.
LogicalResult scheduleLP(Problem &prob, Operation *lastOp)
Solve the basic problem using linear programming and an external LP solver.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.