From 6cc88d3b02f822a79d22aaec726196fed21411b3 Mon Sep 17 00:00:00 2001 From: dingusdev Date: Thu, 15 Oct 2020 21:10:17 -0700 Subject: [PATCH] Started a timing mechanism --- CMakeLists.txt | 3 + execution/CMakeLists.txt | 6 ++ execution/interpreter_loop.cpp | 111 +++++++++++++++++++++++++++++++++ execution/interpreter_loop.h | 23 +++++++ main.cpp | 5 +- 5 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 execution/CMakeLists.txt create mode 100644 execution/interpreter_loop.cpp create mode 100644 execution/interpreter_loop.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a2973b8..d9dd0e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ endif() add_subdirectory("${PROJECT_SOURCE_DIR}/cpu/ppc/") add_subdirectory("${PROJECT_SOURCE_DIR}/debugger/") add_subdirectory("${PROJECT_SOURCE_DIR}/devices/") +add_subdirectory("${PROJECT_SOURCE_DIR}/execution") add_subdirectory("${PROJECT_SOURCE_DIR}/machines/") add_subdirectory("${PROJECT_SOURCE_DIR}/thirdparty/loguru/") @@ -57,6 +58,7 @@ file(GLOB TEST_SOURCES "${PROJECT_SOURCE_DIR}/cpu/ppc/test/*.cpp") add_executable(dingusppc ${SOURCES} $ $ $ + $ $ $) @@ -74,6 +76,7 @@ endif() add_executable(testppc ${TEST_SOURCES} $ $ $ + $ $ $) diff --git a/execution/CMakeLists.txt b/execution/CMakeLists.txt new file mode 100644 index 0000000..7e5ac0d --- /dev/null +++ b/execution/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories("${PROJECT_SOURCE_DIR}") + +file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") + +add_library(execution OBJECT ${SOURCES}) +target_link_libraries(execution PRIVATE cubeb) diff --git a/execution/interpreter_loop.cpp b/execution/interpreter_loop.cpp new file mode 100644 index 0000000..d9cb245 --- /dev/null +++ b/execution/interpreter_loop.cpp @@ -0,0 +1,111 @@ +/* +DingusPPC - The Experimental PowerPC Macintosh emulator +Copyright (C) 2018-20 divingkatae and maximum + (theweirdo) spatium + +(Contact divingkatae#1017 or powermax#2286 on Discord for more info) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include + +std::chrono::high_resolution_clock::time_point global; // global timer +std::chrono::high_resolution_clock::time_point cuda_timer; // updates every 11 ms +std::chrono::high_resolution_clock::time_point disp_timer; // updates every 16 ms + +using namespace std; + +const uint64_t cuda_update = 11000; +const uint64_t display_update = 16667; + +bool cuda_priority = 0; +bool disp_priority = 0; + +uint64_t elapsed_times[3] = {0}; // Elapsed time to reach a cycle (for display) +uint64_t routine_bench[3] = {0}; // Estimated time (in microseconds) to cycle through functions +uint64_t routine_runtime[3] = {0, cuda_update, display_update}; // Time to elapse before execution + +enum general_routine_timepoint { OVERALL_UPDATE_TIME, CUDA_UPDATE_TIME, DISPLAY_UPDATE_TIME }; + +void round_robin_bench() { + // Benchmark how much time elapses during a minimal CPU block + + std::chrono::high_resolution_clock::time_point dummy = std::chrono::high_resolution_clock::now(); + + for (int i = 0; i < 4096; i++) { + ppc_ori(); //execute NOPs as a basic test + } + + std::chrono::high_resolution_clock::time_point dummy2 = std::chrono::high_resolution_clock::now(); + routine_bench[OVERALL_UPDATE_TIME] = + std::chrono::duration_cast(dummy2 - dummy).count(); + std::cout << "Initial test: " << routine_bench[OVERALL_UPDATE_TIME] << endl; +} + +void interpreter_update_counters() { + std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); + elapsed_times[OVERALL_UPDATE_TIME] = + std::chrono::duration_cast(end - global).count(); + elapsed_times[CUDA_UPDATE_TIME] = + std::chrono::duration_cast(end - cuda_timer).count(); + elapsed_times[DISPLAY_UPDATE_TIME] = + std::chrono::duration_cast(end - disp_timer).count(); + + // Calculate if the threshold for updating a time-critical section has reached or is about to be reached + if ((elapsed_times[CUDA_UPDATE_TIME] + routine_bench[OVERALL_UPDATE_TIME]) >= + routine_runtime[CUDA_UPDATE_TIME]) { + cuda_priority = true; + elapsed_times[CUDA_UPDATE_TIME] = 0; + cuda_timer = end; + } + + if ((elapsed_times[DISPLAY_UPDATE_TIME] + routine_bench[OVERALL_UPDATE_TIME]) >= + routine_runtime[DISPLAY_UPDATE_TIME]) { + disp_priority = true; + elapsed_times[DISPLAY_UPDATE_TIME] = 0; + disp_timer = end; + } +} + +void interpreter_main_loop() { + // Round robin algorithm goes here + round_robin_bench(); + + global = std::chrono::high_resolution_clock::now(); + cuda_timer = global; + disp_timer = global; + + for (;;) { + if (cuda_priority) { + LOG_F(9, "Placeholder for Cuda Update function!\n"); + cuda_priority = false; + } + + if (disp_priority) { + LOG_F(9, "Placeholder for Display Update function! \n"); + disp_priority = false; + } + + ppc_exec(); + + interpreter_update_counters(); + } +} \ No newline at end of file diff --git a/execution/interpreter_loop.h b/execution/interpreter_loop.h new file mode 100644 index 0000000..e760826 --- /dev/null +++ b/execution/interpreter_loop.h @@ -0,0 +1,23 @@ +/* +DingusPPC - The Experimental PowerPC Macintosh emulator +Copyright (C) 2018-20 divingkatae and maximum + (theweirdo) spatium + +(Contact divingkatae#1017 or powermax#2286 on Discord for more info) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +void interpreter_update_counters(); +void interpreter_main_loop(); \ No newline at end of file diff --git a/main.cpp b/main.cpp index 7c88af1..7a66297 100644 --- a/main.cpp +++ b/main.cpp @@ -23,6 +23,7 @@ along with this program. If not, see . // This is where the magic begins #include "debugger/debugger.h" +#include "execution/interpreter_loop.h" #include "machines/machinefactory.h" #include "machines/machineproperties.h" #include "ppcemu.h" @@ -165,9 +166,7 @@ int main(int argc, char** argv) { switch (execution_mode) { case 0: - for (;;) { - ppc_exec(); - } + interpreter_main_loop(); break; case 1: enter_debugger();