summaryrefslogtreecommitdiff
path: root/src/tests
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-02-24 22:04:12 -0400
committerGravatar Fernando Sahmkow2020-06-27 11:35:06 -0400
commite31425df3877636c098ec7426ebd2067920715cb (patch)
tree5c0fc518a4ebb8413c491b43a9fdd99450c7bd80 /src/tests
parentMerge pull request #3396 from FernandoS27/prometheus-1 (diff)
downloadyuzu-e31425df3877636c098ec7426ebd2067920715cb.tar.gz
yuzu-e31425df3877636c098ec7426ebd2067920715cb.tar.xz
yuzu-e31425df3877636c098ec7426ebd2067920715cb.zip
General: Recover Prometheus project from harddrive failure
This commit: Implements CPU Interrupts, Replaces Cycle Timing for Host Timing, Reworks the Kernel's Scheduler, Introduce Idle State and Suspended State, Recreates the bootmanager, Initializes Multicore system.
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/CMakeLists.txt1
-rw-r--r--src/tests/core/core_timing.cpp184
2 files changed, 85 insertions, 100 deletions
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 3f750b51c..47ef30aa9 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -8,7 +8,6 @@ add_executable(tests
8 core/arm/arm_test_common.cpp 8 core/arm/arm_test_common.cpp
9 core/arm/arm_test_common.h 9 core/arm/arm_test_common.h
10 core/core_timing.cpp 10 core/core_timing.cpp
11 core/host_timing.cpp
12 tests.cpp 11 tests.cpp
13) 12)
14 13
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp
index ff2d11cc8..795f3da09 100644
--- a/src/tests/core/core_timing.cpp
+++ b/src/tests/core/core_timing.cpp
@@ -16,31 +16,30 @@
16 16
17namespace { 17namespace {
18// Numbers are chosen randomly to make sure the correct one is given. 18// Numbers are chosen randomly to make sure the correct one is given.
19constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}}; 19static constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}};
20constexpr int MAX_SLICE_LENGTH = 10000; // Copied from CoreTiming internals 20static constexpr int MAX_SLICE_LENGTH = 10000; // Copied from CoreTiming internals
21static constexpr std::array<u64, 5> calls_order{{2, 0, 1, 4, 3}};
22static std::array<s64, 5> delays{};
21 23
22std::bitset<CB_IDS.size()> callbacks_ran_flags; 24std::bitset<CB_IDS.size()> callbacks_ran_flags;
23u64 expected_callback = 0; 25u64 expected_callback = 0;
24s64 lateness = 0; 26s64 lateness = 0;
25 27
26template <unsigned int IDX> 28template <unsigned int IDX>
27void CallbackTemplate(u64 userdata, s64 cycles_late) { 29void HostCallbackTemplate(u64 userdata, s64 nanoseconds_late) {
28 static_assert(IDX < CB_IDS.size(), "IDX out of range"); 30 static_assert(IDX < CB_IDS.size(), "IDX out of range");
29 callbacks_ran_flags.set(IDX); 31 callbacks_ran_flags.set(IDX);
30 REQUIRE(CB_IDS[IDX] == userdata); 32 REQUIRE(CB_IDS[IDX] == userdata);
31 REQUIRE(CB_IDS[IDX] == expected_callback); 33 REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]);
32 REQUIRE(lateness == cycles_late); 34 delays[IDX] = nanoseconds_late;
35 ++expected_callback;
33} 36}
34 37
35u64 callbacks_done = 0; 38u64 callbacks_done = 0;
36 39
37void EmptyCallback(u64 userdata, s64 cycles_late) {
38 ++callbacks_done;
39}
40
41struct ScopeInit final { 40struct ScopeInit final {
42 ScopeInit() { 41 ScopeInit() {
43 core_timing.Initialize(); 42 core_timing.Initialize([]() {});
44 } 43 }
45 ~ScopeInit() { 44 ~ScopeInit() {
46 core_timing.Shutdown(); 45 core_timing.Shutdown();
@@ -49,110 +48,97 @@ struct ScopeInit final {
49 Core::Timing::CoreTiming core_timing; 48 Core::Timing::CoreTiming core_timing;
50}; 49};
51 50
52void AdvanceAndCheck(Core::Timing::CoreTiming& core_timing, u32 idx, u32 context = 0,
53 int expected_lateness = 0, int cpu_downcount = 0) {
54 callbacks_ran_flags = 0;
55 expected_callback = CB_IDS[idx];
56 lateness = expected_lateness;
57
58 // Pretend we executed X cycles of instructions.
59 core_timing.SwitchContext(context);
60 core_timing.AddTicks(core_timing.GetDowncount() - cpu_downcount);
61 core_timing.Advance();
62 core_timing.SwitchContext((context + 1) % 4);
63
64 REQUIRE(decltype(callbacks_ran_flags)().set(idx) == callbacks_ran_flags);
65}
66} // Anonymous namespace
67
68TEST_CASE("CoreTiming[BasicOrder]", "[core]") { 51TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
69 ScopeInit guard; 52 ScopeInit guard;
70 auto& core_timing = guard.core_timing; 53 auto& core_timing = guard.core_timing;
54 std::vector<std::shared_ptr<Core::Timing::EventType>> events{
55 Core::Timing::CreateEvent("callbackA", HostCallbackTemplate<0>),
56 Core::Timing::CreateEvent("callbackB", HostCallbackTemplate<1>),
57 Core::Timing::CreateEvent("callbackC", HostCallbackTemplate<2>),
58 Core::Timing::CreateEvent("callbackD", HostCallbackTemplate<3>),
59 Core::Timing::CreateEvent("callbackE", HostCallbackTemplate<4>),
60 };
61
62 expected_callback = 0;
63
64 core_timing.SyncPause(true);
65
66 u64 one_micro = 1000U;
67 for (std::size_t i = 0; i < events.size(); i++) {
68 u64 order = calls_order[i];
69 core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]);
70 }
71 /// test pause
72 REQUIRE(callbacks_ran_flags.none());
71 73
72 std::shared_ptr<Core::Timing::EventType> cb_a = 74 core_timing.Pause(false); // No need to sync
73 Core::Timing::CreateEvent("callbackA", CallbackTemplate<0>);
74 std::shared_ptr<Core::Timing::EventType> cb_b =
75 Core::Timing::CreateEvent("callbackB", CallbackTemplate<1>);
76 std::shared_ptr<Core::Timing::EventType> cb_c =
77 Core::Timing::CreateEvent("callbackC", CallbackTemplate<2>);
78 std::shared_ptr<Core::Timing::EventType> cb_d =
79 Core::Timing::CreateEvent("callbackD", CallbackTemplate<3>);
80 std::shared_ptr<Core::Timing::EventType> cb_e =
81 Core::Timing::CreateEvent("callbackE", CallbackTemplate<4>);
82
83 // Enter slice 0
84 core_timing.ResetRun();
85
86 // D -> B -> C -> A -> E
87 core_timing.SwitchContext(0);
88 core_timing.ScheduleEvent(1000, cb_a, CB_IDS[0]);
89 REQUIRE(1000 == core_timing.GetDowncount());
90 core_timing.ScheduleEvent(500, cb_b, CB_IDS[1]);
91 REQUIRE(500 == core_timing.GetDowncount());
92 core_timing.ScheduleEvent(800, cb_c, CB_IDS[2]);
93 REQUIRE(500 == core_timing.GetDowncount());
94 core_timing.ScheduleEvent(100, cb_d, CB_IDS[3]);
95 REQUIRE(100 == core_timing.GetDowncount());
96 core_timing.ScheduleEvent(1200, cb_e, CB_IDS[4]);
97 REQUIRE(100 == core_timing.GetDowncount());
98
99 AdvanceAndCheck(core_timing, 3, 0);
100 AdvanceAndCheck(core_timing, 1, 1);
101 AdvanceAndCheck(core_timing, 2, 2);
102 AdvanceAndCheck(core_timing, 0, 3);
103 AdvanceAndCheck(core_timing, 4, 0);
104}
105
106TEST_CASE("CoreTiming[FairSharing]", "[core]") {
107 75
108 ScopeInit guard; 76 while (core_timing.HasPendingEvents())
109 auto& core_timing = guard.core_timing; 77 ;
110 78
111 std::shared_ptr<Core::Timing::EventType> empty_callback = 79 REQUIRE(callbacks_ran_flags.all());
112 Core::Timing::CreateEvent("empty_callback", EmptyCallback);
113 80
114 callbacks_done = 0; 81 for (std::size_t i = 0; i < delays.size(); i++) {
115 u64 MAX_CALLBACKS = 10; 82 const double delay = static_cast<double>(delays[i]);
116 for (std::size_t i = 0; i < 10; i++) { 83 const double micro = delay / 1000.0f;
117 core_timing.ScheduleEvent(i * 3333U, empty_callback, 0); 84 const double mili = micro / 1000.0f;
85 printf("HostTimer Pausing Delay[%zu]: %.3f %.6f\n", i, micro, mili);
118 } 86 }
87}
119 88
120 const s64 advances = MAX_SLICE_LENGTH / 10; 89#pragma optimize("", off)
121 core_timing.ResetRun(); 90u64 TestTimerSpeed(Core::Timing::CoreTiming& core_timing) {
122 u64 current_time = core_timing.GetTicks(); 91 u64 start = core_timing.GetGlobalTimeNs().count();
123 bool keep_running{}; 92 u64 placebo = 0;
124 do { 93 for (std::size_t i = 0; i < 1000; i++) {
125 keep_running = false; 94 placebo += core_timing.GetGlobalTimeNs().count();
126 for (u32 active_core = 0; active_core < 4; ++active_core) { 95 }
127 core_timing.SwitchContext(active_core); 96 u64 end = core_timing.GetGlobalTimeNs().count();
128 if (core_timing.CanCurrentContextRun()) { 97 return (end - start);
129 core_timing.AddTicks(std::min<s64>(advances, core_timing.GetDowncount()));
130 core_timing.Advance();
131 }
132 keep_running |= core_timing.CanCurrentContextRun();
133 }
134 } while (keep_running);
135 u64 current_time_2 = core_timing.GetTicks();
136
137 REQUIRE(MAX_CALLBACKS == callbacks_done);
138 REQUIRE(current_time_2 == current_time + MAX_SLICE_LENGTH * 4);
139} 98}
99#pragma optimize("", on)
140 100
141TEST_CASE("Core::Timing[PredictableLateness]", "[core]") { 101TEST_CASE("CoreTiming[BasicOrderNoPausing]", "[core]") {
142 ScopeInit guard; 102 ScopeInit guard;
143 auto& core_timing = guard.core_timing; 103 auto& core_timing = guard.core_timing;
104 std::vector<std::shared_ptr<Core::Timing::EventType>> events{
105 Core::Timing::CreateEvent("callbackA", HostCallbackTemplate<0>),
106 Core::Timing::CreateEvent("callbackB", HostCallbackTemplate<1>),
107 Core::Timing::CreateEvent("callbackC", HostCallbackTemplate<2>),
108 Core::Timing::CreateEvent("callbackD", HostCallbackTemplate<3>),
109 Core::Timing::CreateEvent("callbackE", HostCallbackTemplate<4>),
110 };
111
112 core_timing.SyncPause(true);
113 core_timing.SyncPause(false);
114
115 expected_callback = 0;
116
117 u64 start = core_timing.GetGlobalTimeNs().count();
118 u64 one_micro = 1000U;
119 for (std::size_t i = 0; i < events.size(); i++) {
120 u64 order = calls_order[i];
121 core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]);
122 }
123 u64 end = core_timing.GetGlobalTimeNs().count();
124 const double scheduling_time = static_cast<double>(end - start);
125 const double timer_time = static_cast<double>(TestTimerSpeed(core_timing));
144 126
145 std::shared_ptr<Core::Timing::EventType> cb_a = 127 while (core_timing.HasPendingEvents())
146 Core::Timing::CreateEvent("callbackA", CallbackTemplate<0>); 128 ;
147 std::shared_ptr<Core::Timing::EventType> cb_b =
148 Core::Timing::CreateEvent("callbackB", CallbackTemplate<1>);
149 129
150 // Enter slice 0 130 REQUIRE(callbacks_ran_flags.all());
151 core_timing.ResetRun();
152 131
153 core_timing.ScheduleEvent(100, cb_a, CB_IDS[0]); 132 for (std::size_t i = 0; i < delays.size(); i++) {
154 core_timing.ScheduleEvent(200, cb_b, CB_IDS[1]); 133 const double delay = static_cast<double>(delays[i]);
134 const double micro = delay / 1000.0f;
135 const double mili = micro / 1000.0f;
136 printf("HostTimer No Pausing Delay[%zu]: %.3f %.6f\n", i, micro, mili);
137 }
155 138
156 AdvanceAndCheck(core_timing, 0, 0, 10, -10); // (100 - 10) 139 const double micro = scheduling_time / 1000.0f;
157 AdvanceAndCheck(core_timing, 1, 1, 50, -50); 140 const double mili = micro / 1000.0f;
141 printf("HostTimer No Pausing Scheduling Time: %.3f %.6f\n", micro, mili);
142 printf("HostTimer No Pausing Timer Time: %.3f %.6f\n", timer_time / 1000.f,
143 timer_time / 1000000.f);
158} 144}