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

/yaAGC/agc_simulator.c

https://github.com/argaldo/iAGC
C | 279 lines | 162 code | 34 blank | 83 comment | 20 complexity | d9166db0cea4df08c3f59b74a1e90ec0 MD5 | raw file
  1. /*
  2. * agc_simulator.c
  3. *
  4. * Created on: Dec 2, 2008
  5. * Author: MZ211D
  6. */
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include <string.h>
  10. #include <unistd.h>
  11. #include <stdlib.h>
  12. #include "yaAGC.h"
  13. #include "agc_cli.h"
  14. #include "agc_engine.h"
  15. #include "agc_symtab.h"
  16. #include "agc_debug.h"
  17. #include "agc_debugger.h"
  18. #include "agc_simulator.h"
  19. /** Declare the singleton Simulator object instance */
  20. static Simulator_t Simulator;
  21. static int SimInitializeEngine(void)
  22. {
  23. int result = 0;
  24. /* Initialize the simulation */
  25. if (!Simulator.Options->debug_dsky)
  26. {
  27. if (Simulator.Options->resume == NULL)
  28. {
  29. if (Simulator.Options->cfg)
  30. {
  31. if (CmOrLm)
  32. {
  33. result = agc_engine_init (&Simulator.State,
  34. Simulator.Options->core, "CM.core", 0);
  35. }
  36. else
  37. {
  38. result = agc_engine_init (&Simulator.State,
  39. Simulator.Options->core, "LM.core", 0);
  40. }
  41. }
  42. else
  43. {
  44. result = agc_engine_init (&Simulator.State,
  45. Simulator.Options->core,"core", 0);
  46. }
  47. }
  48. else
  49. {
  50. result = agc_engine_init (&Simulator.State,
  51. Simulator.Options->core, Simulator.Options->resume, 1);
  52. }
  53. /* Check AGC Engine Init Result and display proper message */
  54. switch (result)
  55. {
  56. case 0:
  57. break; /* All is OK */
  58. case 1:
  59. printf ("Specified core-rope image file not found.\n");
  60. break;
  61. case 2:
  62. printf ("Core-rope image larger than core memory.\n");
  63. break;
  64. case 3:
  65. printf ("Core-rope image file must have even size.\n");
  66. break;
  67. case 5:
  68. printf ("Core-rope image file read error.\n");
  69. break;
  70. default:
  71. printf ("Initialization implementation error.\n");
  72. break;
  73. }
  74. }
  75. return (result);
  76. }
  77. /**
  78. This function executes one cycle of the AGC engine. This is
  79. a wrapper function to eliminate showing the passing of the
  80. current engine state. */
  81. void SimExecuteEngine()
  82. {
  83. agc_engine (&Simulator.State);
  84. }
  85. /**
  86. Initialize the AGC Simulator; this means setting up the debugger, AGC
  87. engine and initializing the simulator time parameters.
  88. */
  89. int SimInitialize(Options_t* Options)
  90. {
  91. int result = 0;
  92. /* Without Options we can't Run */
  93. if (!Options) return(6);
  94. /* Set the basic simulator variables */
  95. Simulator.Options = Options;
  96. Simulator.DebugRules = DebugRules;
  97. Simulator.DumpInterval = Options->dump_time * sysconf (_SC_CLK_TCK);
  98. /* Set legacy Option variables */
  99. Portnum = Options->port;
  100. DebugDsky = Options->debug_dsky;
  101. DebugDeda = Options->debug_deda;
  102. DedaQuiet = Options->deda_quiet;
  103. Simulator.DumpInterval = Simulator.DumpInterval;
  104. SocketInterlaceReload = Options->interlace;
  105. /* If we are not in quiet mode display the version info */
  106. if (!Options->quiet) DbgDisplayVersion();
  107. /* Initialize the AGC Engine */
  108. result = SimInitializeEngine();
  109. /* Initialize the Debugger if running with debug mode */
  110. if(Options->debug) DbgInitialize(Options,&(Simulator.State));
  111. // if (Options->cdu_log)
  112. // {
  113. // extern FILE *CduLog;
  114. // CduLog = fopen (Options->cdu_log, "w");
  115. // }
  116. /* Initialize realtime and cycle counters */
  117. Simulator.RealTimeOffset = times (&Simulator.DummyTime); // The starting time of the program.
  118. Simulator.NextCoreDump = Simulator.RealTimeOffset + Simulator.DumpInterval;
  119. SimSetCycleCount(SIM_CYCLECOUNT_AGC); // Num. of AGC cycles so far.
  120. Simulator.RealTimeOffset -= (Simulator.CycleCount + AGC_PER_SECOND / 2) / AGC_PER_SECOND;
  121. Simulator.LastRealTime = ~0UL;
  122. return (result | Options->version);
  123. }
  124. /**
  125. This function adjusts the Simulator Cycle Count. Either based on the number
  126. of AGC Cycles or incremented during Sim cycles. This functions uses a
  127. mode switch to determine how to set or adjust the Cycle Counter
  128. */
  129. void SimSetCycleCount(int Mode)
  130. {
  131. switch(Mode)
  132. {
  133. case SIM_CYCLECOUNT_AGC:
  134. Simulator.CycleCount = sysconf (_SC_CLK_TCK) * Simulator.State.CycleCounter;
  135. break;
  136. case SIM_CYCLECOUNT_INC:
  137. Simulator.CycleCount += sysconf (_SC_CLK_TCK);
  138. break;
  139. }
  140. }
  141. /**
  142. This function puts the simulator in a sleep state to reduce
  143. CPU usage on the PC.
  144. */
  145. static void SimSleep(void)
  146. {
  147. #ifdef WIN32
  148. Sleep (10);
  149. #else
  150. struct timespec req, rem;
  151. req.tv_sec = 0;
  152. req.tv_nsec = 10000000;
  153. nanosleep (&req, &rem);
  154. #endif
  155. }
  156. /**
  157. This function manages the AGC periodic core dumping of the
  158. AGC state machine.
  159. */
  160. static void SimManageCoreDump(void)
  161. {
  162. /* Check to see if the next core dump should be made */
  163. if (Simulator.RealTime >= Simulator.NextCoreDump)
  164. {
  165. /* Use either specific core dump name (from cfg) or generic */
  166. if (Simulator.Options->cfg)
  167. {
  168. if (CmOrLm) MakeCoreDump (&Simulator.State, "CM.core");
  169. else MakeCoreDump (&Simulator.State, "LM.core");
  170. }
  171. else MakeCoreDump (&Simulator.State, "core");
  172. /* Set the next CoreDump Time based on DumpInterval time */
  173. Simulator.NextCoreDump = Simulator.RealTime + Simulator.DumpInterval;
  174. }
  175. }
  176. /**
  177. * This function is a helper to allow the debugger to update the realtime
  178. */
  179. void SimUpdateTime(void)
  180. {
  181. Simulator.RealTimeOffset +=
  182. ((Simulator.RealTime = times (&Simulator.DummyTime)) - Simulator.LastRealTime);
  183. Simulator.LastRealTime = Simulator.RealTime;
  184. }
  185. /**
  186. This function manages the Simulator time to achieve the
  187. average 11.7 microsecond per opcode execution
  188. */
  189. void SimManageTime(void)
  190. {
  191. Simulator.RealTime = times (&Simulator.DummyTime);
  192. if (Simulator.RealTime != Simulator.LastRealTime)
  193. {
  194. /* Make a routine core dump */
  195. SimManageCoreDump();
  196. // Need to recalculate the number of AGC cycles we're supposed to
  197. // have executed. Notice the trick of multiplying both CycleCount
  198. // and DesiredCycles by CLK_TCK, to avoid a long long division by CLK_TCK.
  199. // This not only reduces overhead, but actually makes the calculation
  200. // more exact. A bit tricky to understand at first glance, though.
  201. Simulator.LastRealTime = Simulator.RealTime;
  202. //DesiredCycles = ((RealTime - RealTimeOffset) * AGC_PER_SECOND) / CLK_TCK;
  203. //DesiredCycles = (RealTime - RealTimeOffset) * AGC_PER_SECOND;
  204. // The calculation is done in the following funky way because if done as in
  205. // the line above, the right-hand side will be done in 32-bit arithmetic
  206. // on a 32-bit CPU, while the left-hand side is 64-bit, and so the calculation
  207. // will overflow and fail after 4 minutes of operation. Done the following
  208. // way, the calculation will always be 64-bit. Making AGC_PER_SECOND a ULL
  209. // constant in agc_engine.h would fix it, but the Orbiter folk wouldn't
  210. // be able to compile it.
  211. Simulator.DesiredCycles = Simulator.RealTime;
  212. Simulator.DesiredCycles -= Simulator.RealTimeOffset;
  213. Simulator.DesiredCycles *= AGC_PER_SECOND;
  214. }
  215. else SimSleep();
  216. }
  217. /**
  218. Execute the simulated CPU. Expecting to ACCURATELY cycle the simulation every
  219. 11.7 microseconds within Linux (or Win32) is a bit too much, I think.
  220. (Not that it's really critical, as long as it looks right from the
  221. user's standpoint.) So I do a trick: I just execute the simulation
  222. often enough to keep up with real-time on the average. AGC time is
  223. measured as the number of machine cycles divided by AGC_PER_SECOND,
  224. while real-time is measured using the times() function. What this mains
  225. is that AGC_PER_SECOND AGC cycles are executed every CLK_TCK clock ticks.
  226. The timing is thus rather rough-and-ready (i.e., I'm sure it can be improved
  227. a lot). It's good enough for me, for NOW, but I'd be happy to take suggestions
  228. for how to improve it in a reasonably portable way.*/
  229. void SimExecute(void)
  230. {
  231. while(1)
  232. {
  233. /* Manage the Simulated Time */
  234. SimManageTime();
  235. while (Simulator.CycleCount < Simulator.DesiredCycles)
  236. {
  237. /* If debugging is enabled run the debugger */
  238. if (Simulator.Options->debug && DbgExecute()) continue;
  239. /* Execute a cyle of the AGC engine */
  240. SimExecuteEngine();
  241. /* Adjust the CycleCount */
  242. SimSetCycleCount(SIM_CYCLECOUNT_INC);
  243. }
  244. }
  245. }