Hook up KTimer to scheduler

This commit is contained in:
wheremyfoodat 2024-01-22 04:04:05 +02:00
parent fa82dad38d
commit 0be099d1ea
7 changed files with 96 additions and 27 deletions

View file

@ -126,7 +126,7 @@ class CPU {
Emulator& emu;
public:
static constexpr u64 ticksPerSec = 268111856;
static constexpr u64 ticksPerSec = Scheduler::arm11Clock;
CPU(Memory& mem, Kernel& kernel, Emulator& emu);
void reset();
@ -175,6 +175,10 @@ class CPU {
return scheduler.currentTimestamp;
}
Scheduler& getScheduler() {
return scheduler;
}
void clearCache() { jit->ClearCache(); }
void runFrame();
};

View file

@ -70,6 +70,7 @@ public:
Handle makeMutex(bool locked = false); // Needs to be public to be accessible to the APT/DSP services
Handle makeSemaphore(u32 initialCount, u32 maximumCount); // Needs to be public to be accessible to the service manager port
Handle makeTimer(ResetType resetType);
void pollTimers();
// Signals an event, returns true on success or false if the event does not exist
bool signalEvent(Handle e);
@ -94,7 +95,6 @@ public:
void releaseMutex(Mutex* moo);
void cancelTimer(Timer* timer);
void signalTimer(Handle timerHandle, Timer* timer);
void updateTimer(Handle timerHandle, Timer* timer);
// Wake up the thread with the highest priority out of all threads in the waitlist
// Returns the index of the woken up thread

View file

@ -177,13 +177,12 @@ struct Timer {
u64 waitlist; // Refer to the getWaitlist function below for documentation
ResetType resetType = ResetType::OneShot;
u64 startTick; // CPU tick the timer started
u64 currentDelay; // Number of ns until the timer fires next time
u64 fireTick; // CPU tick the timer will be fired
u64 interval; // Number of ns until the timer fires for the second and future times
bool fired; // Has this timer been signalled?
bool running; // Is this timer running or stopped?
Timer(ResetType type) : resetType(type), startTick(0), currentDelay(0), interval(0), waitlist(0), fired(false), running(false) {}
Timer(ResetType type) : resetType(type), fireTick(0), interval(0), waitlist(0), fired(false), running(false) {}
};
struct MemoryBlock {

View file

@ -5,14 +5,17 @@
#include <ranges>
#include "helpers.hpp"
#include "logger.hpp"
struct Scheduler {
enum class EventType {
VBlank = 0, // End of frame event
Panic = 1, // Dummy event that is always pending and should never be triggered (Timestamp = UINT64_MAX)
UpdateTimers = 1, // Update kernel timer objects
Panic = 2, // Dummy event that is always pending and should never be triggered (Timestamp = UINT64_MAX)
TotalNumberOfEvents // How many event types do we have in total?
};
static constexpr usize totalNumberOfEvents = static_cast<usize>(EventType::TotalNumberOfEvents);
static constexpr u64 arm11Clock = 268111856;
template <typename Key, typename Val, usize size>
using EventMap = boost::container::flat_multimap<Key, Val, std::less<Key>, boost::container::static_vector<std::pair<Key, Val>, size>>;
@ -46,4 +49,37 @@ struct Scheduler {
// Add a dummy event to always keep the scheduler non-empty
addEvent(EventType::Panic, std::numeric_limits<u64>::max());
}
private:
static constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / arm11Clock;
public:
// Function for converting time units to cycles for various kernel functions
// Thank you Citra
static constexpr s64 nsToCycles(float ns) { return s64(arm11Clock * (0.000000001f) * ns); }
static constexpr s64 nsToCycles(int ns) { return arm11Clock * s64(ns) / 1000000000; }
static constexpr s64 nsToCycles(s64 ns) {
if (ns / 1000000000 > static_cast<s64>(MAX_VALUE_TO_MULTIPLY)) {
return std::numeric_limits<s64>::max();
}
if (ns > static_cast<s64>(MAX_VALUE_TO_MULTIPLY)) {
return arm11Clock * (ns / 1000000000);
}
return (arm11Clock * ns) / 1000000000;
}
static constexpr s64 nsToCycles(u64 ns) {
if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) {
return std::numeric_limits<s64>::max();
}
if (ns > MAX_VALUE_TO_MULTIPLY) {
return arm11Clock * (s64(ns) / 1000000000);
}
return (arm11Clock * s64(ns)) / 1000000000;
}
};