/// <summary> /// find the max latency /// </summary> /// <param name="sort">sorted list of vertices</param> /// <param name="graph">delay graph</param> /// <param name="registered">hash table of registered vertices</param> /// <returns>number of cycles</returns> internal static long FindMaxLatencyCore(IEnumerable <DelayGraphVertex> sort, DelayGraph graph, HashSet <DelayGraphVertex> registered) { long maxLatencyCost = 0; var table = new WaveFrontDictionary <long>(); foreach (var v in sort) { var inEdges = graph.GetForwardInEdges(v); var outEdges = graph.GetForwardOutEdges(v); int myRefCount = outEdges.Count(); // first, consume predecessor's wavefront data, if any long myCost = 0; foreach (var e in inEdges) { var p = e.Source; var c = table.Use(p); // default for long is 0 // copy data into myData myCost = Math.Max(myCost, c); } // then add v's latency cost myCost += GetLatencyCost(v, registered); // register myCost into table table.Define(v, myRefCount, myCost); // update maxLatencyCost if v has no outEdges if (myRefCount == 0 && maxLatencyCost < myCost) { maxLatencyCost = myCost; } } return(maxLatencyCost); }
/// <summary> /// Iterative version of topological sort, of forward edges only /// </summary> /// <param name="v">a delay graph vertex</param> /// <param name="sorted">linked list of sorted list of vertices</param> /// <param name="visited">to keep track of vertices that have been visited previously</param> /// <param name="graph">the delay graph</param> /// <returns>return true iff v is processed as unvisited</returns> private static bool TopoIterative(DelayGraphVertex v, LinkedList <DelayGraphVertex> sorted, Dictionary <DelayGraphVertex, VisitState> visited, DelayGraph graph) { // add v to visited first, and if it is already visited, then bail if (visited.ContainsKey(v)) { return(false); } var stack = new Stack <DelayGraphVertex>(); visited[v] = VisitState.Queued; stack.Push(v); while (stack.Any()) { var curr = stack.Peek(); var status = visited[curr]; if (status == VisitState.Queued) { // first ever visit, queue all outgoing vertices visited[curr] = VisitState.Visiting; var outEdges = graph.GetForwardOutEdges(curr); foreach (var e in outEdges.Reverse()) { var next = e.Target; VisitState nextStatus; if (!visited.TryGetValue(next, out nextStatus) || nextStatus == VisitState.Queued) { // not visited yet, or previously queued, queue next visited[next] = VisitState.Queued; stack.Push(next); } else if (nextStatus == VisitState.Visiting) { // found a cycle - not supposed to happen - there is no good topological sort with cycles return(false); } // othewise: visited, no need to queue it again } } else if (status == VisitState.Visiting) { // second visit - all fanout have been processed already visited[curr] = VisitState.Visited; sorted.AddFirst(curr); stack.Pop(); } else { // visited - previously added to sorted already, just pop it stack.Pop(); } } return(true); }
/// <summary> /// return a topologically sorted (according to non-feedback edges only) list of vertices /// </summary> /// <param name="v">a vertex</param> /// <param name="sorted">linked list of sorted list of vertices</param> /// <param name="visited">to keep track of vertices that have been visited previously</param> /// <param name="graph">the delay graph</param> /// <returns>return true iff v is processed as unvisited </returns> private static bool TopoRecursive(DelayGraphVertex v, LinkedList <DelayGraphVertex> sorted, HashSet <DelayGraphVertex> visited, DelayGraph graph) { // add v to visited first, and if it is already visited, then bail if (visited.Add(v)) { var outEdges = graph.GetForwardOutEdges(v); foreach (var e in outEdges) { TopoRecursive(e.Target, sorted, visited, graph); } // all fanout have been visited and added to sorted list - add v to start of sorted list sorted.AddFirst(v); return(true); } return(false); }
/// <summary> /// find and return the maximum cyclic throughput cost /// </summary> /// <param name="sort">topological sorted enumerable of vertices</param> /// <param name="graph">a delay graph</param> /// <param name="registered">a hash set containing registered vertices</param> /// <returns>a value representing maximum throughput cost of all cycles</returns> internal static long FindMaxThroughputCostCore(IEnumerable <DelayGraphVertex> sort, DelayGraph graph, HashSet <DelayGraphVertex> registered) { long maxCycleCost = 0; var table = new WaveFrontDictionary <Dictionary <DelayGraphVertex, long> >(); foreach (var v in sort) { var inEdges = graph.GetForwardInEdges(v); var outEdges = graph.GetForwardOutEdges(v); var feedbackInEdges = graph.GetFeedbackInEdges(v); var feedbackOutEdges = graph.GetFeedbackOutEdges(v); int myRefCount = outEdges.Count(); long cost = GetThroughputCost(v, registered); Dictionary <DelayGraphVertex, long> myData = null; // first, consume predecessor's wavefront data, if any foreach (var e in inEdges) { var p = e.Source; var data = table.Use(p); if (data == null) { continue; } // copy data into myData myData = GetOrMakeMyData(table, v, myRefCount, myData); UpdateMaxData(myData, data); } if (cost > 0 && myData != null) { // incr all costs in myData by cost foreach (var p in myData.Keys.ToList()) { myData[p] += cost; } } if (feedbackInEdges.Any()) { // v is start of cycle - enter v into myData myData = GetOrMakeMyData(table, v, myRefCount, myData); myData[v] = cost; } if (myData == null) { continue; } // update max cycle cost foreach (var e in feedbackOutEdges) { var p = e.Target; long cycleCost; if (myData.TryGetValue(p, out cycleCost) && cycleCost > maxCycleCost) { maxCycleCost = cycleCost; } } } return(maxCycleCost); }