PageRenderTime 26ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/Base/Net.cs

#
C# | 532 lines | 358 code | 56 blank | 118 comment | 84 complexity | 3ca9fa2f77162b810c75f93f0ea25bc2 MD5 | raw file
  1. using System;
  2. namespace RapidHDL
  3. {
  4. /// <summary>
  5. /// Summary description for Net.
  6. /// </summary>
  7. public class Net
  8. {
  9. System.Collections.ArrayList oSourceNodes;
  10. System.Collections.ArrayList oSinkNodes;
  11. System.Collections.ArrayList oPassThroughNodes;
  12. System.Collections.ArrayList oTraceList;
  13. bool bTrace;
  14. SimulationState eSimulationStateOutput;
  15. NodeState eNetState;
  16. double dPropagationDelay;
  17. EventNode oEventNodeStabilize;
  18. RapidHardware oRapidHardware;
  19. // destabilize
  20. // stabilize
  21. /// <summary>
  22. /// Constructor to create a new net
  23. /// </summary>
  24. /// <param name="poNode">A net must have at least one node</param>
  25. public Net(Node poNode)
  26. {
  27. oEventNodeStabilize = null;
  28. dPropagationDelay = 0;
  29. eNetState = NodeState.Undefined;
  30. oSourceNodes = new System.Collections.ArrayList();
  31. oSinkNodes = new System.Collections.ArrayList();
  32. oPassThroughNodes = new System.Collections.ArrayList();
  33. eSimulationStateOutput = SimulationState.Stable;
  34. oRapidHardware = poNode.ParentNodeVector.ParentComponent.RapidHardware;
  35. this.Connect(poNode);
  36. }
  37. /// <summary>
  38. /// For debug purposes.
  39. /// Print the members of this net.
  40. /// Can be called from a debug session if there is a problem with the structure of RTL.
  41. /// </summary>
  42. public void DebugDisplayNet()
  43. {
  44. DebugDisplayNet(this);
  45. }
  46. /// <summary>
  47. /// For debug purposes.
  48. /// Print the members of a net.
  49. /// Can be called from a debug session if there is a problem with the structure of RTL.
  50. /// </summary>
  51. /// <param name="poNet">The net to display</param>
  52. public void DebugDisplayNet(Net poNet)
  53. {
  54. Console.WriteLine("---------- NET -------------- " + poNet.NetName);
  55. Console.WriteLine("Source Nodes");
  56. foreach (Node oNode in poNet.SourceNodes)
  57. {
  58. Console.WriteLine(oNode.ParentNodeVector.HirarchicalName + " " + oNode.Position.ToString());
  59. }
  60. Console.WriteLine("Sink Nodes");
  61. foreach (Node oNode in poNet.SinkNodes)
  62. {
  63. Console.WriteLine(oNode.ParentNodeVector.HirarchicalName + " " + oNode.Position.ToString());
  64. }
  65. Console.WriteLine("Pass Nodes");
  66. foreach (Node oNode in poNet.PassthroughNodes)
  67. {
  68. Console.WriteLine(oNode.ParentNodeVector.HirarchicalName + " " + oNode.Position.ToString());
  69. }
  70. Console.WriteLine("---------- END --------------");
  71. }
  72. /// <summary>
  73. /// Connect all the nodes in a different net to this net
  74. /// </summary>
  75. /// <param name="poNet">node to be added to this net</param>
  76. public void Connect(Net poNet)
  77. {
  78. if (this.NodeCount < poNet.NodeCount)
  79. {
  80. poNet.Connect(this);
  81. return;
  82. }
  83. //DebugDisplayNet();
  84. //DebugDisplayNet(poNet);
  85. foreach(Node oNode in poNet.SourceNodes)
  86. {
  87. this.Connect(oNode);
  88. }
  89. foreach(Node oNode in poNet.SinkNodes)
  90. {
  91. this.Connect(oNode);
  92. }
  93. foreach(Node oNode in poNet.PassthroughNodes)
  94. {
  95. this.Connect(oNode);
  96. }
  97. }
  98. /// <summary>
  99. /// Connect another node to this net
  100. /// </summary>
  101. /// <param name="poNode">node to be added to this net</param>
  102. public void Connect(Node poNode)
  103. {
  104. switch (poNode.NodeFlowType)
  105. {
  106. case NodeFlowType.Source:
  107. oSourceNodes.Add(poNode);
  108. break;
  109. case NodeFlowType.Sink:
  110. oSinkNodes.Add(poNode);
  111. break;
  112. case NodeFlowType.Passthrough:
  113. oPassThroughNodes.Add(poNode);
  114. break;
  115. }
  116. poNode.Net = this;
  117. }
  118. /// <summary>
  119. /// get the number of nodes in this net
  120. /// </summary>
  121. public int NodeCount
  122. {
  123. get
  124. {
  125. return oPassThroughNodes.Count + oSinkNodes.Count + oSourceNodes.Count;
  126. }
  127. }
  128. /// <summary>
  129. /// Used in simulation mode only.
  130. /// Determine if any inputs to this net are unstable or not.
  131. /// </summary>
  132. public SimulationState SimulationStateInput
  133. {
  134. get
  135. {
  136. foreach(Node oNode in oSourceNodes)
  137. {
  138. if (oNode.ParentNodeVector.ParentComponent.SimulationStateOutput == SimulationState.Unstable)
  139. {
  140. //SimulationTraceLog("This net's input node is unstable.",oNode);
  141. return SimulationState.Unstable;
  142. }
  143. }
  144. //SimulationTraceLog("This net's inputs are stable.",null);
  145. return SimulationState.Stable;
  146. }
  147. }
  148. /// <summary>
  149. /// Used in simulation only, get or set the state of the net.
  150. /// Only nets without source nodes may be set, otherwise the source nodes termine the net's state.
  151. /// </summary>
  152. public NodeState NodeState
  153. {
  154. get
  155. {
  156. if (oSourceNodes.Count == 0)
  157. return eNetState;
  158. NodeState eNodeState = NodeState.Tri;
  159. foreach(Node oNode in oSourceNodes)
  160. {
  161. if (oNode.NodeState != NodeState.Tri)
  162. {
  163. if (eNodeState == NodeState.Tri)
  164. eNodeState = oNode.NodeState;
  165. else
  166. {
  167. if (eNodeState != oNode.NodeState)
  168. return NodeState.Undefined;
  169. }
  170. }
  171. }
  172. return eNodeState;
  173. }
  174. set
  175. {
  176. if (oSourceNodes.Count == 0)
  177. {
  178. if (eNetState != value)
  179. {
  180. eNetState = value;
  181. }
  182. }
  183. }
  184. }
  185. /// <summary>
  186. /// Used in Verilog Creation
  187. /// </summary>
  188. /// <param name="poComponent"></param>
  189. /// <returns></returns>
  190. public Node SelectCriticalNode(Component poComponent)
  191. {
  192. foreach(Node oNode in oSourceNodes)
  193. {
  194. if (oNode.ParentNodeVector.ParentComponent == poComponent)
  195. if(oNode.NodeStructure == NetStructure.Connection | oNode.NodeStructure == NetStructure.Input | oNode.NodeStructure == NetStructure.Output)
  196. return oNode;
  197. }
  198. foreach(Node oNode in oSinkNodes)
  199. {
  200. if (oNode.ParentNodeVector.ParentComponent == poComponent)
  201. if(oNode.NodeStructure == NetStructure.Connection | oNode.NodeStructure == NetStructure.Input | oNode.NodeStructure == NetStructure.Output)
  202. return oNode;
  203. }
  204. foreach(Node oNode in oPassThroughNodes)
  205. {
  206. if (oNode.ParentNodeVector.ParentComponent == poComponent)
  207. if(oNode.NodeStructure == NetStructure.Connection | oNode.NodeStructure == NetStructure.Input | oNode.NodeStructure == NetStructure.Output)
  208. return oNode;
  209. }
  210. return null;
  211. }
  212. /// <summary>
  213. /// used for verilog generation, return nodes from thsi net matching a criteria
  214. /// </summary>
  215. /// <param name="poComponent">select only nodes from this component</param>
  216. /// <param name="peNetStructure">select only nodes of this structure type</param>
  217. /// <returns>list of nodes from this net</returns>
  218. public System.Collections.ArrayList SelectNodes(Component poComponent, NetStructure peNetStructure)
  219. {
  220. System.Collections.ArrayList oResult = new System.Collections.ArrayList();
  221. foreach(Node oNode in oSourceNodes)
  222. {
  223. if (oNode.ParentNodeVector.ParentComponent == poComponent & oNode.NodeStructure == peNetStructure)
  224. oResult.Add(oNode);
  225. }
  226. foreach(Node oNode in oSinkNodes)
  227. {
  228. if (oNode.ParentNodeVector.ParentComponent == poComponent & oNode.NodeStructure == peNetStructure)
  229. oResult.Add(oNode);
  230. }
  231. foreach(Node oNode in oPassThroughNodes)
  232. {
  233. if (oNode.ParentNodeVector.ParentComponent == poComponent & oNode.NodeStructure == peNetStructure)
  234. oResult.Add(oNode);
  235. }
  236. return oResult;
  237. }
  238. /// <summary>
  239. /// used for verilog generation, return nodes from this net matching a criteria
  240. /// </summary>
  241. /// <param name="poComponent">select only nodes from this component</param>
  242. /// <returns>list of nodes from this net</returns>
  243. public System.Collections.ArrayList SelectNodes(Component poComponent)
  244. {
  245. System.Collections.ArrayList oResult = new System.Collections.ArrayList();
  246. foreach(Node oNode in oSourceNodes)
  247. {
  248. if (oNode.ParentNodeVector.ParentComponent == poComponent)
  249. oResult.Add(oNode);
  250. }
  251. foreach(Node oNode in oSinkNodes)
  252. {
  253. if (oNode.ParentNodeVector.ParentComponent == poComponent)
  254. oResult.Add(oNode);
  255. }
  256. foreach(Node oNode in oPassThroughNodes)
  257. {
  258. if (oNode.ParentNodeVector.ParentComponent == poComponent)
  259. oResult.Add(oNode);
  260. }
  261. return oResult;
  262. }
  263. /// <summary>
  264. /// return the output state of this net, used for simulation
  265. /// </summary>
  266. public SimulationState SimulationStateOutput
  267. {
  268. get{return eSimulationStateOutput;}
  269. }
  270. /// <summary>
  271. /// ArrayList of nodes that are neither sources nor sinks, but passthrough conduits only
  272. /// </summary>
  273. public System.Collections.ArrayList PassthroughNodes
  274. {
  275. get {return oPassThroughNodes;}
  276. }
  277. /// <summary>
  278. /// Arraylist of nodes that are sources in this net. Note, if using tristates, you may have more than one source.
  279. /// </summary>
  280. public System.Collections.ArrayList SourceNodes
  281. {
  282. get {return oSourceNodes;}
  283. }
  284. /// <summary>
  285. /// Arraylist of nodes that are sinks, or consumers, of this net.
  286. /// </summary>
  287. public System.Collections.ArrayList SinkNodes
  288. {
  289. get {return oSinkNodes;}
  290. }
  291. /// <summary>
  292. /// used by simulation to mark this network as unstable
  293. /// </summary>
  294. public void SimulationDestabilizeNet()
  295. {
  296. // if net output is already unstable...
  297. // we only need to cancel any scheduled stabilization event
  298. if (eSimulationStateOutput == SimulationState.Unstable)
  299. {
  300. SimulationTraceLog("net is already unstable",null);
  301. // cancel stabilization event
  302. if (oEventNodeStabilize != null)
  303. oRapidHardware.Simulation.Clock.UnlinkNode(oEventNodeStabilize);
  304. oEventNodeStabilize = null;
  305. return;
  306. }
  307. // otherwise, we were a net stable,
  308. // we need to alert sink nodes in the net that we are now unstable
  309. eSimulationStateOutput = SimulationState.Unstable;
  310. int i = 1;
  311. foreach(Node oNode in oSinkNodes)
  312. {
  313. Component oComponent = oNode.ParentNodeVector.ParentComponent;
  314. if (!oComponent.RegisteredComponent)
  315. {
  316. SimulationTraceLog("Destabilizing Component {" + oNode.ParentNodeVector.ParentComponent.HirarchicalName + "} from Net via Node, loop " + i.ToString() + " of " + oSinkNodes.Count.ToString(), oNode);
  317. oComponent.SimulationDestabilizeComponent();
  318. }
  319. }
  320. }
  321. /// <summary>
  322. /// used by simulation to mark this net as stable
  323. /// </summary>
  324. public void SimulationStabilizeNet()
  325. {
  326. // should never call this when node is already stable
  327. System.Diagnostics.Debug.Assert(eSimulationStateOutput != SimulationState.Stable);
  328. // debug trace stabililzation event
  329. if (bTrace)
  330. {
  331. if (oTraceList.Contains("stabilize"))
  332. {
  333. System.Console.Write("Break for {stabilize} " + this.NodeState + " - " + this.NetName + "\n");
  334. oRapidHardware.SystemInterface.ListAll();
  335. System.Diagnostics.Debugger.Break();
  336. }
  337. }
  338. // check to see if the inputs are all stable
  339. if (this.SimulationStateInput != SimulationState.Stable)
  340. {
  341. return; // unstable inputs mean unstable net
  342. }
  343. // if there is no propagation delay, immediately stabilize output too
  344. // but, if there is a propagation delay, schedule stabilization event on clock
  345. // hack: hardcoded propagation delay, try to fix hold time failures on registers
  346. if (dPropagationDelay == 0)
  347. {
  348. SimulationStabilizeNetOutputEvent(0);
  349. //dPropagationDelay = (1.0 / (double)oRapidHardware.Simulation.Clock.Frequency * .01);
  350. }
  351. else
  352. {
  353. if (oEventNodeStabilize != null)
  354. oRapidHardware.Simulation.Clock.UnlinkNode(oEventNodeStabilize);
  355. oEventNodeStabilize = oRapidHardware.Simulation.Clock.ScheduleClockEvent(dPropagationDelay,this.SimulationStabilizeNetOutputEvent);
  356. }
  357. }
  358. /// <summary>
  359. /// simulation event delegate, stabilize the net at specified time
  360. /// </summary>
  361. /// <param name="pdTimeNow">time (after delay) when stabilization event is scheduled in event clock</param>
  362. public void SimulationStabilizeNetOutputEvent(double pdTimeNow)
  363. {
  364. SimulationTraceLog("SimulationSabilizeComponentOutputEvent at time " + pdTimeNow.ToString() + "/" + oRapidHardware.Simulation.Clock.TimeNow.ToString() ,null);
  365. // if oEventNode is not null when calling directly, then there is a fundamental scheduling problem
  366. System.Diagnostics.Debug.Assert(oEventNodeStabilize == null & pdTimeNow == 0 | pdTimeNow != 0,"Phantom EventNodeStabilize event scheduled in Net object!");
  367. // should never call this event if node is already stable
  368. System.Diagnostics.Debug.Assert(eSimulationStateOutput != SimulationState.Stable,"Net stabilization event called when net is already stable!");
  369. eSimulationStateOutput = SimulationState.Stable;
  370. int i = 1;
  371. foreach(Node oNode in oSinkNodes)
  372. {
  373. Component oComponent = oNode.ParentNodeVector.ParentComponent;
  374. if (!oComponent.RegisteredComponent)
  375. {
  376. SimulationTraceLog("Stabilizing Component {" + oNode.ParentNodeVector.ParentComponent.HirarchicalName + "} from Net via Node, loop " + i.ToString() + " of " + oSinkNodes.Count.ToString(), oNode);
  377. oComponent.SimulationStabilizeComponent();
  378. }
  379. i++;
  380. }
  381. }
  382. /// <summary>
  383. /// Log the simulation state variables of a particular node
  384. /// </summary>
  385. /// <param name="psLogEntry">information is added to this input string</param>
  386. /// <param name="poNode">state data of this node is logged</param>
  387. private void SimulationTraceLog(string psLogEntry, Node poNode)
  388. {
  389. string sLogEntry = "Net: ";
  390. sLogEntry += psLogEntry;
  391. if (poNode != null)
  392. sLogEntry += " {Node: " + poNode.ParentNodeVector.ParentComponent.HirarchicalName.ToString() + "." + poNode.Name + " = '" + poNode.NodeState.ToString() + "'}";
  393. oRapidHardware.InternalLog.Log(LogType.SimulationTrace,sLogEntry);
  394. }
  395. /// <summary>
  396. ///
  397. /// </summary>
  398. /// <param name="psLabel"></param>
  399. public void SetTrace(string psLabel)
  400. {
  401. if (!bTrace)
  402. {
  403. bTrace = true;
  404. oTraceList = new System.Collections.ArrayList();
  405. }
  406. if (oTraceList.Contains(psLabel))
  407. return;
  408. oTraceList.Add(psLabel);
  409. }
  410. /// <summary>
  411. /// returns the connections of the structure of this network,
  412. /// using source hirarchical names
  413. /// </summary>
  414. public string NetName
  415. {
  416. get
  417. {
  418. string sName = "";
  419. Node oNode;
  420. if (oSinkNodes.Count > 0)
  421. {
  422. oNode = (Node)oSinkNodes[0];
  423. sName += oNode.HirarchicalName;
  424. }
  425. sName += "<=";
  426. if (oSourceNodes.Count > 0)
  427. {
  428. oNode = (Node)oSourceNodes[0];
  429. sName += oNode.HirarchicalName;
  430. }
  431. return sName;
  432. }
  433. }
  434. /// <summary>
  435. /// used only for simulation,
  436. /// force the state of all nodes in this net
  437. /// </summary>
  438. /// <param name="pNodeState">state to force</param>
  439. public void ForceNodeState(NodeState pNodeState)
  440. {
  441. if (this.NodeState == pNodeState)
  442. return;
  443. this.NodeState = pNodeState;
  444. if (this.NodeState == pNodeState)
  445. return;
  446. foreach (Node oNode in SourceNodes)
  447. {
  448. oNode.NodeState = pNodeState;
  449. }
  450. }
  451. /// <summary>
  452. /// check to see if a node belongs to this net
  453. /// </summary>
  454. /// <param name="poNode">node we are seeking</param>
  455. /// <returns>true if the node belongs to this net</returns>
  456. public bool ContainsNode(Node poNode)
  457. {
  458. foreach (Node oNode in oSourceNodes)
  459. {
  460. if (oNode == poNode)
  461. return true;
  462. }
  463. foreach (Node oNode in oSinkNodes)
  464. {
  465. if (oNode == poNode)
  466. return true;
  467. }
  468. foreach (Node oNode in oPassThroughNodes)
  469. {
  470. if (oNode == poNode)
  471. return true;
  472. }
  473. return false;
  474. }
  475. }
  476. }