@@ -49,15 +49,19 @@ class ScopeInit final
Config::Init ();
SConfig::Init ();
PowerPC::Init (PowerPC::CPUCore::Interpreter);
CoreTiming::Init ();
auto & system = Core::System::GetInstance ();
auto & core_timing = system .GetCoreTiming ();
core_timing.Init ();
}
~ScopeInit ()
{
if (!UserDirectoryExists ())
{
return ;
}
CoreTiming::Shutdown ();
auto & system = Core::System::GetInstance ();
auto & core_timing = system .GetCoreTiming ();
core_timing.Shutdown ();
PowerPC::Shutdown ();
SConfig::Shutdown ();
Config::Shutdown ();
@@ -78,7 +82,9 @@ static void AdvanceAndCheck(u32 idx, int downcount, int expected_lateness = 0,
s_lateness = expected_lateness;
PowerPC::ppcState.downcount = cpu_downcount; // Pretend we executed X cycles of instructions.
CoreTiming::Advance ();
auto & system = Core::System::GetInstance ();
auto & core_timing = system .GetCoreTiming ();
core_timing.Advance ();
EXPECT_EQ (decltype (s_callbacks_ran_flags)().set (idx), s_callbacks_ran_flags);
EXPECT_EQ (downcount, PowerPC::ppcState.downcount );
@@ -89,25 +95,28 @@ TEST(CoreTiming, BasicOrder)
ScopeInit guard;
ASSERT_TRUE (guard.UserDirectoryExists ());
CoreTiming::EventType* cb_a = CoreTiming::RegisterEvent (" callbackA" , CallbackTemplate<0 >);
CoreTiming::EventType* cb_b = CoreTiming::RegisterEvent (" callbackB" , CallbackTemplate<1 >);
CoreTiming::EventType* cb_c = CoreTiming::RegisterEvent (" callbackC" , CallbackTemplate<2 >);
CoreTiming::EventType* cb_d = CoreTiming::RegisterEvent (" callbackD" , CallbackTemplate<3 >);
CoreTiming::EventType* cb_e = CoreTiming::RegisterEvent (" callbackE" , CallbackTemplate<4 >);
auto & system = Core::System::GetInstance ();
auto & core_timing = system .GetCoreTiming ();
CoreTiming::EventType* cb_a = core_timing.RegisterEvent (" callbackA" , CallbackTemplate<0 >);
CoreTiming::EventType* cb_b = core_timing.RegisterEvent (" callbackB" , CallbackTemplate<1 >);
CoreTiming::EventType* cb_c = core_timing.RegisterEvent (" callbackC" , CallbackTemplate<2 >);
CoreTiming::EventType* cb_d = core_timing.RegisterEvent (" callbackD" , CallbackTemplate<3 >);
CoreTiming::EventType* cb_e = core_timing.RegisterEvent (" callbackE" , CallbackTemplate<4 >);
// Enter slice 0
CoreTiming:: Advance ();
core_timing. Advance ();
// D -> B -> C -> A -> E
CoreTiming:: ScheduleEvent (1000 , cb_a, CB_IDS[0 ]);
core_timing. ScheduleEvent (1000 , cb_a, CB_IDS[0 ]);
EXPECT_EQ (1000 , PowerPC::ppcState.downcount );
CoreTiming:: ScheduleEvent (500 , cb_b, CB_IDS[1 ]);
core_timing. ScheduleEvent (500 , cb_b, CB_IDS[1 ]);
EXPECT_EQ (500 , PowerPC::ppcState.downcount );
CoreTiming:: ScheduleEvent (800 , cb_c, CB_IDS[2 ]);
core_timing. ScheduleEvent (800 , cb_c, CB_IDS[2 ]);
EXPECT_EQ (500 , PowerPC::ppcState.downcount );
CoreTiming:: ScheduleEvent (100 , cb_d, CB_IDS[3 ]);
core_timing. ScheduleEvent (100 , cb_d, CB_IDS[3 ]);
EXPECT_EQ (100 , PowerPC::ppcState.downcount );
CoreTiming:: ScheduleEvent (1200 , cb_e, CB_IDS[4 ]);
core_timing. ScheduleEvent (1200 , cb_e, CB_IDS[4 ]);
EXPECT_EQ (100 , PowerPC::ppcState.downcount );
AdvanceAndCheck (3 , 400 );
@@ -140,27 +149,30 @@ TEST(CoreTiming, SharedSlot)
ScopeInit guard;
ASSERT_TRUE (guard.UserDirectoryExists ());
CoreTiming::EventType* cb_a = CoreTiming::RegisterEvent (" callbackA" , FifoCallback<0 >);
CoreTiming::EventType* cb_b = CoreTiming::RegisterEvent (" callbackB" , FifoCallback<1 >);
CoreTiming::EventType* cb_c = CoreTiming::RegisterEvent (" callbackC" , FifoCallback<2 >);
CoreTiming::EventType* cb_d = CoreTiming::RegisterEvent (" callbackD" , FifoCallback<3 >);
CoreTiming::EventType* cb_e = CoreTiming::RegisterEvent (" callbackE" , FifoCallback<4 >);
auto & system = Core::System::GetInstance ();
auto & core_timing = system .GetCoreTiming ();
CoreTiming::EventType* cb_a = core_timing.RegisterEvent (" callbackA" , FifoCallback<0 >);
CoreTiming::EventType* cb_b = core_timing.RegisterEvent (" callbackB" , FifoCallback<1 >);
CoreTiming::EventType* cb_c = core_timing.RegisterEvent (" callbackC" , FifoCallback<2 >);
CoreTiming::EventType* cb_d = core_timing.RegisterEvent (" callbackD" , FifoCallback<3 >);
CoreTiming::EventType* cb_e = core_timing.RegisterEvent (" callbackE" , FifoCallback<4 >);
CoreTiming:: ScheduleEvent (1000 , cb_a, CB_IDS[0 ]);
CoreTiming:: ScheduleEvent (1000 , cb_b, CB_IDS[1 ]);
CoreTiming:: ScheduleEvent (1000 , cb_c, CB_IDS[2 ]);
CoreTiming:: ScheduleEvent (1000 , cb_d, CB_IDS[3 ]);
CoreTiming:: ScheduleEvent (1000 , cb_e, CB_IDS[4 ]);
core_timing. ScheduleEvent (1000 , cb_a, CB_IDS[0 ]);
core_timing. ScheduleEvent (1000 , cb_b, CB_IDS[1 ]);
core_timing. ScheduleEvent (1000 , cb_c, CB_IDS[2 ]);
core_timing. ScheduleEvent (1000 , cb_d, CB_IDS[3 ]);
core_timing. ScheduleEvent (1000 , cb_e, CB_IDS[4 ]);
// Enter slice 0
CoreTiming:: Advance ();
core_timing. Advance ();
EXPECT_EQ (1000 , PowerPC::ppcState.downcount );
s_callbacks_ran_flags = 0 ;
s_counter = 0 ;
s_lateness = 0 ;
PowerPC::ppcState.downcount = 0 ;
CoreTiming:: Advance ();
core_timing. Advance ();
EXPECT_EQ (MAX_SLICE_LENGTH, PowerPC::ppcState.downcount );
EXPECT_EQ (0x1FULL , s_callbacks_ran_flags.to_ullong ());
}
@@ -170,14 +182,17 @@ TEST(CoreTiming, PredictableLateness)
ScopeInit guard;
ASSERT_TRUE (guard.UserDirectoryExists ());
CoreTiming::EventType* cb_a = CoreTiming::RegisterEvent (" callbackA" , CallbackTemplate<0 >);
CoreTiming::EventType* cb_b = CoreTiming::RegisterEvent (" callbackB" , CallbackTemplate<1 >);
auto & system = Core::System::GetInstance ();
auto & core_timing = system .GetCoreTiming ();
CoreTiming::EventType* cb_a = core_timing.RegisterEvent (" callbackA" , CallbackTemplate<0 >);
CoreTiming::EventType* cb_b = core_timing.RegisterEvent (" callbackB" , CallbackTemplate<1 >);
// Enter slice 0
CoreTiming:: Advance ();
core_timing. Advance ();
CoreTiming:: ScheduleEvent (100 , cb_a, CB_IDS[0 ]);
CoreTiming:: ScheduleEvent (200 , cb_b, CB_IDS[1 ]);
core_timing. ScheduleEvent (100 , cb_a, CB_IDS[0 ]);
core_timing. ScheduleEvent (200 , cb_b, CB_IDS[1 ]);
AdvanceAndCheck (0 , 90 , 10 , -10 ); // (100 - 10)
AdvanceAndCheck (1 , MAX_SLICE_LENGTH, 50 , -50 );
@@ -194,7 +209,10 @@ static void RescheduleCallback(Core::System& system, u64 userdata, s64 lateness)
EXPECT_EQ (s_lateness, lateness);
if (s_reschedules > 0 )
CoreTiming::ScheduleEvent (1000 , reinterpret_cast <CoreTiming::EventType*>(userdata), userdata);
{
system .GetCoreTiming ().ScheduleEvent (1000 , reinterpret_cast <CoreTiming::EventType*>(userdata),
userdata);
}
}
} // namespace ChainSchedulingTest
@@ -205,19 +223,22 @@ TEST(CoreTiming, ChainScheduling)
ScopeInit guard;
ASSERT_TRUE (guard.UserDirectoryExists ());
CoreTiming::EventType* cb_a = CoreTiming::RegisterEvent (" callbackA" , CallbackTemplate<0 >);
CoreTiming::EventType* cb_b = CoreTiming::RegisterEvent (" callbackB" , CallbackTemplate<1 >);
CoreTiming::EventType* cb_c = CoreTiming::RegisterEvent (" callbackC" , CallbackTemplate<2 >);
auto & system = Core::System::GetInstance ();
auto & core_timing = system .GetCoreTiming ();
CoreTiming::EventType* cb_a = core_timing.RegisterEvent (" callbackA" , CallbackTemplate<0 >);
CoreTiming::EventType* cb_b = core_timing.RegisterEvent (" callbackB" , CallbackTemplate<1 >);
CoreTiming::EventType* cb_c = core_timing.RegisterEvent (" callbackC" , CallbackTemplate<2 >);
CoreTiming::EventType* cb_rs =
CoreTiming:: RegisterEvent (" callbackReschedule" , RescheduleCallback);
core_timing. RegisterEvent (" callbackReschedule" , RescheduleCallback);
// Enter slice 0
CoreTiming:: Advance ();
core_timing. Advance ();
CoreTiming:: ScheduleEvent (800 , cb_a, CB_IDS[0 ]);
CoreTiming:: ScheduleEvent (1000 , cb_b, CB_IDS[1 ]);
CoreTiming:: ScheduleEvent (2200 , cb_c, CB_IDS[2 ]);
CoreTiming:: ScheduleEvent (1000 , cb_rs, reinterpret_cast <u64>(cb_rs));
core_timing. ScheduleEvent (800 , cb_a, CB_IDS[0 ]);
core_timing. ScheduleEvent (1000 , cb_b, CB_IDS[1 ]);
core_timing. ScheduleEvent (2200 , cb_c, CB_IDS[2 ]);
core_timing. ScheduleEvent (1000 , cb_rs, reinterpret_cast <u64>(cb_rs));
EXPECT_EQ (800 , PowerPC::ppcState.downcount );
s_reschedules = 3 ;
@@ -226,14 +247,14 @@ TEST(CoreTiming, ChainScheduling)
EXPECT_EQ (2 , s_reschedules);
PowerPC::ppcState.downcount = 0 ;
CoreTiming:: Advance (); // cb_rs
core_timing. Advance (); // cb_rs
EXPECT_EQ (1 , s_reschedules);
EXPECT_EQ (200 , PowerPC::ppcState.downcount );
AdvanceAndCheck (2 , 800 ); // cb_c
PowerPC::ppcState.downcount = 0 ;
CoreTiming:: Advance (); // cb_rs
core_timing. Advance (); // cb_rs
EXPECT_EQ (0 , s_reschedules);
EXPECT_EQ (MAX_SLICE_LENGTH, PowerPC::ppcState.downcount );
}
@@ -247,7 +268,7 @@ static void ChainCallback(Core::System& system, u64 userdata, s64 lateness)
EXPECT_EQ (CB_IDS[0 ] + 1 , userdata);
EXPECT_EQ (0 , lateness);
CoreTiming:: ScheduleEvent (-1000 , s_cb_next, userdata - 1 );
system . GetCoreTiming (). ScheduleEvent (-1000 , s_cb_next, userdata - 1 );
}
} // namespace ScheduleIntoPastTest
@@ -261,14 +282,17 @@ TEST(CoreTiming, ScheduleIntoPast)
ScopeInit guard;
ASSERT_TRUE (guard.UserDirectoryExists ());
s_cb_next = CoreTiming::RegisterEvent (" callbackA" , CallbackTemplate<0 >);
CoreTiming::EventType* cb_b = CoreTiming::RegisterEvent (" callbackB" , CallbackTemplate<1 >);
CoreTiming::EventType* cb_chain = CoreTiming::RegisterEvent (" callbackChain" , ChainCallback);
auto & system = Core::System::GetInstance ();
auto & core_timing = system .GetCoreTiming ();
s_cb_next = core_timing.RegisterEvent (" callbackA" , CallbackTemplate<0 >);
CoreTiming::EventType* cb_b = core_timing.RegisterEvent (" callbackB" , CallbackTemplate<1 >);
CoreTiming::EventType* cb_chain = core_timing.RegisterEvent (" callbackChain" , ChainCallback);
// Enter slice 0
CoreTiming:: Advance ();
core_timing. Advance ();
CoreTiming:: ScheduleEvent (1000 , cb_chain, CB_IDS[0 ] + 1 );
core_timing. ScheduleEvent (1000 , cb_chain, CB_IDS[0 ] + 1 );
EXPECT_EQ (1000 , PowerPC::ppcState.downcount );
AdvanceAndCheck (0 , MAX_SLICE_LENGTH, 1000 ); // Run cb_chain into late cb_a
@@ -280,17 +304,17 @@ TEST(CoreTiming, ScheduleIntoPast)
// the stale value, i.e. effectively half-way through the previous slice.
// NOTE: We're only testing that the scheduler doesn't break, not whether this makes sense.
Core::UndeclareAsCPUThread ();
auto & core_timing_globals = Core::System::GetInstance (). GetCoreTimingGlobals ();
auto & core_timing_globals = core_timing. GetGlobals ();
core_timing_globals.global_timer -= 1000 ;
CoreTiming:: ScheduleEvent (0 , cb_b, CB_IDS[1 ], CoreTiming::FromThread::NON_CPU);
core_timing. ScheduleEvent (0 , cb_b, CB_IDS[1 ], CoreTiming::FromThread::NON_CPU);
core_timing_globals.global_timer += 1000 ;
Core::DeclareAsCPUThread ();
AdvanceAndCheck (1 , MAX_SLICE_LENGTH, MAX_SLICE_LENGTH + 1000 );
// Schedule directly into the past from the CPU.
// This shouldn't happen in practice, but it's best if we don't mess up the slice length and
// downcount if we do.
CoreTiming:: ScheduleEvent (-1000 , s_cb_next, CB_IDS[0 ]);
core_timing. ScheduleEvent (-1000 , s_cb_next, CB_IDS[0 ]);
EXPECT_EQ (0 , PowerPC::ppcState.downcount );
AdvanceAndCheck (0 , MAX_SLICE_LENGTH, 1000 );
}
@@ -300,25 +324,28 @@ TEST(CoreTiming, Overclocking)
ScopeInit guard;
ASSERT_TRUE (guard.UserDirectoryExists ());
CoreTiming::EventType* cb_a = CoreTiming::RegisterEvent (" callbackA" , CallbackTemplate<0 >);
CoreTiming::EventType* cb_b = CoreTiming::RegisterEvent (" callbackB" , CallbackTemplate<1 >);
CoreTiming::EventType* cb_c = CoreTiming::RegisterEvent (" callbackC" , CallbackTemplate<2 >);
CoreTiming::EventType* cb_d = CoreTiming::RegisterEvent (" callbackD" , CallbackTemplate<3 >);
CoreTiming::EventType* cb_e = CoreTiming::RegisterEvent (" callbackE" , CallbackTemplate<4 >);
auto & system = Core::System::GetInstance ();
auto & core_timing = system .GetCoreTiming ();
CoreTiming::EventType* cb_a = core_timing.RegisterEvent (" callbackA" , CallbackTemplate<0 >);
CoreTiming::EventType* cb_b = core_timing.RegisterEvent (" callbackB" , CallbackTemplate<1 >);
CoreTiming::EventType* cb_c = core_timing.RegisterEvent (" callbackC" , CallbackTemplate<2 >);
CoreTiming::EventType* cb_d = core_timing.RegisterEvent (" callbackD" , CallbackTemplate<3 >);
CoreTiming::EventType* cb_e = core_timing.RegisterEvent (" callbackE" , CallbackTemplate<4 >);
// Overclock
Config::SetCurrent (Config::MAIN_OVERCLOCK_ENABLE, true );
Config::SetCurrent (Config::MAIN_OVERCLOCK, 2 .0f );
// Enter slice 0
// Updates s_last_OC_factor.
CoreTiming:: Advance ();
core_timing. Advance ();
CoreTiming:: ScheduleEvent (100 , cb_a, CB_IDS[0 ]);
CoreTiming:: ScheduleEvent (200 , cb_b, CB_IDS[1 ]);
CoreTiming:: ScheduleEvent (400 , cb_c, CB_IDS[2 ]);
CoreTiming:: ScheduleEvent (800 , cb_d, CB_IDS[3 ]);
CoreTiming:: ScheduleEvent (1600 , cb_e, CB_IDS[4 ]);
core_timing. ScheduleEvent (100 , cb_a, CB_IDS[0 ]);
core_timing. ScheduleEvent (200 , cb_b, CB_IDS[1 ]);
core_timing. ScheduleEvent (400 , cb_c, CB_IDS[2 ]);
core_timing. ScheduleEvent (800 , cb_d, CB_IDS[3 ]);
core_timing. ScheduleEvent (1600 , cb_e, CB_IDS[4 ]);
EXPECT_EQ (200 , PowerPC::ppcState.downcount );
AdvanceAndCheck (0 , 200 ); // (200 - 100) * 2
@@ -329,13 +356,13 @@ TEST(CoreTiming, Overclocking)
// Underclock
Config::SetCurrent (Config::MAIN_OVERCLOCK, 0 .5f );
CoreTiming:: Advance ();
core_timing. Advance ();
CoreTiming:: ScheduleEvent (100 , cb_a, CB_IDS[0 ]);
CoreTiming:: ScheduleEvent (200 , cb_b, CB_IDS[1 ]);
CoreTiming:: ScheduleEvent (400 , cb_c, CB_IDS[2 ]);
CoreTiming:: ScheduleEvent (800 , cb_d, CB_IDS[3 ]);
CoreTiming:: ScheduleEvent (1600 , cb_e, CB_IDS[4 ]);
core_timing. ScheduleEvent (100 , cb_a, CB_IDS[0 ]);
core_timing. ScheduleEvent (200 , cb_b, CB_IDS[1 ]);
core_timing. ScheduleEvent (400 , cb_c, CB_IDS[2 ]);
core_timing. ScheduleEvent (800 , cb_d, CB_IDS[3 ]);
core_timing. ScheduleEvent (1600 , cb_e, CB_IDS[4 ]);
EXPECT_EQ (50 , PowerPC::ppcState.downcount );
AdvanceAndCheck (0 , 50 ); // (200 - 100) / 2
@@ -346,13 +373,13 @@ TEST(CoreTiming, Overclocking)
// Try switching the clock mid-emulation
Config::SetCurrent (Config::MAIN_OVERCLOCK, 1 .0f );
CoreTiming:: Advance ();
core_timing. Advance ();
CoreTiming:: ScheduleEvent (100 , cb_a, CB_IDS[0 ]);
CoreTiming:: ScheduleEvent (200 , cb_b, CB_IDS[1 ]);
CoreTiming:: ScheduleEvent (400 , cb_c, CB_IDS[2 ]);
CoreTiming:: ScheduleEvent (800 , cb_d, CB_IDS[3 ]);
CoreTiming:: ScheduleEvent (1600 , cb_e, CB_IDS[4 ]);
core_timing. ScheduleEvent (100 , cb_a, CB_IDS[0 ]);
core_timing. ScheduleEvent (200 , cb_b, CB_IDS[1 ]);
core_timing. ScheduleEvent (400 , cb_c, CB_IDS[2 ]);
core_timing. ScheduleEvent (800 , cb_d, CB_IDS[3 ]);
core_timing. ScheduleEvent (1600 , cb_e, CB_IDS[4 ]);
EXPECT_EQ (100 , PowerPC::ppcState.downcount );
AdvanceAndCheck (0 , 100 ); // (200 - 100)