public long Schedule <T>(ISchedulingAdapter <T> a, IList <T> nodes, IList <T> end, SchedulingConstraints constraints) { ASAPScheduler.CheckInput(a, nodes); long endTime = constraints.EndTime; foreach (T x in nodes) { a.CStep[x] = long.MaxValue; } var pq = new PriorityQueue <NodeSet <T> >() { Resolve = NodeSet <T> .Merge }; foreach (T x in end) { pq.Enqueue(-endTime, NodeSet <T> .From(x)); } long startTime = endTime - 1; while (!pq.IsEmpty) { var cur = pq.Dequeue(); long curTime = -cur.Key; long reqTime = long.MaxValue; var curSet = cur.Value; var order = PriorizeNodes(curSet.Nodes); foreach (T x in order) { bool ready = true; foreach (var dy in a.Succs[x]) { T y = dy.Task; if (a.CStep[y] == long.MaxValue) { // at least one successor is not yet scheduled // -> task not ready ready = false; reqTime = long.MaxValue; break; } else if (a.CStep[y] < curTime - a.Latency[x] + dy.MinDelay) { // at least one successor starts before current task could // complete -> task not ready ready = false; if (reqTime < long.MaxValue) { reqTime = Math.Min(reqTime, a.CStep[y] + a.Latency[x] - dy.MinDelay); } } } if (ready) { // Check for deadline violations in second pass foreach (var dy in a.Succs[x]) { T y = dy.Task; if (a.CStep[y] > curTime - a.Latency[x] + dy.MaxDelay) { // deadline exceeded throw new NotSchedulableException(); } } long lat = a.Latency[x]; long execTime = curTime - lat; // If some operation is combinatorial (latency == 0) and is scheduled as // last instruction, it must be moved one step back to fit inside the schedule's // time frame. if (execTime == endTime) { --execTime; } long preHint, postHint; if (!ConstrainedResources || a.TryPin(x, execTime, out preHint, out postHint)) { a.CStep[x] = execTime; long nextTime = execTime; startTime = Math.Min(startTime, execTime); // requeue predecessors foreach (var dw in a.Preds[x]) { T w = dw.Task; pq.Enqueue(-(execTime - dw.MinDelay + a.Latency[w]), NodeSet <T> .From(w)); } } else { if (preHint < 0) { throw new NotSchedulableException(); } pq.Enqueue(-(preHint + lat), NodeSet <T> .From(x)); } } else if (reqTime < long.MaxValue) { pq.Enqueue(-reqTime, NodeSet <T> .From(x)); } } } foreach (T x in nodes) { if (a.CStep[x] == long.MaxValue) { throw new NotSchedulableException(); } } return(startTime); }
public bool TryPin(T task, long cstep, out long preHint, out long postHint) { return(_scha.TryPin(task, cstep, out preHint, out postHint)); }
public long Schedule <T>(ISchedulingAdapter <T> a, IList <T> nodes, IList <T> startNodes, SchedulingConstraints constraints) { CheckInput(a, nodes); long startTime = constraints.StartTime; foreach (T x in nodes) { a.CStep[x] = long.MinValue; } var pq = new PriorityQueue <NodeSet <T> >() { Resolve = NodeSet <T> .Merge }; foreach (T x in startNodes) { pq.Enqueue(startTime, NodeSet <T> .From(x)); } long endTime = startTime + 1; while (!pq.IsEmpty) { var cur = pq.Dequeue(); long curTime = cur.Key; var curSet = cur.Value; foreach (T x in curSet.Nodes) { bool ready = true; long reqTime = curTime; foreach (var dw in a.Preds[x]) { T w = dw.Task; if (a.CStep[w] == long.MinValue) { // at least one predecessor is not yet scheduled // -> we cannot tell whether it is ok to schedule current task. ready = false; reqTime = long.MinValue; break; } else if (a.CStep[w] + dw.MinDelay > curTime) { // at least one predecessor did not yet complete. ready = false; if (reqTime > long.MinValue) { reqTime = Math.Max(reqTime, a.CStep[w] + dw.MinDelay); } } } if (ready) { // Check for deadline violations in second pass foreach (var dw in a.Preds[x]) { T w = dw.Task; if (a.CStep[w] + dw.MaxDelay < curTime) { // deadline exceeded throw new NotSchedulableException(); } } if (a.CStep[x] == long.MinValue) { long preHint, postHint; if (!ConstrainedResources || a.TryPin(x, curTime, out preHint, out postHint)) { a.CStep[x] = curTime; long lat = a.Latency[x]; long nextTime = curTime + lat; if (lat > 0) { endTime = Math.Max(endTime, nextTime); } else { endTime = Math.Max(endTime, nextTime + 1); } // enqueue successor tasks foreach (var dy in a.Succs[x]) { T y = dy.Task; pq.Enqueue(curTime + dy.MinDelay, NodeSet <T> .From(y)); } } else { pq.Enqueue(postHint, NodeSet <T> .From(x)); } } } else if (reqTime > long.MinValue) { pq.Enqueue(reqTime, NodeSet <T> .From(x)); } } } foreach (T x in nodes) { if (a.CStep[x] == long.MinValue) { throw new NotSchedulableException(); } } return(endTime); }