private int FindClockPeriod(DelayGraphVertex vertex, Dictionary <DelayGraphVertex, int> computedDelays, out bool foundCycle) { int periodEstimatedFromThisTerminalForward = TraverseForwardCalculatingPeriodIterative(vertex, computedDelays, out foundCycle); return(periodEstimatedFromThisTerminalForward); }
private static long GetLatencyCost(DelayGraphVertex v, HashSet <DelayGraphVertex> registered) { if (v.IsRegistered || registered.Contains(v)) { return(v.LatencyCostIfRegistered); } return(0); }
private int TraverseForwardCalculatingPeriod( DelayGraphVertex startingVertex, out bool foundCycle) { var computedDelays = new Dictionary <DelayGraphVertex, int>(); var visiting = new HashSet <DelayGraphVertex>(); return(TraverseForwardCalculatingPeriodRecursive(startingVertex, out foundCycle, visiting, computedDelays)); }
/// <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> /// allocate and enter a data into WaveFrontDictionary for vertex v, initialized to refCount /// </summary> /// <param name="v">a vertex</param> /// <param name="refCount">the reference count for number of uses before deleting from dictionary</param> /// <param name="data">The data for this definition.</param> /// <returns>the allocated data</returns> internal void Define(DelayGraphVertex v, int refCount, T data) { var packet = new Packet <T>(refCount, data); if (refCount > 0) { this[v] = packet; } }
private static IEnumerable <DelayGraphVertex> GetFanouts(DelayGraphVertex v, DelayGraph graph) { IEnumerable <DelayGraphEdge> edges; if (graph.TryGetOutEdges(v, out edges)) { return(edges.Select(e => e.Target)); } return(Enumerable.Empty <DelayGraphVertex>()); }
/// <summary> /// if myData is null, create it and register it into table using table.Define() for vertex v /// </summary> /// <param name="table">the wavefront dictionary</param> /// <param name="v">a vertex</param> /// <param name="myRefCount">reference count </param> /// <param name="myData">original data, could be null</param> /// <returns></returns> private static Dictionary <DelayGraphVertex, long> GetOrMakeMyData(WaveFrontDictionary <Dictionary <DelayGraphVertex, long> > table, DelayGraphVertex v, int myRefCount, Dictionary <DelayGraphVertex, long> myData) { if (myData == null) { myData = new Dictionary <DelayGraphVertex, long>(); table.Define(v, myRefCount, myData); } return(myData); }
internal PeriodTraverseState( DelayGraphVertex vertex, int delayReturned, Queue <DelayGraphEdge> unfinishedEdges, int maxAmongOutgoingEdges) { Vertex = vertex; DelayReturned = delayReturned; UnfinishedEdges = unfinishedEdges; MaxAmongOutgoingEdges = maxAmongOutgoingEdges; StateWaitingOn = null; }
private int TraverseForwardCalculatingPeriodRecursive(DelayGraphVertex startingVertex, out bool foundCycle, HashSet <DelayGraphVertex> visiting, Dictionary <DelayGraphVertex, int> computedDelays) { foundCycle = false; int maxAmongOutgoingEdges = 0; if (computedDelays.TryGetValue(startingVertex, out maxAmongOutgoingEdges)) { return(maxAmongOutgoingEdges); } if (visiting.Contains(startingVertex)) // stop recursing if we hit a cycle { foundCycle = true; return(0); } // set state to visiting for starting vertex visiting.Add(startingVertex); IEnumerable <DelayGraphEdge> foundOutgoingEdges; if (Graph.TryGetOutEdges(startingVertex, out foundOutgoingEdges)) { foreach (var outEdge in foundOutgoingEdges) { int delayOnThisPath; if (Registered(outEdge.Target)) // stop recursing when we hit a register { delayOnThisPath = outEdge.Delay; } else { bool anyCycle; delayOnThisPath = outEdge.Delay + TraverseForwardCalculatingPeriodRecursive( startingVertex: outEdge.Target, foundCycle: out anyCycle, visiting: visiting, computedDelays: computedDelays); if (anyCycle) { foundCycle = true; } } maxAmongOutgoingEdges = Math.Max(maxAmongOutgoingEdges, delayOnThisPath); } } // finished visiting startingVertex - enter into ComputeDelays - which means visited is done // and remove it from visiting to be technically correct computedDelays[startingVertex] = maxAmongOutgoingEdges; visiting.Remove(startingVertex); return(maxAmongOutgoingEdges); }
/// <summary> /// decrement reference count, if 0, remove v from dictinary /// </summary> /// <param name="v">a vertex</param> /// <returns>the data being kept for v in WaveFrontDictionary</returns> internal T Use(DelayGraphVertex v) { Packet <T> packet; if (TryGetValue(v, out packet)) { var data = packet.Data; packet.RefCount--; if (packet.RefCount == 0) { Remove(v); } return(data); } return(default(T)); }
/// <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); }
private void RetimeRegister(DelayGraphVertex v) { if (v.IsInputTerminal) { // move v's register to incoming edges foreach (var e in Graph.GetForwardInEdges(v)) { RegisteredTerminals.Add(e.Source); } } else { // move v's register to outgoing edges foreach (var e in Graph.GetForwardOutEdges(v)) { RegisteredTerminals.Add(e.Source); } } RegisteredTerminals.Remove(v); }
private static Dictionary <String, DelayGraphVertex> RecreateVertices(XElement graph, String nmsp, DelayGraph delayGraph) { var nodeIdToVertexMap = new Dictionary <String, DelayGraphVertex>(); var vertexType = typeof(DelayGraphVertex); // todo: update this map if new properties are added...or use "CreatePropertyTypeMap" below var propertyToTypeMap = new Dictionary <String, Type>() { { "VertexId", typeof(int) }, { "NodeType", typeof(int) }, { "NodeUniqueId", typeof(int) }, { "ThroughputCostIfRegistered", typeof(long) }, { "LatencyCostIfRegistered", typeof(long) }, { "RegisterCostIfRegistered", typeof(long) }, { "IsRegistered", typeof(bool) }, { "IsInputTerminal", typeof(bool) }, { "IsOutputTerminal", typeof(bool) }, { "DisallowRegister", typeof(bool) } }; // get the nodes foreach (var node in graph.Elements(nmsp + "node")) { // create new vertex var vertex = new DelayGraphVertex(); var id = (string)node.Attribute("id"); nodeIdToVertexMap.Add(id, vertex); // populate the fields of the node foreach (var data in node.Elements()) { var key = (string)data.Attribute("key"); dynamic contents = Convert.ChangeType(data.Value, propertyToTypeMap[key], CultureInfo.InvariantCulture); vertexType.GetProperty(key).SetValue(vertex, contents); } // add the node to the graph delayGraph.AddVertex(vertex); } return(nodeIdToVertexMap); }
/// <summary> /// return true iff there is at least one forward combinational path from v to target (ie, a path consisting of forward edges and no registered vertices along the way) /// </summary> /// <param name="v">the source vertex</param> /// <param name="target">the target vertex</param> /// <param name="visited">a cache for visited vertices</param> /// <returns>true iff there is a combinational forward path</returns> private bool FindForwardPath(DelayGraphVertex v, DelayGraphVertex target, HashSet <DelayGraphVertex> visited) { if (v == target) { return(true); } if (!visited.Add(v)) { // previously visited return(false); } foreach (var e in Graph.GetForwardOutEdges(v)) { if (Registered(e.Target)) { continue; } if (FindForwardPath(e.Target, target, visited)) { return(true); } } return(false); }
private int TraverseForwardCalculatingPeriodIterative( DelayGraphVertex startingVertex, Dictionary <DelayGraphVertex, int> computedDelays, out bool foundCycle) { Stack <DelayGraphVertex> stack = new Stack <DelayGraphVertex>(); var visited = new Dictionary <DelayGraphVertex, VisitState>(); stack.Push(startingVertex); visited[startingVertex] = VisitState.Queued; foundCycle = false; while (stack.Any()) { DelayGraphVertex currentVertex = stack.Peek(); var visitStatus = visited[currentVertex]; // it is an error if currentVertex is not found in visited dictionary if (visitStatus == VisitState.Queued) { // first time processing currentVertex - queue all outgoing edges visited[currentVertex] = VisitState.Visiting; IEnumerable <DelayGraphEdge> foundOutgoingEdges; if (Graph.TryGetOutEdges(currentVertex, out foundOutgoingEdges)) { var todo = foundOutgoingEdges.Where(e => !Registered(e.Target)).Select(e => e.Target); todo.Reverse(); foreach (var next in todo) { VisitState status; if (!visited.TryGetValue(next, out status)) { visited[next] = VisitState.Queued; stack.Push(next); } else if (status == VisitState.Queued) { // next has been previously queued - have to push it again so this is processed before parent's second visit stack.Push(next); } else if (status == VisitState.Visiting) { // found a cycle foundCycle = true; computedDelays[next] = 0; } // ok if status is Visited - no need to re-schedule next } } } else if (visitStatus == VisitState.Visiting) { // second visit - all fanout have been processed already int maxDelay = 0; IEnumerable <DelayGraphEdge> foundOutgoingEdges; if (Graph.TryGetOutEdges(currentVertex, out foundOutgoingEdges)) { foreach (var edge in foundOutgoingEdges) { var next = edge.Target; int nextDelay = 0; if (!Registered(next)) { if (!computedDelays.TryGetValue(next, out nextDelay)) { throw new Exception("Cannot find Key: next should have been processed and found in ComputeDelays"); } } maxDelay = Math.Max(maxDelay, edge.Delay + nextDelay); } } computedDelays[currentVertex] = maxDelay; visited[currentVertex] = VisitState.Visited; stack.Pop(); } else { // visited - due to reconvergence - just pop it stack.Pop(); } } return(computedDelays[startingVertex]); }
private int TraverseForwardCalculatingPeriodIterative2( DelayGraphVertex startingVertex, out bool foundCycle) { Stack <PeriodTraverseState> stack = new Stack <PeriodTraverseState>(); stack.Push(new PeriodTraverseState(startingVertex)); PeriodTraverseState currentState = null; foundCycle = false; while (stack.Any()) { currentState = stack.Peek(); int alreadyComputedDelay = 0; if (ComputedDelays.TryGetValue(currentState.Vertex, out alreadyComputedDelay)) // put in for reconvergent paths { currentState.DelayReturned = alreadyComputedDelay; stack.Pop(); continue; } if (currentState.StateWaitingOn == null) // this state is used here just to tell if we are coming along here b/c we need to attend to unfinished business where we might have already set 'visited' { if (Visiting.Contains(currentState.Vertex)) // stop recursing if we're going along a loop, but still add up the delays of the loop { currentState.DelayReturned = 0; foundCycle = true; stack.Pop(); continue; } Visiting.Add(currentState.Vertex); } if (currentState.UnfinishedEdges == null) { IEnumerable <DelayGraphEdge> foundOutgoingEdges; if (Graph.TryGetOutEdges(currentState.Vertex, out foundOutgoingEdges)) { currentState.UnfinishedEdges = new Queue <DelayGraphEdge>(foundOutgoingEdges); } } bool done = true; while (currentState.UnfinishedEdges != null && currentState.UnfinishedEdges.Any()) { var outEdge = currentState.UnfinishedEdges.Peek(); int delayOnThisPath; if (Registered(outEdge.Target)) // stop recursing when we hit a register { delayOnThisPath = outEdge.Delay; } else if (Visiting.Contains(outEdge.Target)) { // found a cycle foundCycle = true; delayOnThisPath = outEdge.Delay; } else { if (currentState.StateWaitingOn == null) { currentState.StateWaitingOn = new PeriodTraverseState(outEdge.Target); stack.Push(currentState.StateWaitingOn); done = false; // need to process what we just pushed break; } else { delayOnThisPath = outEdge.Delay + currentState.StateWaitingOn.DelayReturned; currentState.StateWaitingOn = null; } } currentState.UnfinishedEdges.Dequeue(); currentState.MaxAmongOutgoingEdges = Math.Max(currentState.MaxAmongOutgoingEdges, delayOnThisPath); } if (done) { ComputedDelays[currentState.Vertex] = currentState.MaxAmongOutgoingEdges; currentState.DelayReturned = currentState.MaxAmongOutgoingEdges; Visiting.Remove(currentState.Vertex); stack.Pop(); } } return(currentState.DelayReturned); }
internal PeriodTraverseState( DelayGraphVertex vertex) : this(vertex, 0, null, 0) { }
private bool Registered(DelayGraphVertex v) { return(v.IsRegistered || RegisteredTerminals.Contains(v)); }