magic_server.cc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #include "magic_server.h"
  2. #include "sim_api.h"
  3. #include "simulator.h"
  4. #include "thread_manager.h"
  5. #include "logmem.h"
  6. #include "performance_model.h"
  7. #include "fastforward_performance_model.h"
  8. #include "core_manager.h"
  9. #include "dvfs_manager.h"
  10. #include "hooks_manager.h"
  11. #include "stats.h"
  12. #include "timer.h"
  13. #include "thread.h"
  14. MagicServer::MagicServer()
  15. : m_performance_enabled(false)
  16. {
  17. }
  18. MagicServer::~MagicServer()
  19. { }
  20. UInt64 MagicServer::Magic(thread_id_t thread_id, core_id_t core_id, UInt64 cmd, UInt64 arg0, UInt64 arg1)
  21. {
  22. ScopedLock sl(Sim()->getThreadManager()->getLock());
  23. return Magic_unlocked(thread_id, core_id, cmd, arg0, arg1);
  24. }
  25. UInt64 MagicServer::Magic_unlocked(thread_id_t thread_id, core_id_t core_id, UInt64 cmd, UInt64 arg0, UInt64 arg1)
  26. {
  27. switch(cmd)
  28. {
  29. case SIM_CMD_ROI_TOGGLE:
  30. if (Sim()->getConfig()->getSimulationROI() == Config::ROI_MAGIC)
  31. {
  32. return setPerformance(! m_performance_enabled);
  33. }
  34. else
  35. {
  36. return 0;
  37. }
  38. case SIM_CMD_ROI_START:
  39. Sim()->getHooksManager()->callHooks(HookType::HOOK_APPLICATION_ROI_BEGIN, 0);
  40. if (Sim()->getConfig()->getSimulationROI() == Config::ROI_MAGIC)
  41. {
  42. return setPerformance(true);
  43. }
  44. else
  45. {
  46. return 0;
  47. }
  48. case SIM_CMD_ROI_END:
  49. Sim()->getHooksManager()->callHooks(HookType::HOOK_APPLICATION_ROI_END, 0);
  50. if (Sim()->getConfig()->getSimulationROI() == Config::ROI_MAGIC)
  51. {
  52. return setPerformance(false);
  53. }
  54. else
  55. {
  56. return 0;
  57. }
  58. case SIM_CMD_MHZ_SET:
  59. return setFrequency(arg0, arg1);
  60. case SIM_CMD_NAMED_MARKER:
  61. {
  62. char str[256];
  63. Core *core = Sim()->getCoreManager()->getCoreFromID(core_id);
  64. core->accessMemory(Core::NONE, Core::READ, arg1, str, 256, Core::MEM_MODELED_NONE);
  65. str[255] = '\0';
  66. MagicMarkerType args = { thread_id: thread_id, core_id: core_id, arg0: arg0, arg1: 0, str: str };
  67. Sim()->getHooksManager()->callHooks(HookType::HOOK_MAGIC_MARKER, (UInt64)&args);
  68. return 0;
  69. }
  70. case SIM_CMD_SET_THREAD_NAME:
  71. {
  72. char str[256];
  73. Core *core = Sim()->getCoreManager()->getCoreFromID(core_id);
  74. core->accessMemory(Core::NONE, Core::READ, arg0, str, 256, Core::MEM_MODELED_NONE);
  75. str[255] = '\0';
  76. Sim()->getStatsManager()->logEvent(StatsManager::EVENT_THREAD_NAME, SubsecondTime::MaxTime(), core_id, thread_id, 0, 0, str);
  77. Sim()->getThreadManager()->getThreadFromID(thread_id)->setName(str);
  78. return 0;
  79. }
  80. case SIM_CMD_MARKER:
  81. {
  82. MagicMarkerType args = { thread_id: thread_id, core_id: core_id, arg0: arg0, arg1: arg1, str: NULL };
  83. Sim()->getHooksManager()->callHooks(HookType::HOOK_MAGIC_MARKER, (UInt64)&args);
  84. return 0;
  85. }
  86. case SIM_CMD_USER:
  87. {
  88. MagicMarkerType args = { thread_id: thread_id, core_id: core_id, arg0: arg0, arg1: arg1, str: NULL };
  89. return Sim()->getHooksManager()->callHooks(HookType::HOOK_MAGIC_USER, (UInt64)&args, true /* expect return value */);
  90. }
  91. case SIM_CMD_INSTRUMENT_MODE:
  92. return setInstrumentationMode(arg0);
  93. case SIM_CMD_MHZ_GET:
  94. return getFrequency(arg0);
  95. default:
  96. LOG_ASSERT_ERROR(false, "Got invalid Magic %lu, arg0(%lu) arg1(%lu)", cmd, arg0, arg1);
  97. }
  98. return 0;
  99. }
  100. UInt64 MagicServer::getGlobalInstructionCount(void)
  101. {
  102. UInt64 ninstrs = 0;
  103. for (UInt32 i = 0; i < Sim()->getConfig()->getApplicationCores(); i++)
  104. ninstrs += Sim()->getCoreManager()->getCoreFromID(i)->getInstructionCount();
  105. return ninstrs;
  106. }
  107. static Timer t_start;
  108. UInt64 ninstrs_start;
  109. __attribute__((weak)) void PinDetach(void) {}
  110. void MagicServer::enablePerformance()
  111. {
  112. Sim()->getStatsManager()->recordStats("roi-begin");
  113. ninstrs_start = getGlobalInstructionCount();
  114. t_start.start();
  115. Simulator::enablePerformanceModels();
  116. Sim()->setInstrumentationMode(InstMode::inst_mode_roi, true /* update_barrier */);
  117. }
  118. void MagicServer::disablePerformance()
  119. {
  120. Simulator::disablePerformanceModels();
  121. Sim()->getStatsManager()->recordStats("roi-end");
  122. float seconds = t_start.getTime() / 1e9;
  123. UInt64 ninstrs = getGlobalInstructionCount() - ninstrs_start;
  124. UInt64 cycles = SubsecondTime::divideRounded(Sim()->getClockSkewMinimizationServer()->getGlobalTime(),
  125. Sim()->getCoreManager()->getCoreFromID(0)->getDvfsDomain()->getPeriod());
  126. printf("[SNIPER] Simulated %.1fM instructions, %.1fM cycles, %.2f IPC\n",
  127. ninstrs / 1e6,
  128. cycles / 1e6,
  129. float(ninstrs) / (cycles ? cycles : 1));
  130. printf("[SNIPER] Simulation speed %.1f KIPS (%.1f KIPS / target core - %.1fns/instr)\n",
  131. ninstrs / seconds / 1e3,
  132. ninstrs / seconds / 1e3 / Sim()->getConfig()->getApplicationCores(),
  133. seconds * 1e9 / (float(ninstrs ? ninstrs : 1.) / Sim()->getConfig()->getApplicationCores()));
  134. PerformanceModel *perf = Sim()->getCoreManager()->getCoreFromID(0)->getPerformanceModel();
  135. if (perf->getFastforwardPerformanceModel()->getFastforwardedTime() > SubsecondTime::Zero())
  136. {
  137. // NOTE: Prints out the non-idle ratio for core 0 only, but it's just indicative anyway
  138. double ff_ratio = double(perf->getFastforwardPerformanceModel()->getFastforwardedTime().getNS())
  139. / double(perf->getNonIdleElapsedTime().getNS());
  140. double percent_detailed = 100. * (1. - ff_ratio);
  141. printf("[SNIPER] Sampling: executed %.2f%% of simulated time in detailed mode\n", percent_detailed);
  142. }
  143. fflush(NULL);
  144. Sim()->setInstrumentationMode(InstMode::inst_mode_end, true /* update_barrier */);
  145. PinDetach();
  146. }
  147. void print_allocations();
  148. UInt64 MagicServer::setPerformance(bool enabled)
  149. {
  150. if (m_performance_enabled == enabled)
  151. return 1;
  152. m_performance_enabled = enabled;
  153. //static bool enabled = false;
  154. static Timer t_start;
  155. //ScopedLock sl(l_alloc);
  156. if (m_performance_enabled)
  157. {
  158. printf("[SNIPER] Enabling performance models\n");
  159. fflush(NULL);
  160. t_start.start();
  161. logmem_enable(true);
  162. Sim()->getHooksManager()->callHooks(HookType::HOOK_ROI_BEGIN, 0);
  163. }
  164. else
  165. {
  166. Sim()->getHooksManager()->callHooks(HookType::HOOK_ROI_END, 0);
  167. printf("[SNIPER] Disabling performance models\n");
  168. float seconds = t_start.getTime() / 1e9;
  169. printf("[SNIPER] Leaving ROI after %.2f seconds\n", seconds);
  170. fflush(NULL);
  171. logmem_enable(false);
  172. logmem_write_allocations();
  173. }
  174. if (enabled)
  175. enablePerformance();
  176. else
  177. disablePerformance();
  178. return 0;
  179. }
  180. UInt64 MagicServer::setFrequency(UInt64 core_number, UInt64 freq_in_mhz)
  181. {
  182. UInt32 num_cores = Sim()->getConfig()->getApplicationCores();
  183. UInt64 freq_in_hz;
  184. if (core_number >= num_cores)
  185. return 1;
  186. freq_in_hz = 1000000 * freq_in_mhz;
  187. printf("[SNIPER] Setting frequency for core %" PRId64 " in DVFS domain %d to %" PRId64 " MHz\n", core_number, Sim()->getDvfsManager()->getCoreDomainId(core_number), freq_in_mhz);
  188. if (freq_in_hz > 0)
  189. Sim()->getDvfsManager()->setCoreDomain(core_number, ComponentPeriod::fromFreqHz(freq_in_hz));
  190. else {
  191. Sim()->getThreadManager()->stallThread_async(core_number, ThreadManager::STALL_BROKEN, SubsecondTime::MaxTime());
  192. Sim()->getCoreManager()->getCoreFromID(core_number)->setState(Core::BROKEN);
  193. }
  194. // First set frequency, then call hooks so hook script can find the new frequency by querying the DVFS manager
  195. Sim()->getHooksManager()->callHooks(HookType::HOOK_CPUFREQ_CHANGE, core_number);
  196. return 0;
  197. }
  198. UInt64 MagicServer::getFrequency(UInt64 core_number)
  199. {
  200. UInt32 num_cores = Sim()->getConfig()->getApplicationCores();
  201. if (core_number >= num_cores)
  202. return UINT64_MAX;
  203. const ComponentPeriod *per = Sim()->getDvfsManager()->getCoreDomain(core_number);
  204. return per->getPeriodInFreqMHz();
  205. }
  206. UInt64 MagicServer::setInstrumentationMode(UInt64 sim_api_opt)
  207. {
  208. InstMode::inst_mode_t inst_mode;
  209. switch (sim_api_opt)
  210. {
  211. case SIM_OPT_INSTRUMENT_DETAILED:
  212. inst_mode = InstMode::DETAILED;
  213. break;
  214. case SIM_OPT_INSTRUMENT_WARMUP:
  215. inst_mode = InstMode::CACHE_ONLY;
  216. break;
  217. case SIM_OPT_INSTRUMENT_FASTFORWARD:
  218. inst_mode = InstMode::FAST_FORWARD;
  219. break;
  220. default:
  221. LOG_PRINT_ERROR("Unexpected magic instrument opt type: %lx.", sim_api_opt);
  222. }
  223. Sim()->setInstrumentationMode(inst_mode, true /* update_barrier */);
  224. return 0;
  225. }