fastforward_performance_manager.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #include "fastforward_performance_manager.h"
  2. #include "simulator.h"
  3. #include "config.hpp"
  4. #include "thread.h"
  5. #include "hooks_manager.h"
  6. #include "core_manager.h"
  7. #include "performance_model.h"
  8. #include "fastforward_performance_model.h"
  9. FastForwardPerformanceManager *
  10. FastForwardPerformanceManager::create(void)
  11. {
  12. String model = Sim()->getCfg()->getString("perf_model/fast_forward/model");
  13. if (model == "none")
  14. return NULL;
  15. else if (model == "oneipc")
  16. return new FastForwardPerformanceManager();
  17. else
  18. LOG_PRINT_ERROR("Unknown fast-forward performance model %s", model.c_str());
  19. }
  20. FastForwardPerformanceManager::FastForwardPerformanceManager()
  21. : m_sync_interval(SubsecondTime::NS(Sim()->getCfg()->getInt("perf_model/fast_forward/oneipc/interval")))
  22. , m_enabled(false)
  23. , m_target_sync_time(SubsecondTime::Zero())
  24. {
  25. Sim()->getHooksManager()->registerHook(HookType::HOOK_INSTR_COUNT, FastForwardPerformanceManager::hook_instr_count, (UInt64)this);
  26. Sim()->getHooksManager()->registerHook(HookType::HOOK_PERIODIC, FastForwardPerformanceManager::hook_periodic, (UInt64)this);
  27. }
  28. void
  29. FastForwardPerformanceManager::enable()
  30. {
  31. m_enabled = true;
  32. for (UInt32 i = 0; i < Sim()->getConfig()->getTotalCores(); i++)
  33. Sim()->getCoreManager()->getCoreFromID(i)->enablePerformanceModels();
  34. Sim()->getClockSkewMinimizationServer()->setFastForward(true);
  35. // Make sure all threads are released, as the barrier has just changed from per-core to per-HW-context mode
  36. Sim()->getClockSkewMinimizationServer()->release();
  37. step();
  38. }
  39. void
  40. FastForwardPerformanceManager::disable()
  41. {
  42. m_enabled = false;
  43. SubsecondTime barrier_next = SubsecondTime::Zero();
  44. SubsecondTime core_last = SubsecondTime::MaxTime();
  45. for(unsigned int core_id = 0; core_id < Sim()->getConfig()->getApplicationCores(); ++core_id)
  46. {
  47. Core *core = Sim()->getCoreManager()->getCoreFromID(core_id);
  48. core->disablePerformanceModels(); // Probably someone else will turn them on again soon, but let's do this anyway
  49. core->getPerformanceModel()->setFastForward(false);
  50. core->disableInstructionsCallback();
  51. if (core->getThread() && Sim()->getThreadManager()->isThreadRunning(core->getThread()->getId()))
  52. {
  53. barrier_next = std::max(barrier_next, core->getPerformanceModel()->getElapsedTime());
  54. core_last = std::min(core_last, core->getPerformanceModel()->getElapsedTime());
  55. }
  56. }
  57. Sim()->getClockSkewMinimizationServer()->setFastForward(false, barrier_next);
  58. // If some threads were behind but still caught the barrier (everyone does in fast-forward mode),
  59. // make sure to release them so they have a chance to make progress and hit the barrier again at the proper time.
  60. Sim()->getClockSkewMinimizationServer()->release();
  61. }
  62. void
  63. FastForwardPerformanceManager::periodic(SubsecondTime time)
  64. {
  65. if (m_enabled)
  66. {
  67. step();
  68. }
  69. }
  70. void
  71. FastForwardPerformanceManager::instr_count(core_id_t core_id)
  72. {
  73. if (m_enabled)
  74. {
  75. Sim()->getCoreManager()->getCoreFromID(core_id)->getClockSkewMinimizationClient()->synchronize(SubsecondTime::Zero(), true);
  76. if (!Sim()->isRunning())
  77. {
  78. // Main thread has exited, but we still seem to be running.
  79. // Don't touch any more simulator structure as they're being deallocated right now.
  80. // Just wait here until the whole application terminates us.
  81. while(1)
  82. sched_yield();
  83. }
  84. }
  85. }
  86. void
  87. FastForwardPerformanceManager::step()
  88. {
  89. // Approximate time we want to leave fastforward mode
  90. m_target_sync_time = Sim()->getClockSkewMinimizationServer()->getGlobalTime() + m_sync_interval;
  91. SubsecondTime barrier_next = SubsecondTime::Zero();
  92. for(unsigned int core_id = 0; core_id < Sim()->getConfig()->getApplicationCores(); ++core_id)
  93. {
  94. PerformanceModel *perf = Sim()->getCoreManager()->getCoreFromID(core_id)->getPerformanceModel();
  95. perf->setFastForward(true);
  96. barrier_next = std::max(barrier_next, perf->getElapsedTime());
  97. recalibrateInstructionsCallback(core_id);
  98. }
  99. // Set barrier to fastforward, and update next_barrier_time to the maximum of all core times so we definitely release everyone
  100. Sim()->getClockSkewMinimizationServer()->setFastForward(true, barrier_next);
  101. }
  102. void
  103. FastForwardPerformanceManager::recalibrateInstructionsCallback(core_id_t core_id)
  104. {
  105. Core *core = Sim()->getCoreManager()->getCoreFromID(core_id);
  106. SubsecondTime now = core->getPerformanceModel()->getElapsedTime();
  107. if (now > m_target_sync_time)
  108. {
  109. // Just a single instruction so we call into the barrier immediately
  110. core->setInstructionsCallback(1);
  111. }
  112. else
  113. {
  114. // One IPC
  115. SubsecondTime cpi = Sim()->getCoreManager()->getCoreFromID(core_id)->getDvfsDomain()->getPeriod();
  116. UInt64 ninstrs = SubsecondTime::divideRounded(m_target_sync_time - now, cpi);
  117. core->getPerformanceModel()->getFastforwardPerformanceModel()->setCurrentCPI(cpi);
  118. core->setInstructionsCallback(ninstrs);
  119. }
  120. }