diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb396ced..6bce4eba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,7 +24,7 @@ set(rscore_srcs mm/buddy/checkpoint.c mm/model_allocator.c mm/msg_allocator.c - parallel/parallel.c + parallel/timewarp.c serial/serial.c) if(MPI_FOUND) diff --git a/src/ROOT-Sim.h b/src/ROOT-Sim.h index d4b76a30..8b861e55 100644 --- a/src/ROOT-Sim.h +++ b/src/ROOT-Sim.h @@ -170,6 +170,11 @@ enum log_level { LOG_SILENT //!< Emit no messages during the simulation. }; +enum synchronization_algorithm { + SERIAL = 1, //!< The simulation runs on the serial runtime + TIME_WARP, //!< The simulation runs using the optimistic Time Warp algorithm +}; + /// A set of configurable values used by other modules struct simulation_configuration { /// The number of LPs to be used in the simulation @@ -190,7 +195,12 @@ struct simulation_configuration { unsigned ckpt_interval; /// If set, worker threads are bound to physical cores bool core_binding; - /// If set, the simulation will run on the serial runtime + /// Specify what synchronization algorithm we are using + enum synchronization_algorithm synchronization; + /** + * @deprecated since 3.1.0 + * If set, the simulation will run on the serial runtime + */ bool serial; /// Function pointer to the dispatching function ProcessEvent_t dispatcher; diff --git a/src/gvt/termination.c b/src/gvt/termination.c index 74d389cb..3ef725f6 100644 --- a/src/gvt/termination.c +++ b/src/gvt/termination.c @@ -86,7 +86,7 @@ void termination_on_gvt(const simtime_t current_gvt) */ void RootsimStop(void) { - if(global_config.serial) { + if(global_config.synchronization == SERIAL) { global_config.termination_time = -1.0; return; } diff --git a/src/init.c b/src/init.c index 38347780..71c4781e 100644 --- a/src/init.c +++ b/src/init.c @@ -17,7 +17,6 @@ #include -#include #include /// A flag to check if the core library has been initialized correctly @@ -54,14 +53,21 @@ static void print_config(void) else fprintf(stderr, "%lf\n", global_config.termination_time); - if(global_config.serial) { - fprintf(stderr, "Parallelism: sequential simulation\n"); - } else { + switch (global_config.synchronization) { + case SERIAL: + fprintf(stderr, "Parallelism: sequential simulation\n"); + break; + case TIME_WARP: + fprintf(stderr, "Parallelism: optimistic synchronization\n"); + break; + } + if (global_config.synchronization != SERIAL) { if(n_nodes > 1) fprintf(stderr, "Parallelism: %d MPI processes\n", n_nodes); else fprintf(stderr, "Parallelism: %u threads\n", global_config.n_threads); } + fprintf(stderr, "Thread-to-core binding: %s\n", global_config.core_binding ? "enabled" : "disabled"); fprintf(stderr, "GVT period: %u ms\n", global_config.gvt_period / 1000); @@ -69,7 +75,7 @@ static void print_config(void) if(global_config.ckpt_interval) { fprintf(stderr, "Checkpoint interval: %u events\n", global_config.ckpt_interval); } else { - if(!global_config.serial) + if(global_config.synchronization != SERIAL) fprintf(stderr, "Checkpoint interval: auto\n"); } @@ -108,9 +114,19 @@ int RootsimInit(const struct simulation_configuration *conf) return -1; } + if (global_config.serial) { + fprintf(stderr, "Using the deprecated `serial` configuration flag. Please swith to `.synchronization = SERIAL` instead\n"); + global_config.synchronization = SERIAL; + } + + if (unlikely(global_config.synchronization == 0)) { + fprintf(stderr, "No synchronization algorithm specified.\n"); + return -1; + } + log_init(global_config.logfile); - if(global_config.serial) + if(global_config.synchronization == SERIAL) global_config.n_threads = 1; else if(global_config.n_threads == 0) global_config.n_threads = thread_cores_count(); @@ -138,7 +154,7 @@ int RootsimRun(void) if(!configuration_done) return -1; - if(!global_config.serial) + if(global_config.synchronization == TIME_WARP) mpi_global_init(NULL, NULL); if(global_config.log_level < LOG_SILENT && !rid) { @@ -146,7 +162,7 @@ int RootsimRun(void) print_config(); } - if(global_config.serial) { + if(global_config.synchronization == SERIAL) { ret = serial_simulation(); } else { ret = parallel_simulation(); diff --git a/src/lp/process.c b/src/lp/process.c index 965430a9..acc597a8 100644 --- a/src/lp/process.c +++ b/src/lp/process.c @@ -62,7 +62,7 @@ static _Thread_local struct lp_msg *current_msg; void ScheduleNewEvent(const lp_id_t receiver, const simtime_t timestamp, const unsigned event_type, const void *payload, unsigned payload_size) { - if(unlikely(global_config.serial)) { + if(unlikely(global_config.synchronization == SERIAL)) { ScheduleNewEvent_serial(receiver, timestamp, event_type, payload, payload_size); return; } diff --git a/src/parallel/parallel.c b/src/parallel/timewarp.c similarity index 100% rename from src/parallel/parallel.c rename to src/parallel/timewarp.c diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 56ba32bf..9ac3ad43 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -41,7 +41,7 @@ test_program_link_libraries(sync rscore) # Integration tests test_program(correctness_serial integration/correctness/serial.c integration/correctness/application.c integration/correctness/functions.c integration/correctness/output_256.c) test_program_link_libraries(correctness_serial rscore) -test_program(correctness_parallel integration/correctness/parallel.c integration/correctness/application.c integration/correctness/functions.c integration/correctness/output_256.c) +test_program(correctness_parallel integration/correctness/timewarp.c integration/correctness/application.c integration/correctness/functions.c integration/correctness/output_256.c) test_program_link_libraries(correctness_parallel rscore) test_program(phold integration/phold.c) test_program_link_libraries(phold rscore) diff --git a/test/core/load.c b/test/core/load.c index 0e6319d6..a5611e08 100644 --- a/test/core/load.c +++ b/test/core/load.c @@ -27,10 +27,24 @@ static struct simulation_configuration conf = { .committed = NULL, }; +static const struct simulation_configuration no_synchronization = { + .lps = 1, + .dispatcher = DummyProcessEvent, + .committed = DummyCanEnd, +}; + static const struct simulation_configuration valid_conf = { - .lps = 1, - .dispatcher = DummyProcessEvent, - .committed = DummyCanEnd, + .lps = 1, + .dispatcher = DummyProcessEvent, + .committed = DummyCanEnd, + .synchronization = TIME_WARP, +}; + +static const struct simulation_configuration deprecated_conf = { + .lps = 1, + .dispatcher = DummyProcessEvent, + .committed = DummyCanEnd, + .serial = true, }; static int run_rootsim(_unused void *_) @@ -62,6 +76,13 @@ int main(void) test_xf("CanEnd not set", init_rootsim, &conf); test_xf("Start simulation with no CanEnd", run_rootsim, NULL); + memcpy(&conf, &no_synchronization, sizeof(conf)); + test_xf("No synchronization algorithm", init_rootsim, &conf); + test_xf("Start simulation with no synchronization algorithm", run_rootsim, NULL); + + memcpy(&conf, &deprecated_conf, sizeof(conf)); + test("Legacy serial flag", init_rootsim, &conf); + memcpy(&conf, &valid_conf, sizeof(conf)); test("Initialization", init_rootsim, &conf); test("Dummy simulation", run_rootsim, NULL); diff --git a/test/gvt/termination.c b/test/gvt/termination.c index d1f5b300..cf1726c0 100644 --- a/test/gvt/termination.c +++ b/test/gvt/termination.c @@ -30,10 +30,10 @@ static bool DummyCanEnd(_unused lp_id_t lid, _unused const void *state) } static struct simulation_configuration serial_conf = { - .lps = 1, .dispatcher = DummyProcessEvent, .committed = DummyCanEnd, .serial = true}; + .lps = 1, .dispatcher = DummyProcessEvent, .committed = DummyCanEnd, .synchronization = SERIAL}; static struct simulation_configuration parallel_conf = { - .lps = 1, .dispatcher = DummyProcessEvent, .committed = DummyCanEnd, .serial = false}; + .lps = 1, .dispatcher = DummyProcessEvent, .committed = DummyCanEnd, .synchronization = TIME_WARP}; static int force_termination_test(void *conf) { diff --git a/test/integration/correctness/serial.c b/test/integration/correctness/serial.c index 9292d7e8..11a5563f 100644 --- a/test/integration/correctness/serial.c +++ b/test/integration/correctness/serial.c @@ -19,7 +19,7 @@ struct simulation_configuration conf = { .stats_file = NULL, .ckpt_interval = 0, .core_binding = false, - .serial = true, + .synchronization = SERIAL, .dispatcher = ProcessEvent, .committed = CanEnd, }; diff --git a/test/integration/correctness/parallel.c b/test/integration/correctness/timewarp.c similarity index 95% rename from test/integration/correctness/parallel.c rename to test/integration/correctness/timewarp.c index 1f0946ab..069cd314 100644 --- a/test/integration/correctness/parallel.c +++ b/test/integration/correctness/timewarp.c @@ -19,7 +19,7 @@ struct simulation_configuration conf = { .stats_file = NULL, .ckpt_interval = 0, .core_binding = false, - .serial = false, + .synchronization = TIME_WARP, .dispatcher = ProcessEvent, .committed = CanEnd, }; diff --git a/test/integration/phold.c b/test/integration/phold.c index e97b6f82..99878970 100644 --- a/test/integration/phold.c +++ b/test/integration/phold.c @@ -106,7 +106,7 @@ struct simulation_configuration conf = { .stats_file = "phold", .ckpt_interval = 0, .core_binding = true, - .serial = false, + .synchronization = TIME_WARP, .dispatcher = ProcessEvent, .committed = CanEnd, }; diff --git a/test/log/rootsim_stats_test.py b/test/log/rootsim_stats_test.py index 618fca46..79d3e6ee 100644 --- a/test/log/rootsim_stats_test.py +++ b/test/log/rootsim_stats_test.py @@ -99,6 +99,7 @@ def test_stats_file(base_name, expected): if float(match[i + 1]) == 0: sys.exit(1) elif expected_field != match[i + 1]: + print(f"Error in {base_name} at field {i + 1}: expected '{expected_field}', got '{match[i + 1]}'") sys.exit(1) diff --git a/test/log/stats.c b/test/log/stats.c index 6eb8302f..7cd37b8c 100644 --- a/test/log/stats.c +++ b/test/log/stats.c @@ -39,7 +39,7 @@ static struct simulation_configuration conf = { .stats_file = NULL, .ckpt_interval = 0, .core_binding = true, - .serial = false, + .synchronization = TIME_WARP, .dispatcher = DummyProcessEvent, .committed = DummyCanEnd, };