diff options
Diffstat (limited to '')
| -rw-r--r-- | src/tests/core/core_timing.cpp | 193 |
1 files changed, 0 insertions, 193 deletions
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp index f8be8fd19..596a2f4aa 100644 --- a/src/tests/core/core_timing.cpp +++ b/src/tests/core/core_timing.cpp | |||
| @@ -52,196 +52,3 @@ static void AdvanceAndCheck(Core::Timing::CoreTiming& core_timing, u32 idx, int | |||
| 52 | REQUIRE(decltype(callbacks_ran_flags)().set(idx) == callbacks_ran_flags); | 52 | REQUIRE(decltype(callbacks_ran_flags)().set(idx) == callbacks_ran_flags); |
| 53 | REQUIRE(downcount == core_timing.GetDowncount()); | 53 | REQUIRE(downcount == core_timing.GetDowncount()); |
| 54 | } | 54 | } |
| 55 | |||
| 56 | TEST_CASE("CoreTiming[BasicOrder]", "[core]") { | ||
| 57 | ScopeInit guard; | ||
| 58 | auto& core_timing = guard.core_timing; | ||
| 59 | |||
| 60 | Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>); | ||
| 61 | Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>); | ||
| 62 | Core::Timing::EventType* cb_c = core_timing.RegisterEvent("callbackC", CallbackTemplate<2>); | ||
| 63 | Core::Timing::EventType* cb_d = core_timing.RegisterEvent("callbackD", CallbackTemplate<3>); | ||
| 64 | Core::Timing::EventType* cb_e = core_timing.RegisterEvent("callbackE", CallbackTemplate<4>); | ||
| 65 | |||
| 66 | // Enter slice 0 | ||
| 67 | core_timing.Advance(); | ||
| 68 | |||
| 69 | // D -> B -> C -> A -> E | ||
| 70 | core_timing.ScheduleEvent(1000, cb_a, CB_IDS[0]); | ||
| 71 | REQUIRE(1000 == core_timing.GetDowncount()); | ||
| 72 | core_timing.ScheduleEvent(500, cb_b, CB_IDS[1]); | ||
| 73 | REQUIRE(500 == core_timing.GetDowncount()); | ||
| 74 | core_timing.ScheduleEvent(800, cb_c, CB_IDS[2]); | ||
| 75 | REQUIRE(500 == core_timing.GetDowncount()); | ||
| 76 | core_timing.ScheduleEvent(100, cb_d, CB_IDS[3]); | ||
| 77 | REQUIRE(100 == core_timing.GetDowncount()); | ||
| 78 | core_timing.ScheduleEvent(1200, cb_e, CB_IDS[4]); | ||
| 79 | REQUIRE(100 == core_timing.GetDowncount()); | ||
| 80 | |||
| 81 | AdvanceAndCheck(core_timing, 3, 400); | ||
| 82 | AdvanceAndCheck(core_timing, 1, 300); | ||
| 83 | AdvanceAndCheck(core_timing, 2, 200); | ||
| 84 | AdvanceAndCheck(core_timing, 0, 200); | ||
| 85 | AdvanceAndCheck(core_timing, 4, MAX_SLICE_LENGTH); | ||
| 86 | } | ||
| 87 | |||
| 88 | TEST_CASE("CoreTiming[Threadsave]", "[core]") { | ||
| 89 | ScopeInit guard; | ||
| 90 | auto& core_timing = guard.core_timing; | ||
| 91 | |||
| 92 | Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>); | ||
| 93 | Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>); | ||
| 94 | Core::Timing::EventType* cb_c = core_timing.RegisterEvent("callbackC", CallbackTemplate<2>); | ||
| 95 | Core::Timing::EventType* cb_d = core_timing.RegisterEvent("callbackD", CallbackTemplate<3>); | ||
| 96 | Core::Timing::EventType* cb_e = core_timing.RegisterEvent("callbackE", CallbackTemplate<4>); | ||
| 97 | |||
| 98 | // Enter slice 0 | ||
| 99 | core_timing.Advance(); | ||
| 100 | |||
| 101 | // D -> B -> C -> A -> E | ||
| 102 | core_timing.ScheduleEvent(1000, cb_a, CB_IDS[0]); | ||
| 103 | // Manually force since ScheduleEvent doesn't call it | ||
| 104 | core_timing.ForceExceptionCheck(1000); | ||
| 105 | REQUIRE(1000 == core_timing.GetDowncount()); | ||
| 106 | core_timing.ScheduleEvent(500, cb_b, CB_IDS[1]); | ||
| 107 | // Manually force since ScheduleEvent doesn't call it | ||
| 108 | core_timing.ForceExceptionCheck(500); | ||
| 109 | REQUIRE(500 == core_timing.GetDowncount()); | ||
| 110 | core_timing.ScheduleEvent(800, cb_c, CB_IDS[2]); | ||
| 111 | // Manually force since ScheduleEvent doesn't call it | ||
| 112 | core_timing.ForceExceptionCheck(800); | ||
| 113 | REQUIRE(500 == core_timing.GetDowncount()); | ||
| 114 | core_timing.ScheduleEvent(100, cb_d, CB_IDS[3]); | ||
| 115 | // Manually force since ScheduleEvent doesn't call it | ||
| 116 | core_timing.ForceExceptionCheck(100); | ||
| 117 | REQUIRE(100 == core_timing.GetDowncount()); | ||
| 118 | core_timing.ScheduleEvent(1200, cb_e, CB_IDS[4]); | ||
| 119 | // Manually force since ScheduleEvent doesn't call it | ||
| 120 | core_timing.ForceExceptionCheck(1200); | ||
| 121 | REQUIRE(100 == core_timing.GetDowncount()); | ||
| 122 | |||
| 123 | AdvanceAndCheck(core_timing, 3, 400); | ||
| 124 | AdvanceAndCheck(core_timing, 1, 300); | ||
| 125 | AdvanceAndCheck(core_timing, 2, 200); | ||
| 126 | AdvanceAndCheck(core_timing, 0, 200); | ||
| 127 | AdvanceAndCheck(core_timing, 4, MAX_SLICE_LENGTH); | ||
| 128 | } | ||
| 129 | |||
| 130 | namespace SharedSlotTest { | ||
| 131 | static unsigned int counter = 0; | ||
| 132 | |||
| 133 | template <unsigned int ID> | ||
| 134 | void FifoCallback(u64 userdata, s64 cycles_late) { | ||
| 135 | static_assert(ID < CB_IDS.size(), "ID out of range"); | ||
| 136 | callbacks_ran_flags.set(ID); | ||
| 137 | REQUIRE(CB_IDS[ID] == userdata); | ||
| 138 | REQUIRE(ID == counter); | ||
| 139 | REQUIRE(lateness == cycles_late); | ||
| 140 | ++counter; | ||
| 141 | } | ||
| 142 | } // namespace SharedSlotTest | ||
| 143 | |||
| 144 | TEST_CASE("CoreTiming[SharedSlot]", "[core]") { | ||
| 145 | using namespace SharedSlotTest; | ||
| 146 | |||
| 147 | ScopeInit guard; | ||
| 148 | auto& core_timing = guard.core_timing; | ||
| 149 | |||
| 150 | Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", FifoCallback<0>); | ||
| 151 | Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", FifoCallback<1>); | ||
| 152 | Core::Timing::EventType* cb_c = core_timing.RegisterEvent("callbackC", FifoCallback<2>); | ||
| 153 | Core::Timing::EventType* cb_d = core_timing.RegisterEvent("callbackD", FifoCallback<3>); | ||
| 154 | Core::Timing::EventType* cb_e = core_timing.RegisterEvent("callbackE", FifoCallback<4>); | ||
| 155 | |||
| 156 | core_timing.ScheduleEvent(1000, cb_a, CB_IDS[0]); | ||
| 157 | core_timing.ScheduleEvent(1000, cb_b, CB_IDS[1]); | ||
| 158 | core_timing.ScheduleEvent(1000, cb_c, CB_IDS[2]); | ||
| 159 | core_timing.ScheduleEvent(1000, cb_d, CB_IDS[3]); | ||
| 160 | core_timing.ScheduleEvent(1000, cb_e, CB_IDS[4]); | ||
| 161 | |||
| 162 | // Enter slice 0 | ||
| 163 | core_timing.Advance(); | ||
| 164 | REQUIRE(1000 == core_timing.GetDowncount()); | ||
| 165 | |||
| 166 | callbacks_ran_flags = 0; | ||
| 167 | counter = 0; | ||
| 168 | lateness = 0; | ||
| 169 | core_timing.AddTicks(core_timing.GetDowncount()); | ||
| 170 | core_timing.Advance(); | ||
| 171 | REQUIRE(MAX_SLICE_LENGTH == core_timing.GetDowncount()); | ||
| 172 | REQUIRE(0x1FULL == callbacks_ran_flags.to_ullong()); | ||
| 173 | } | ||
| 174 | |||
| 175 | TEST_CASE("Core::Timing[PredictableLateness]", "[core]") { | ||
| 176 | ScopeInit guard; | ||
| 177 | auto& core_timing = guard.core_timing; | ||
| 178 | |||
| 179 | Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>); | ||
| 180 | Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>); | ||
| 181 | |||
| 182 | // Enter slice 0 | ||
| 183 | core_timing.Advance(); | ||
| 184 | |||
| 185 | core_timing.ScheduleEvent(100, cb_a, CB_IDS[0]); | ||
| 186 | core_timing.ScheduleEvent(200, cb_b, CB_IDS[1]); | ||
| 187 | |||
| 188 | AdvanceAndCheck(core_timing, 0, 90, 10, -10); // (100 - 10) | ||
| 189 | AdvanceAndCheck(core_timing, 1, MAX_SLICE_LENGTH, 50, -50); | ||
| 190 | } | ||
| 191 | |||
| 192 | namespace ChainSchedulingTest { | ||
| 193 | static int reschedules = 0; | ||
| 194 | |||
| 195 | static void RescheduleCallback(Core::Timing::CoreTiming& core_timing, u64 userdata, | ||
| 196 | s64 cycles_late) { | ||
| 197 | --reschedules; | ||
| 198 | REQUIRE(reschedules >= 0); | ||
| 199 | REQUIRE(lateness == cycles_late); | ||
| 200 | |||
| 201 | if (reschedules > 0) { | ||
| 202 | core_timing.ScheduleEvent(1000, reinterpret_cast<Core::Timing::EventType*>(userdata), | ||
| 203 | userdata); | ||
| 204 | } | ||
| 205 | } | ||
| 206 | } // namespace ChainSchedulingTest | ||
| 207 | |||
| 208 | TEST_CASE("CoreTiming[ChainScheduling]", "[core]") { | ||
| 209 | using namespace ChainSchedulingTest; | ||
| 210 | |||
| 211 | ScopeInit guard; | ||
| 212 | auto& core_timing = guard.core_timing; | ||
| 213 | |||
| 214 | Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>); | ||
| 215 | Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>); | ||
| 216 | Core::Timing::EventType* cb_c = core_timing.RegisterEvent("callbackC", CallbackTemplate<2>); | ||
| 217 | Core::Timing::EventType* cb_rs = core_timing.RegisterEvent( | ||
| 218 | "callbackReschedule", [&core_timing](u64 userdata, s64 cycles_late) { | ||
| 219 | RescheduleCallback(core_timing, userdata, cycles_late); | ||
| 220 | }); | ||
| 221 | |||
| 222 | // Enter slice 0 | ||
| 223 | core_timing.Advance(); | ||
| 224 | |||
| 225 | core_timing.ScheduleEvent(800, cb_a, CB_IDS[0]); | ||
| 226 | core_timing.ScheduleEvent(1000, cb_b, CB_IDS[1]); | ||
| 227 | core_timing.ScheduleEvent(2200, cb_c, CB_IDS[2]); | ||
| 228 | core_timing.ScheduleEvent(1000, cb_rs, reinterpret_cast<u64>(cb_rs)); | ||
| 229 | REQUIRE(800 == core_timing.GetDowncount()); | ||
| 230 | |||
| 231 | reschedules = 3; | ||
| 232 | AdvanceAndCheck(core_timing, 0, 200); // cb_a | ||
| 233 | AdvanceAndCheck(core_timing, 1, 1000); // cb_b, cb_rs | ||
| 234 | REQUIRE(2 == reschedules); | ||
| 235 | |||
| 236 | core_timing.AddTicks(core_timing.GetDowncount()); | ||
| 237 | core_timing.Advance(); // cb_rs | ||
| 238 | REQUIRE(1 == reschedules); | ||
| 239 | REQUIRE(200 == core_timing.GetDowncount()); | ||
| 240 | |||
| 241 | AdvanceAndCheck(core_timing, 2, 800); // cb_c | ||
| 242 | |||
| 243 | core_timing.AddTicks(core_timing.GetDowncount()); | ||
| 244 | core_timing.Advance(); // cb_rs | ||
| 245 | REQUIRE(0 == reschedules); | ||
| 246 | REQUIRE(MAX_SLICE_LENGTH == core_timing.GetDowncount()); | ||
| 247 | } | ||