dvfs_manager.cc 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include <cassert>
  2. #include "dvfs_manager.h"
  3. #include "simulator.h"
  4. #include "core_manager.h"
  5. #include "core.h"
  6. #include "performance_model.h"
  7. #include "instruction.h"
  8. #include "log.h"
  9. #include "config.hpp"
  10. DvfsManager::DvfsManager()
  11. {
  12. m_num_app_cores = Config::getSingleton()->getApplicationCores();
  13. m_cores_per_socket = Sim()->getCfg()->getInt("dvfs/simple/cores_per_socket");
  14. m_transition_latency = SubsecondTime::NS() * Sim()->getCfg()->getInt("dvfs/transition_latency");
  15. LOG_ASSERT_ERROR("simple" == Sim()->getCfg()->getString("dvfs/type"), "Currently, only this simple dvfs scheme is defined");
  16. // Initial configuration provides for socket-wide frequency control, with [dvfs/simple/cores_per_socket] cores per socket
  17. m_num_proc_domains = m_num_app_cores / m_cores_per_socket;
  18. if (m_num_app_cores % m_cores_per_socket != 0)
  19. {
  20. // Round up if necessary
  21. m_num_proc_domains++;
  22. }
  23. float core_frequency = Sim()->getCfg()->getFloat("perf_model/core/frequency");
  24. // Create a domain, converting from GHz frequencies specified in the configuration to Hz
  25. ComponentPeriod core_period = ComponentPeriod::fromFreqHz(core_frequency*1000000000);
  26. // Allocate m_num_proc_domains clock domains, each with core_period as the initial frequency/period
  27. app_proc_domains.resize(m_num_proc_domains, core_period);
  28. // Allow per-core initial frequency overrides
  29. for(unsigned int i = 0; i < m_num_app_cores; ++i)
  30. {
  31. float _core_frequency = Sim()->getCfg()->getFloatArray("perf_model/core/frequency", i);
  32. if (_core_frequency != core_frequency) {
  33. app_proc_domains[getCoreDomainId(i)] = ComponentPeriod::fromFreqHz(_core_frequency*1000000000);
  34. printf("Core %d at %.2f GHz (global clock %.2f GHz)\n", i, _core_frequency, core_frequency);
  35. }
  36. }
  37. // Allocate global domains for all other non-application processors
  38. global_domains.resize(DOMAIN_GLOBAL_MAX, core_period);
  39. }
  40. UInt32 DvfsManager::getCoreDomainId(UInt32 core_id)
  41. {
  42. LOG_ASSERT_ERROR(core_id < m_num_app_cores, "Core domain ids are only supported for application process domains");
  43. return core_id / m_cores_per_socket;
  44. }
  45. // core_id, 0-indexed
  46. const ComponentPeriod* DvfsManager::getCoreDomain(UInt32 core_id)
  47. {
  48. if (core_id < m_num_app_cores)
  49. {
  50. return &app_proc_domains[getCoreDomainId(core_id)];
  51. }
  52. else
  53. {
  54. // We currently only support a single non-app domain
  55. return &global_domains[DOMAIN_GLOBAL_DEFAULT];
  56. }
  57. }
  58. const ComponentPeriod* DvfsManager::getGlobalDomain(DvfsGlobalDomain domain_id)
  59. {
  60. LOG_ASSERT_ERROR(UInt32(domain_id) < global_domains.size(),
  61. "Global domain %d requested, only %d exist", domain_id, global_domains.size());
  62. return &global_domains[domain_id];
  63. }
  64. void DvfsManager::setCoreDomain(UInt32 core_id, ComponentPeriod new_freq)
  65. {
  66. if (core_id < m_num_app_cores)
  67. {
  68. if (new_freq.getPeriod() != app_proc_domains[getCoreDomainId(core_id)].getPeriod())
  69. {
  70. /* queue a fake instruction that will account for the transition latency */
  71. PseudoInstruction *i = new DelayInstruction(m_transition_latency, DelayInstruction::DVFS_TRANSITION);
  72. Sim()->getCoreManager()->getCoreFromID(core_id)->getPerformanceModel()->queuePseudoInstruction(i);
  73. }
  74. app_proc_domains[getCoreDomainId(core_id)] = new_freq;
  75. }
  76. else
  77. {
  78. // We currently only support a single non-app domain
  79. LOG_PRINT_ERROR("Cannot change non-core frequency");
  80. }
  81. }