/Base/Net.cs
C# | 532 lines | 358 code | 56 blank | 118 comment | 84 complexity | 3ca9fa2f77162b810c75f93f0ea25bc2 MD5 | raw file
- using System;
-
- namespace RapidHDL
- {
- /// <summary>
- /// Summary description for Net.
- /// </summary>
- public class Net
- {
- System.Collections.ArrayList oSourceNodes;
- System.Collections.ArrayList oSinkNodes;
- System.Collections.ArrayList oPassThroughNodes;
-
- System.Collections.ArrayList oTraceList;
- bool bTrace;
-
- SimulationState eSimulationStateOutput;
- NodeState eNetState;
-
- double dPropagationDelay;
-
- EventNode oEventNodeStabilize;
- RapidHardware oRapidHardware;
-
- // destabilize
- // stabilize
-
- /// <summary>
- /// Constructor to create a new net
- /// </summary>
- /// <param name="poNode">A net must have at least one node</param>
- public Net(Node poNode)
- {
- oEventNodeStabilize = null;
- dPropagationDelay = 0;
- eNetState = NodeState.Undefined;
- oSourceNodes = new System.Collections.ArrayList();
- oSinkNodes = new System.Collections.ArrayList();
- oPassThroughNodes = new System.Collections.ArrayList();
- eSimulationStateOutput = SimulationState.Stable;
- oRapidHardware = poNode.ParentNodeVector.ParentComponent.RapidHardware;
- this.Connect(poNode);
- }
-
- /// <summary>
- /// For debug purposes.
- /// Print the members of this net.
- /// Can be called from a debug session if there is a problem with the structure of RTL.
- /// </summary>
- public void DebugDisplayNet()
- {
- DebugDisplayNet(this);
- }
-
- /// <summary>
- /// For debug purposes.
- /// Print the members of a net.
- /// Can be called from a debug session if there is a problem with the structure of RTL.
- /// </summary>
- /// <param name="poNet">The net to display</param>
- public void DebugDisplayNet(Net poNet)
- {
- Console.WriteLine("---------- NET -------------- " + poNet.NetName);
- Console.WriteLine("Source Nodes");
- foreach (Node oNode in poNet.SourceNodes)
- {
- Console.WriteLine(oNode.ParentNodeVector.HirarchicalName + " " + oNode.Position.ToString());
- }
- Console.WriteLine("Sink Nodes");
- foreach (Node oNode in poNet.SinkNodes)
- {
- Console.WriteLine(oNode.ParentNodeVector.HirarchicalName + " " + oNode.Position.ToString());
- }
- Console.WriteLine("Pass Nodes");
- foreach (Node oNode in poNet.PassthroughNodes)
- {
- Console.WriteLine(oNode.ParentNodeVector.HirarchicalName + " " + oNode.Position.ToString());
- }
- Console.WriteLine("---------- END --------------");
- }
-
-
- /// <summary>
- /// Connect all the nodes in a different net to this net
- /// </summary>
- /// <param name="poNet">node to be added to this net</param>
- public void Connect(Net poNet)
- {
- if (this.NodeCount < poNet.NodeCount)
- {
- poNet.Connect(this);
- return;
- }
-
- //DebugDisplayNet();
- //DebugDisplayNet(poNet);
-
- foreach(Node oNode in poNet.SourceNodes)
- {
- this.Connect(oNode);
- }
- foreach(Node oNode in poNet.SinkNodes)
- {
- this.Connect(oNode);
- }
- foreach(Node oNode in poNet.PassthroughNodes)
- {
- this.Connect(oNode);
- }
- }
-
- /// <summary>
- /// Connect another node to this net
- /// </summary>
- /// <param name="poNode">node to be added to this net</param>
- public void Connect(Node poNode)
- {
- switch (poNode.NodeFlowType)
- {
- case NodeFlowType.Source:
- oSourceNodes.Add(poNode);
- break;
- case NodeFlowType.Sink:
- oSinkNodes.Add(poNode);
- break;
- case NodeFlowType.Passthrough:
- oPassThroughNodes.Add(poNode);
- break;
- }
- poNode.Net = this;
- }
-
- /// <summary>
- /// get the number of nodes in this net
- /// </summary>
- public int NodeCount
- {
- get
- {
- return oPassThroughNodes.Count + oSinkNodes.Count + oSourceNodes.Count;
- }
- }
-
- /// <summary>
- /// Used in simulation mode only.
- /// Determine if any inputs to this net are unstable or not.
- /// </summary>
- public SimulationState SimulationStateInput
- {
- get
- {
- foreach(Node oNode in oSourceNodes)
- {
- if (oNode.ParentNodeVector.ParentComponent.SimulationStateOutput == SimulationState.Unstable)
- {
- //SimulationTraceLog("This net's input node is unstable.",oNode);
- return SimulationState.Unstable;
- }
- }
- //SimulationTraceLog("This net's inputs are stable.",null);
- return SimulationState.Stable;
- }
- }
-
- /// <summary>
- /// Used in simulation only, get or set the state of the net.
- /// Only nets without source nodes may be set, otherwise the source nodes termine the net's state.
- /// </summary>
- public NodeState NodeState
- {
- get
- {
- if (oSourceNodes.Count == 0)
- return eNetState;
-
- NodeState eNodeState = NodeState.Tri;
- foreach(Node oNode in oSourceNodes)
- {
- if (oNode.NodeState != NodeState.Tri)
- {
- if (eNodeState == NodeState.Tri)
- eNodeState = oNode.NodeState;
- else
- {
- if (eNodeState != oNode.NodeState)
- return NodeState.Undefined;
- }
- }
- }
- return eNodeState;
- }
-
- set
- {
- if (oSourceNodes.Count == 0)
- {
- if (eNetState != value)
- {
- eNetState = value;
- }
- }
- }
- }
-
- /// <summary>
- /// Used in Verilog Creation
- /// </summary>
- /// <param name="poComponent"></param>
- /// <returns></returns>
- public Node SelectCriticalNode(Component poComponent)
- {
- foreach(Node oNode in oSourceNodes)
- {
- if (oNode.ParentNodeVector.ParentComponent == poComponent)
- if(oNode.NodeStructure == NetStructure.Connection | oNode.NodeStructure == NetStructure.Input | oNode.NodeStructure == NetStructure.Output)
- return oNode;
- }
-
- foreach(Node oNode in oSinkNodes)
- {
- if (oNode.ParentNodeVector.ParentComponent == poComponent)
- if(oNode.NodeStructure == NetStructure.Connection | oNode.NodeStructure == NetStructure.Input | oNode.NodeStructure == NetStructure.Output)
- return oNode;
- }
-
- foreach(Node oNode in oPassThroughNodes)
- {
- if (oNode.ParentNodeVector.ParentComponent == poComponent)
- if(oNode.NodeStructure == NetStructure.Connection | oNode.NodeStructure == NetStructure.Input | oNode.NodeStructure == NetStructure.Output)
- return oNode;
- }
-
- return null;
- }
-
- /// <summary>
- /// used for verilog generation, return nodes from thsi net matching a criteria
- /// </summary>
- /// <param name="poComponent">select only nodes from this component</param>
- /// <param name="peNetStructure">select only nodes of this structure type</param>
- /// <returns>list of nodes from this net</returns>
- public System.Collections.ArrayList SelectNodes(Component poComponent, NetStructure peNetStructure)
- {
- System.Collections.ArrayList oResult = new System.Collections.ArrayList();
- foreach(Node oNode in oSourceNodes)
- {
- if (oNode.ParentNodeVector.ParentComponent == poComponent & oNode.NodeStructure == peNetStructure)
- oResult.Add(oNode);
- }
-
- foreach(Node oNode in oSinkNodes)
- {
- if (oNode.ParentNodeVector.ParentComponent == poComponent & oNode.NodeStructure == peNetStructure)
- oResult.Add(oNode);
- }
-
- foreach(Node oNode in oPassThroughNodes)
- {
- if (oNode.ParentNodeVector.ParentComponent == poComponent & oNode.NodeStructure == peNetStructure)
- oResult.Add(oNode);
- }
-
- return oResult;
- }
-
-
- /// <summary>
- /// used for verilog generation, return nodes from this net matching a criteria
- /// </summary>
- /// <param name="poComponent">select only nodes from this component</param>
- /// <returns>list of nodes from this net</returns>
- public System.Collections.ArrayList SelectNodes(Component poComponent)
- {
- System.Collections.ArrayList oResult = new System.Collections.ArrayList();
- foreach(Node oNode in oSourceNodes)
- {
- if (oNode.ParentNodeVector.ParentComponent == poComponent)
- oResult.Add(oNode);
- }
-
- foreach(Node oNode in oSinkNodes)
- {
- if (oNode.ParentNodeVector.ParentComponent == poComponent)
- oResult.Add(oNode);
- }
-
- foreach(Node oNode in oPassThroughNodes)
- {
- if (oNode.ParentNodeVector.ParentComponent == poComponent)
- oResult.Add(oNode);
- }
-
- return oResult;
- }
-
- /// <summary>
- /// return the output state of this net, used for simulation
- /// </summary>
- public SimulationState SimulationStateOutput
- {
- get{return eSimulationStateOutput;}
- }
-
- /// <summary>
- /// ArrayList of nodes that are neither sources nor sinks, but passthrough conduits only
- /// </summary>
- public System.Collections.ArrayList PassthroughNodes
- {
- get {return oPassThroughNodes;}
- }
-
- /// <summary>
- /// Arraylist of nodes that are sources in this net. Note, if using tristates, you may have more than one source.
- /// </summary>
- public System.Collections.ArrayList SourceNodes
- {
- get {return oSourceNodes;}
- }
-
- /// <summary>
- /// Arraylist of nodes that are sinks, or consumers, of this net.
- /// </summary>
- public System.Collections.ArrayList SinkNodes
- {
- get {return oSinkNodes;}
- }
-
- /// <summary>
- /// used by simulation to mark this network as unstable
- /// </summary>
- public void SimulationDestabilizeNet()
- {
- // if net output is already unstable...
- // we only need to cancel any scheduled stabilization event
- if (eSimulationStateOutput == SimulationState.Unstable)
- {
- SimulationTraceLog("net is already unstable",null);
-
- // cancel stabilization event
- if (oEventNodeStabilize != null)
- oRapidHardware.Simulation.Clock.UnlinkNode(oEventNodeStabilize);
- oEventNodeStabilize = null;
- return;
- }
-
- // otherwise, we were a net stable,
- // we need to alert sink nodes in the net that we are now unstable
- eSimulationStateOutput = SimulationState.Unstable;
- int i = 1;
- foreach(Node oNode in oSinkNodes)
- {
- Component oComponent = oNode.ParentNodeVector.ParentComponent;
- if (!oComponent.RegisteredComponent)
- {
- SimulationTraceLog("Destabilizing Component {" + oNode.ParentNodeVector.ParentComponent.HirarchicalName + "} from Net via Node, loop " + i.ToString() + " of " + oSinkNodes.Count.ToString(), oNode);
- oComponent.SimulationDestabilizeComponent();
- }
- }
- }
-
- /// <summary>
- /// used by simulation to mark this net as stable
- /// </summary>
- public void SimulationStabilizeNet()
- {
- // should never call this when node is already stable
- System.Diagnostics.Debug.Assert(eSimulationStateOutput != SimulationState.Stable);
-
- // debug trace stabililzation event
- if (bTrace)
- {
- if (oTraceList.Contains("stabilize"))
- {
- System.Console.Write("Break for {stabilize} " + this.NodeState + " - " + this.NetName + "\n");
- oRapidHardware.SystemInterface.ListAll();
- System.Diagnostics.Debugger.Break();
- }
- }
-
- // check to see if the inputs are all stable
- if (this.SimulationStateInput != SimulationState.Stable)
- {
- return; // unstable inputs mean unstable net
- }
-
- // if there is no propagation delay, immediately stabilize output too
- // but, if there is a propagation delay, schedule stabilization event on clock
- // hack: hardcoded propagation delay, try to fix hold time failures on registers
- if (dPropagationDelay == 0)
- {
- SimulationStabilizeNetOutputEvent(0);
- //dPropagationDelay = (1.0 / (double)oRapidHardware.Simulation.Clock.Frequency * .01);
- }
- else
- {
- if (oEventNodeStabilize != null)
- oRapidHardware.Simulation.Clock.UnlinkNode(oEventNodeStabilize);
- oEventNodeStabilize = oRapidHardware.Simulation.Clock.ScheduleClockEvent(dPropagationDelay,this.SimulationStabilizeNetOutputEvent);
- }
- }
-
- /// <summary>
- /// simulation event delegate, stabilize the net at specified time
- /// </summary>
- /// <param name="pdTimeNow">time (after delay) when stabilization event is scheduled in event clock</param>
- public void SimulationStabilizeNetOutputEvent(double pdTimeNow)
- {
-
- SimulationTraceLog("SimulationSabilizeComponentOutputEvent at time " + pdTimeNow.ToString() + "/" + oRapidHardware.Simulation.Clock.TimeNow.ToString() ,null);
-
- // if oEventNode is not null when calling directly, then there is a fundamental scheduling problem
- System.Diagnostics.Debug.Assert(oEventNodeStabilize == null & pdTimeNow == 0 | pdTimeNow != 0,"Phantom EventNodeStabilize event scheduled in Net object!");
-
- // should never call this event if node is already stable
- System.Diagnostics.Debug.Assert(eSimulationStateOutput != SimulationState.Stable,"Net stabilization event called when net is already stable!");
-
- eSimulationStateOutput = SimulationState.Stable;
-
- int i = 1;
- foreach(Node oNode in oSinkNodes)
- {
- Component oComponent = oNode.ParentNodeVector.ParentComponent;
- if (!oComponent.RegisteredComponent)
- {
- SimulationTraceLog("Stabilizing Component {" + oNode.ParentNodeVector.ParentComponent.HirarchicalName + "} from Net via Node, loop " + i.ToString() + " of " + oSinkNodes.Count.ToString(), oNode);
- oComponent.SimulationStabilizeComponent();
- }
- i++;
- }
- }
-
- /// <summary>
- /// Log the simulation state variables of a particular node
- /// </summary>
- /// <param name="psLogEntry">information is added to this input string</param>
- /// <param name="poNode">state data of this node is logged</param>
- private void SimulationTraceLog(string psLogEntry, Node poNode)
- {
- string sLogEntry = "Net: ";
- sLogEntry += psLogEntry;
- if (poNode != null)
- sLogEntry += " {Node: " + poNode.ParentNodeVector.ParentComponent.HirarchicalName.ToString() + "." + poNode.Name + " = '" + poNode.NodeState.ToString() + "'}";
- oRapidHardware.InternalLog.Log(LogType.SimulationTrace,sLogEntry);
- }
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="psLabel"></param>
- public void SetTrace(string psLabel)
- {
- if (!bTrace)
- {
- bTrace = true;
- oTraceList = new System.Collections.ArrayList();
- }
- if (oTraceList.Contains(psLabel))
- return;
- oTraceList.Add(psLabel);
- }
-
- /// <summary>
- /// returns the connections of the structure of this network,
- /// using source hirarchical names
- /// </summary>
- public string NetName
- {
- get
- {
- string sName = "";
- Node oNode;
- if (oSinkNodes.Count > 0)
- {
- oNode = (Node)oSinkNodes[0];
- sName += oNode.HirarchicalName;
- }
- sName += "<=";
- if (oSourceNodes.Count > 0)
- {
- oNode = (Node)oSourceNodes[0];
- sName += oNode.HirarchicalName;
- }
-
- return sName;
- }
- }
-
- /// <summary>
- /// used only for simulation,
- /// force the state of all nodes in this net
- /// </summary>
- /// <param name="pNodeState">state to force</param>
- public void ForceNodeState(NodeState pNodeState)
- {
- if (this.NodeState == pNodeState)
- return;
- this.NodeState = pNodeState;
- if (this.NodeState == pNodeState)
- return;
- foreach (Node oNode in SourceNodes)
- {
- oNode.NodeState = pNodeState;
- }
- }
-
- /// <summary>
- /// check to see if a node belongs to this net
- /// </summary>
- /// <param name="poNode">node we are seeking</param>
- /// <returns>true if the node belongs to this net</returns>
- public bool ContainsNode(Node poNode)
- {
- foreach (Node oNode in oSourceNodes)
- {
- if (oNode == poNode)
- return true;
- }
- foreach (Node oNode in oSinkNodes)
- {
- if (oNode == poNode)
- return true;
- }
- foreach (Node oNode in oPassThroughNodes)
- {
- if (oNode == poNode)
- return true;
- }
- return false;
- }
-
- }
- }