mirror of
https://github.com/raphaelthegreat/teakra.git
synced 2025-06-18 17:05:34 -04:00
Devirtualize core timing
* Ticking core timing is a very hot path and the components aren't that many so it makes sense to not pay the cost of a virtual call
This commit is contained in:
parent
48d2dd788f
commit
e811e340a1
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -4,3 +4,6 @@
|
||||
[submodule "externals/mcl"]
|
||||
path = externals/mcl
|
||||
url = https://github.com/merryhime/mcl
|
||||
[submodule "externals/robin-map"]
|
||||
path = externals/robin-map
|
||||
url = https://github.com/Tessil/robin-map
|
||||
|
1
externals/robin-map
vendored
Submodule
1
externals/robin-map
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit f45ebce73b3631fdfb8205e2ba700b726ff0c34f
|
@ -60,7 +60,7 @@ add_library(teakra
|
||||
|
||||
create_target_directory_groups(teakra)
|
||||
|
||||
target_link_libraries(teakra PRIVATE Threads::Threads mcl xbyak::xbyak)
|
||||
target_link_libraries(teakra PRIVATE Threads::Threads tsl::robin_map xbyak::xbyak)
|
||||
target_include_directories(teakra
|
||||
PUBLIC ../include
|
||||
PRIVATE .)
|
||||
|
@ -1,13 +1,10 @@
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include "btdmp.h"
|
||||
#include "crash.h"
|
||||
|
||||
namespace Teakra {
|
||||
|
||||
Btdmp::Btdmp(CoreTiming& core_timing) {
|
||||
core_timing.RegisterCallbacks(this);
|
||||
}
|
||||
|
||||
Btdmp::Btdmp() = default;
|
||||
Btdmp::~Btdmp() = default;
|
||||
|
||||
void Btdmp::Reset() {
|
||||
@ -21,35 +18,38 @@ void Btdmp::Reset() {
|
||||
}
|
||||
|
||||
void Btdmp::Tick(u64 ticks) {
|
||||
if (transmit_enable) {
|
||||
transmit_timer += ticks;
|
||||
if (transmit_timer >= transmit_period) {
|
||||
transmit_timer = 0;
|
||||
std::array<std::int16_t, 2> sample;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (transmit_queue.empty()) {
|
||||
std::printf("BTDMP: transmit buffer underrun\n");
|
||||
sample[i] = 0;
|
||||
} else {
|
||||
sample[i] = static_cast<s16>(transmit_queue.front());
|
||||
transmit_queue.pop();
|
||||
transmit_empty = transmit_queue.empty();
|
||||
transmit_full = false;
|
||||
if (transmit_empty) {
|
||||
interrupt_handler();
|
||||
}
|
||||
if (!transmit_enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
transmit_timer += ticks;
|
||||
while (transmit_timer >= transmit_period) {
|
||||
transmit_timer -= transmit_period;
|
||||
|
||||
std::array<std::int16_t, 2> sample;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (transmit_queue.empty()) {
|
||||
std::printf("BTDMP: transmit buffer underrun\n");
|
||||
sample[i] = 0;
|
||||
} else {
|
||||
sample[i] = static_cast<s16>(transmit_queue.front());
|
||||
transmit_queue.pop();
|
||||
transmit_empty = transmit_queue.empty();
|
||||
transmit_full = false;
|
||||
if (transmit_empty) {
|
||||
interrupt_handler();
|
||||
}
|
||||
}
|
||||
if (audio_callback) {
|
||||
audio_callback(sample);
|
||||
}
|
||||
}
|
||||
if (audio_callback) {
|
||||
audio_callback(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u64 Btdmp::GetMaxSkip() const {
|
||||
if (!transmit_enable || transmit_queue.empty()) {
|
||||
return Infinity;
|
||||
return std::numeric_limits<u64>::max();
|
||||
}
|
||||
|
||||
u64 ticks = 0;
|
||||
|
12
src/btdmp.h
12
src/btdmp.h
@ -1,17 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <queue>
|
||||
#include "common_types.h"
|
||||
#include "core_timing.h"
|
||||
|
||||
namespace Teakra {
|
||||
|
||||
class Btdmp : public CoreTiming::Callbacks {
|
||||
class Btdmp {
|
||||
public:
|
||||
Btdmp(CoreTiming& core_timing);
|
||||
Btdmp();
|
||||
~Btdmp();
|
||||
|
||||
void Reset();
|
||||
@ -68,9 +68,9 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Tick(u64 ticks) override;
|
||||
u64 GetMaxSkip() const override;
|
||||
void Skip(u64 ticks) override;
|
||||
void Tick(u64 ticks);
|
||||
u64 GetMaxSkip() const;
|
||||
void Skip(u64 ticks);
|
||||
|
||||
void SetAudioCallback(std::function<void(std::array<std::int16_t, 2>)> callback) {
|
||||
audio_callback = std::move(callback);
|
||||
|
@ -12,6 +12,13 @@ using s16 = std::int16_t;
|
||||
using s32 = std::int32_t;
|
||||
using s64 = std::int64_t;
|
||||
|
||||
// Inlining
|
||||
#ifdef _WIN32
|
||||
#define FORCE_INLINE __forceinline
|
||||
#else
|
||||
#define FORCE_INLINE inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
constexpr unsigned BitSize() {
|
||||
return sizeof(T) * 8; // yeah I know I shouldn't use 8 here.
|
||||
|
@ -1,46 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include "common_types.h"
|
||||
#include "btdmp.h"
|
||||
#include "timer.h"
|
||||
|
||||
namespace Teakra {
|
||||
|
||||
class CoreTiming {
|
||||
public:
|
||||
class Callbacks {
|
||||
public:
|
||||
virtual ~Callbacks() = default;
|
||||
virtual void Tick(u64) = 0;
|
||||
virtual u64 GetMaxSkip() const = 0;
|
||||
virtual void Skip(u64) = 0;
|
||||
static constexpr u64 Infinity = std::numeric_limits<u64>::max();
|
||||
};
|
||||
CoreTiming(std::array<Timer, 2>& timer_, std::array<Btdmp, 2>& btdmp_) :
|
||||
timer{timer_}, btdmp{btdmp_} {}
|
||||
|
||||
void Tick(u64 ticks = 1) {
|
||||
for (const auto& callbacks : registered_callbacks) {
|
||||
callbacks->Tick(ticks);
|
||||
}
|
||||
timer[0].Tick(ticks);
|
||||
timer[1].Tick(ticks);
|
||||
btdmp[0].Tick(ticks);
|
||||
btdmp[1].Tick(ticks);
|
||||
}
|
||||
|
||||
u64 Skip(u64 maximum) {
|
||||
u64 ticks = maximum;
|
||||
for (const auto& callbacks : registered_callbacks) {
|
||||
ticks = std::min(ticks, callbacks->GetMaxSkip());
|
||||
}
|
||||
for (const auto& callbacks : registered_callbacks) {
|
||||
callbacks->Skip(ticks);
|
||||
}
|
||||
const u64 ticks = GetMaxSkip(maximum);
|
||||
timer[0].Skip(ticks);
|
||||
timer[1].Skip(ticks);
|
||||
btdmp[0].Skip(ticks);
|
||||
btdmp[1].Skip(ticks);
|
||||
return ticks;
|
||||
}
|
||||
|
||||
void RegisterCallbacks(Callbacks* callbacks) {
|
||||
registered_callbacks.push_back(std::move(callbacks));
|
||||
u64 GetMaxSkip(u64 maximum) {
|
||||
u64 ticks = maximum;
|
||||
ticks = std::min(ticks, timer[0].GetMaxSkip());
|
||||
ticks = std::min(ticks, timer[1].GetMaxSkip());
|
||||
ticks = std::min(ticks, btdmp[0].GetMaxSkip());
|
||||
ticks = std::min(ticks, btdmp[1].GetMaxSkip());
|
||||
return ticks;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Callbacks*> registered_callbacks;
|
||||
std::array<Timer, 2>& timer;
|
||||
std::array<Btdmp, 2>& btdmp;
|
||||
};
|
||||
|
||||
} // namespace Teakra
|
||||
|
16
src/jit.h
16
src/jit.h
@ -2,15 +2,14 @@
|
||||
#include "shared_memory.h"
|
||||
#include <utility>
|
||||
#include <atomic>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <xbyak/xbyak.h>
|
||||
#include <tsl/robin_map.h>
|
||||
#include "bit.h"
|
||||
#include <bit>
|
||||
#include <set>
|
||||
#include "core_timing.h"
|
||||
#include "memory_interface.h"
|
||||
@ -79,6 +78,12 @@ public:
|
||||
s32 cycles;
|
||||
};
|
||||
|
||||
enum JitStatus {
|
||||
Compiling = 0,
|
||||
EndStaticJump = 1,
|
||||
EndDynJump = 2,
|
||||
};
|
||||
|
||||
CoreTiming& core_timing;
|
||||
JitRegisters& regs;
|
||||
RegisterState* iregs;
|
||||
@ -91,7 +96,8 @@ public:
|
||||
std::set<u32> bkrep_end_locations;
|
||||
std::set<u32> rep_end_locations;
|
||||
bool compiling = false;
|
||||
std::unordered_map<size_t, Block, std::identity> code_blocks;
|
||||
JitStatus status = JitStatus::Compiling;
|
||||
tsl::robin_map<size_t, Block, std::identity> code_blocks;
|
||||
const Block* current_blk{};
|
||||
BlockKey blk_key{};
|
||||
bool unimplemented = false;
|
||||
@ -172,7 +178,7 @@ public:
|
||||
|
||||
if (new_block) {
|
||||
// Note: They key may change during compilation, so this needs to be first.
|
||||
auto& blk = it->second;
|
||||
auto& blk = it.value();
|
||||
blk.entry_key = blk_key;
|
||||
CompileBlock(blk);
|
||||
}
|
||||
@ -2523,8 +2529,6 @@ public:
|
||||
}
|
||||
|
||||
void shfc(Ab a, Ab b, Cond cond) {
|
||||
//NOT_IMPLEMENTED();
|
||||
//return;
|
||||
ConditionPass(cond, [&] {
|
||||
const Reg64 value = rax;
|
||||
GetAcc(value, a.GetName());
|
||||
|
@ -1,6 +1,4 @@
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include "ahbm.h"
|
||||
#include "apbp.h"
|
||||
#include "btdmp.h"
|
||||
@ -17,15 +15,15 @@
|
||||
namespace Teakra {
|
||||
|
||||
struct Teakra::Impl {
|
||||
CoreTiming core_timing;
|
||||
std::array<Timer, 2> timer{};
|
||||
std::array<Btdmp, 2> btdmp{};
|
||||
CoreTiming core_timing{timer, btdmp};
|
||||
SharedMemory shared_memory;
|
||||
MemoryInterfaceUnit miu;
|
||||
ICU icu;
|
||||
Apbp apbp_from_cpu, apbp_from_dsp;
|
||||
std::array<Timer, 2> timer{{{core_timing}, {core_timing}}};
|
||||
Ahbm ahbm;
|
||||
Dma dma{shared_memory, ahbm};
|
||||
std::array<Btdmp, 2> btdmp{{{core_timing}, {core_timing}}};
|
||||
MMIORegion mmio{miu, icu, apbp_from_cpu, apbp_from_dsp, timer, dma, ahbm, btdmp};
|
||||
MemoryInterface memory_interface{shared_memory, miu};
|
||||
Processor processor;
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <limits>
|
||||
#include "crash.h"
|
||||
#include "timer.h"
|
||||
#include "crash.h"
|
||||
@ -75,7 +76,7 @@ void Timer::UpdateMMIO() {
|
||||
|
||||
u64 Timer::GetMaxSkip() const {
|
||||
if (pause || count_mode == CountMode::EventCount)
|
||||
return Infinity;
|
||||
return std::numeric_limits<u64>::max();
|
||||
|
||||
if (counter == 0) {
|
||||
if (count_mode == CountMode::AutoRestart) {
|
||||
@ -83,7 +84,7 @@ u64 Timer::GetMaxSkip() const {
|
||||
} else if (count_mode == CountMode::FreeRunning) {
|
||||
return 0xFFFFFFFF;
|
||||
} else /*Single*/ {
|
||||
return Infinity;
|
||||
return std::numeric_limits<u64>::max();
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,8 +114,4 @@ void Timer::Skip(u64 ticks) {
|
||||
UpdateMMIO();
|
||||
}
|
||||
|
||||
Timer::Timer(CoreTiming& core_timing) {
|
||||
core_timing.RegisterCallbacks(this);
|
||||
}
|
||||
|
||||
} // namespace Teakra
|
||||
|
12
src/timer.h
12
src/timer.h
@ -3,14 +3,11 @@
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include "common_types.h"
|
||||
#include "core_timing.h"
|
||||
|
||||
namespace Teakra {
|
||||
|
||||
class Timer : public CoreTiming::Callbacks {
|
||||
class Timer {
|
||||
public:
|
||||
Timer(CoreTiming& core_timing);
|
||||
|
||||
enum class CountMode : u16 {
|
||||
Single = 0,
|
||||
AutoRestart = 1,
|
||||
@ -21,10 +18,11 @@ public:
|
||||
void Reset();
|
||||
|
||||
void Restart();
|
||||
void Tick(u64 ticks) override;
|
||||
void TickEvent();
|
||||
u64 GetMaxSkip() const override;
|
||||
void Skip(u64 ticks) override;
|
||||
|
||||
void Tick(u64 ticks);
|
||||
u64 GetMaxSkip() const;
|
||||
void Skip(u64 ticks);
|
||||
|
||||
u16 update_mmio = 0;
|
||||
u16 pause = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user