mirror of https://git.citron-emu.org/citron/emu
feat: add CPU clock rate slider to settings
Implement a slider in the CPU settings tab to adjust the BASE_CLOCK_RATE up to 1,785 MHz (Switch's official maximum clock rate). Default remains at 1,020 MHz. This change: - Adds UI slider and spinbox to configure_cpu.ui with range 500-1785 MHz - Makes BASE_CLOCK_RATE dynamic by reading from settings - Modifies WallClock to handle dynamic clock rate changes - Updates APM controller to properly set the clock rate - Changes clock rate settings category from Core to CPU The user can now easily adjust the CPU clock rate to improve performance or manage thermals and power consumption. Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
parent
bbd3253169
commit
278486d059
|
@ -1,10 +1,13 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <memory>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
#include <QSlider>
|
||||
#include "common/common_types.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/settings_enums.h"
|
||||
|
@ -38,7 +41,22 @@ ConfigureCpu::ConfigureCpu(const Core::System& system_,
|
|||
|
||||
ConfigureCpu::~ConfigureCpu() = default;
|
||||
|
||||
void ConfigureCpu::SetConfiguration() {}
|
||||
void ConfigureCpu::SetConfiguration() {
|
||||
// Set clock rate values from settings
|
||||
const u32 clock_rate_mhz = Settings::values.cpu_clock_rate.GetValue() / 1'000'000;
|
||||
ui->clock_rate_slider->setValue(static_cast<int>(clock_rate_mhz));
|
||||
ui->clock_rate_spinbox->setValue(static_cast<int>(clock_rate_mhz));
|
||||
|
||||
// Connect slider and spinbox signals to keep them in sync
|
||||
connect(ui->clock_rate_slider, &QSlider::valueChanged, this, [this](int value) {
|
||||
ui->clock_rate_spinbox->setValue(value);
|
||||
});
|
||||
|
||||
connect(ui->clock_rate_spinbox, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int value) {
|
||||
ui->clock_rate_slider->setValue(value);
|
||||
});
|
||||
}
|
||||
|
||||
void ConfigureCpu::Setup(const ConfigurationShared::Builder& builder) {
|
||||
auto* accuracy_layout = ui->widget_accuracy->layout();
|
||||
auto* backend_layout = ui->widget_backend->layout();
|
||||
|
@ -99,6 +117,9 @@ void ConfigureCpu::ApplyConfiguration() {
|
|||
for (const auto& apply_func : apply_funcs) {
|
||||
apply_func(is_powered_on);
|
||||
}
|
||||
|
||||
// Save the clock rate setting (convert from MHz to Hz)
|
||||
Settings::values.cpu_clock_rate = static_cast<u32>(ui->clock_rate_spinbox->value()) * 1'000'000;
|
||||
}
|
||||
|
||||
void ConfigureCpu::changeEvent(QEvent* event) {
|
||||
|
|
|
@ -126,6 +126,67 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="clock_rate_group">
|
||||
<property name="title">
|
||||
<string>CPU Clock Rate</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_clock_description">
|
||||
<property name="text">
|
||||
<string>CPU clock rate in MHz. Setting a higher clock rate will improve performance but may cause system instability. Default is 1020 MHz.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QSlider" name="clock_rate_slider">
|
||||
<property name="minimum">
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1785</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1020</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="clock_rate_spinbox">
|
||||
<property name="suffix">
|
||||
<string> MHz</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1785</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1020</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -199,6 +199,7 @@ struct Values {
|
|||
MemoryLayout::Memory_12Gb,
|
||||
"memory_layout_mode",
|
||||
Category::Core};
|
||||
SwitchableSetting<u32> cpu_clock_rate{linkage, 1'020'000'000, "cpu_clock_rate", Category::Cpu};
|
||||
SwitchableSetting<bool> use_speed_limit{
|
||||
linkage, true, "use_speed_limit", Category::Core, Specialization::Paired, false, true};
|
||||
SwitchableSetting<u16, true> speed_limit{linkage,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
@ -8,6 +9,7 @@
|
|||
#include <ratio>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hardware_properties.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
|
@ -15,7 +17,10 @@ class WallClock {
|
|||
public:
|
||||
static constexpr u64 CNTFRQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz
|
||||
static constexpr u64 GPUTickFreq = 614'400'000; // GM20B GPU Tick Frequency = 614.4 MHz
|
||||
static constexpr u64 CPUTickFreq = 1'020'000'000; // T210/4 A57 CPU Tick Frequency = 1020.0 MHz
|
||||
// Changed from constexpr to function to get dynamic value from settings
|
||||
static inline u64 CPUTickFreq() {
|
||||
return Core::Hardware::BASE_CLOCK_RATE();
|
||||
} // T210/4 A57 CPU Tick Frequency from settings
|
||||
|
||||
virtual ~WallClock() = default;
|
||||
|
||||
|
@ -76,12 +81,28 @@ protected:
|
|||
using NsToCNTPCTRatio = std::ratio<CNTFRQ, std::nano::den>;
|
||||
using NsToGPUTickRatio = std::ratio<GPUTickFreq, std::nano::den>;
|
||||
|
||||
// Cycle Timing
|
||||
// Cycle Timing - using functions for dynamic values
|
||||
|
||||
using CPUTickToNsRatio = std::ratio<std::nano::den, CPUTickFreq>;
|
||||
using CPUTickToUsRatio = std::ratio<std::micro::den, CPUTickFreq>;
|
||||
using CPUTickToCNTPCTRatio = std::ratio<CNTFRQ, CPUTickFreq>;
|
||||
using CPUTickToGPUTickRatio = std::ratio<GPUTickFreq, CPUTickFreq>;
|
||||
// Update these to use functions instead of constexpr
|
||||
struct CPUTickToNsRatio {
|
||||
static inline std::intmax_t num = std::nano::den;
|
||||
static inline std::intmax_t den = CPUTickFreq();
|
||||
};
|
||||
|
||||
struct CPUTickToUsRatio {
|
||||
static inline std::intmax_t num = std::micro::den;
|
||||
static inline std::intmax_t den = CPUTickFreq();
|
||||
};
|
||||
|
||||
struct CPUTickToCNTPCTRatio {
|
||||
static inline std::intmax_t num = CNTFRQ;
|
||||
static inline std::intmax_t den = CPUTickFreq();
|
||||
};
|
||||
|
||||
struct CPUTickToGPUTickRatio {
|
||||
static inline std::intmax_t num = GPUTickFreq;
|
||||
static inline std::intmax_t den = CPUTickFreq();
|
||||
};
|
||||
};
|
||||
|
||||
std::unique_ptr<WallClock> CreateOptimalClock();
|
||||
|
|
|
@ -9,12 +9,13 @@
|
|||
|
||||
#include "common/bit_util.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/settings.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
namespace Hardware {
|
||||
|
||||
constexpr u64 BASE_CLOCK_RATE = 1'020'000'000; // Default CPU Frequency = 1020 MHz
|
||||
inline u64 BASE_CLOCK_RATE() { return Settings::values.cpu_clock_rate.GetValue(); } // Default CPU Frequency set in settings, defaults to 1020 MHz
|
||||
constexpr u64 CNTFREQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz
|
||||
constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -81,8 +82,8 @@ PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(Performa
|
|||
|
||||
void Controller::SetClockSpeed(u32 mhz) {
|
||||
LOG_DEBUG(Service_APM, "called, mhz={:08X}", mhz);
|
||||
// TODO(DarkLordZach): Actually signal core_timing to change clock speed.
|
||||
// TODO(Rodrigo): Remove [[maybe_unused]] when core_timing is used.
|
||||
// Update the clock rate setting with the provided MHz value (convert to Hz)
|
||||
Settings::values.cpu_clock_rate = mhz * 1'000'000;
|
||||
}
|
||||
|
||||
} // namespace Service::APM
|
||||
|
|
Loading…
Reference in New Issue