blob: fa63851c59e7a3ee8051ea18868b3e930fe46ea8 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "power_manager.h"
#include "registers.h"
PowerManager::PowerManager(magma::RegisterIo* io)
{
// Initialize current set of running cores.
ReceivedPowerInterrupt(io);
last_check_time_ = std::chrono::steady_clock::now();
}
void PowerManager::EnableCores(magma::RegisterIo* io, uint64_t shader_bitmask)
{
registers::CoreReadyState::WriteState(io, registers::CoreReadyState::CoreType::kShader,
registers::CoreReadyState::ActionType::kActionPowerOn,
shader_bitmask);
registers::CoreReadyState::WriteState(io, registers::CoreReadyState::CoreType::kL2,
registers::CoreReadyState::ActionType::kActionPowerOn, 1);
registers::CoreReadyState::WriteState(io, registers::CoreReadyState::CoreType::kTiler,
registers::CoreReadyState::ActionType::kActionPowerOn, 1);
}
void PowerManager::ReceivedPowerInterrupt(magma::RegisterIo* io)
{
tiler_ready_status_ =
registers::CoreReadyState::ReadBitmask(io, registers::CoreReadyState::CoreType::kTiler,
registers::CoreReadyState::StatusType::kReady);
l2_ready_status_ =
registers::CoreReadyState::ReadBitmask(io, registers::CoreReadyState::CoreType::kL2,
registers::CoreReadyState::StatusType::kReady);
shader_ready_status_ =
registers::CoreReadyState::ReadBitmask(io, registers::CoreReadyState::CoreType::kShader,
registers::CoreReadyState::StatusType::kReady);
}
void PowerManager::UpdateGpuActive(bool active)
{
auto now = std::chrono::steady_clock::now();
std::chrono::steady_clock::duration total_time = now - last_check_time_;
constexpr uint32_t kMemoryMilliseconds = 100;
std::chrono::milliseconds memory_duration(kMemoryMilliseconds);
// Ignore long periods of inactive time.
if (total_time > memory_duration)
total_time = memory_duration;
std::chrono::steady_clock::duration active_time =
gpu_active_ ? total_time : std::chrono::steady_clock::duration(0);
constexpr uint32_t kBucketLengthMilliseconds = 50;
bool coalesced = false;
if (!time_periods_.empty()) {
auto start_time = time_periods_.back().end_time - time_periods_.back().total_time;
if (now - start_time < std::chrono::milliseconds(kBucketLengthMilliseconds)) {
coalesced = true;
time_periods_.back().end_time = now;
time_periods_.back().total_time += total_time;
time_periods_.back().active_time += active_time;
}
}
if (!coalesced)
time_periods_.push_back(TimePeriod{now, total_time, active_time});
while (!time_periods_.empty() && (now - time_periods_.front().end_time > memory_duration)) {
time_periods_.pop_front();
}
last_check_time_ = now;
gpu_active_ = active;
}
void PowerManager::GetGpuActiveInfo(std::chrono::steady_clock::duration* total_time_out,
std::chrono::steady_clock::duration* active_time_out)
{
UpdateGpuActive(gpu_active_);
std::chrono::steady_clock::duration total_time_accumulate(0);
std::chrono::steady_clock::duration active_time_accumulate(0);
for (auto& period : time_periods_) {
total_time_accumulate += period.total_time;
active_time_accumulate += period.active_time;
}
*total_time_out = total_time_accumulate;
*active_time_out = active_time_accumulate;
}