diff --git a/docs/documentation/building_a_simulation/Simulation-Definition-File.md b/docs/documentation/building_a_simulation/Simulation-Definition-File.md index becbd673..d5911819 100644 --- a/docs/documentation/building_a_simulation/Simulation-Definition-File.md +++ b/docs/documentation/building_a_simulation/Simulation-Definition-File.md @@ -377,7 +377,10 @@ This section of the S_define (encapsulated by "job_class_order{...};) can be use scheduled loop job class order. The user may simply re-order the existing job classes that exist or can specify a new set of scheduled loop job classes. Job classes that are eligible for reassignment are listed in Table SD_1 between automatic and automatic_last inclusive. The order they are shown -in the table is the default ordering. +in the table is the default ordering. Note that if the user provides an ordering, classes that are +not included in the ordering (excluding automatic and automatic_last) will not be handled by any scheduler, + and therefore not executed in the sim. + ```C++ job_class_order { diff --git a/libexec/trick/pm/parse_s_define.pm b/libexec/trick/pm/parse_s_define.pm index c0313c50..d05b8ff8 100644 --- a/libexec/trick/pm/parse_s_define.pm +++ b/libexec/trick/pm/parse_s_define.pm @@ -20,6 +20,8 @@ use Text::Balanced qw(extract_bracketed); use html ; use get_paths ; +no warnings ; + my ($integ_loop_def , $collect_def , $vcollect_def); my ($job_class_order_def ) ; my ($sim_class_def , $sim_class_job_def , $instantiation_def , $create_connections_def) ; @@ -943,6 +945,9 @@ sub preparse_job_class_order($$) { return ; } + # Scheduled loop classes that should not be reordered + my @non_reorderable_classes = qw(logging data_record system_checkpoint system_advance_sim_time system_moding integ_loop); + # get a list of classes ($class_text) = @{$job_class_order_structs}[0] =~ /{(.*?)}/sx ; $class_text =~ s/^\s+|\s+$//gs ; @@ -955,26 +960,28 @@ sub preparse_job_class_order($$) { edit_and_exit("CP bad job class order" , "$s_define_file" , 1 ) ; } $temp_hash{$c}++ ; + + if ($c ~~ @non_reorderable_classes) { + trick_print($$sim_ref{fh}, "\nCP ERROR:\n Job class \"$c\" cannot be reordered by job_class_order.\n" , "title_red" , $$sim_ref{args}{v} ) ; + edit_and_exit("CP bad job class order" , "$s_define_file" , 1 ) ; + } } # save the new order @{$$sim_ref{user_class_order}} = @class_list ; - # push on the advance_sim_time class last if not specified - if ( !exists $temp_hash{data_record} ) { - push @{$$sim_ref{user_class_order}} , "data_record" ; + # push on classes important to trick system function if not specified + if ( !exists $temp_hash{automatic} ) { + unshift @{$$sim_ref{user_class_order}} , "automatic" ; } - if ( !exists $temp_hash{system_checkpoint} ) { - push @{$$sim_ref{user_class_order}} , "system_checkpoint" ; + if ( !exists $temp_hash{automatic_last} ) { + push @{$$sim_ref{user_class_order}} , "automatic_last" ; } - if ( !exists $temp_hash{system_advance_sim_time} ) { - push @{$$sim_ref{user_class_order}} , "system_advance_sim_time" ; - } - - if ( !exists $temp_hash{system_moding} ) { - push @{$$sim_ref{user_class_order}} , "system_moding" ; + # Push on the rest of the non-reorderable system job classes + foreach my $c ( @non_reorderable_classes ) { + push @{$$sim_ref{user_class_order}} , $c ; } } diff --git a/test/SIM_job_class_order/RUN_test/input.py b/test/SIM_job_class_order/RUN_test/input.py new file mode 100644 index 00000000..064838e8 --- /dev/null +++ b/test/SIM_job_class_order/RUN_test/input.py @@ -0,0 +1,3 @@ + + +trick.stop(10); diff --git a/test/SIM_job_class_order/S_define b/test/SIM_job_class_order/S_define new file mode 100644 index 00000000..b2187c18 --- /dev/null +++ b/test/SIM_job_class_order/S_define @@ -0,0 +1,48 @@ +/************************TRICK HEADER************************* +PURPOSE: + () +LIBRARY DEPENDENCIES: +*************************************************************/ + +#include "sim_objects/default_trick_sys.sm" + +##include "starter.h" + +class StarterSimObject : public Trick::SimObject { + + public: + Starter starter; + + StarterSimObject() { + ("top_of_frame") starter.top (); + + (0.5, "scheduled") starter.sched (); + (0.5, "my_class") starter.custom (); + + ("derivative") starter.deriv(); + ("integration") trick_ret = starter.integ() ; + + ("automatic") starter.automatic(); + ("automatic_last") starter.automatic_last(); + + + ("end_of_frame") starter.end (); + + ("shutdown") starter.test_calls (); + + } +}; + +StarterSimObject starterSimObject; + +job_class_order { + my_class , + scheduled +}; + +IntegLoop dyn_integloop(0.1) starterSimObject; + +void create_connections() { + dyn_integloop.getIntegrator(Runge_Kutta_4, 2); +} + diff --git a/test/SIM_job_class_order/S_overrides.mk b/test/SIM_job_class_order/S_overrides.mk new file mode 100644 index 00000000..016cadcd --- /dev/null +++ b/test/SIM_job_class_order/S_overrides.mk @@ -0,0 +1,3 @@ + +TRICK_CFLAGS += -I./models +TRICK_CXXFLAGS += -I./models -std=c++11 diff --git a/test/SIM_job_class_order/models/starter.cpp b/test/SIM_job_class_order/models/starter.cpp new file mode 100644 index 00000000..ff7b51cb --- /dev/null +++ b/test/SIM_job_class_order/models/starter.cpp @@ -0,0 +1,76 @@ +#include "starter.h" +#include +#include "trick/exec_proto.hh" +#include "trick/exec_proto.h" + +void Starter::sched () { + sched_calls++; +} + +void Starter::custom () { + custom_calls++; +} + +void Starter::top () { + top_calls++; +} + +void Starter::automatic () { + + Trick::JobData * thisJob = exec_get_curr_job() ; + thisJob->set_next_call_time(exec_get_time_tics() + exec_get_time_tic_value()); + automatic_calls++; +} + +void Starter::automatic_last () { + + Trick::JobData * thisJob = exec_get_curr_job() ; + thisJob->set_next_call_time(exec_get_time_tics() + exec_get_time_tic_value()); + + automatic_last_calls++; +} + +void Starter::end() { + end_calls++; +} + +void Starter::deriv() { + deriv_calls++; +} + +int Starter::integ() { + integ_calls++; + + return 0; +} + +void Starter::test_calls() { + if (top_calls == 0) { + exec_terminate_with_return(1, __FILE__, __LINE__, "top_of_frame job never called"); + } + + if (custom_calls == 0) { + exec_terminate_with_return(1, __FILE__, __LINE__, "custom job never called"); + } + + if (sched_calls == 0) { + exec_terminate_with_return(1, __FILE__, __LINE__, "scheduled job never called"); + } + + if (automatic_calls == 0) { + exec_terminate_with_return(1, __FILE__, __LINE__, "automatic job never called"); + } + + if (automatic_last_calls == 0) { + exec_terminate_with_return(1, __FILE__, __LINE__, "automatic_last job never called"); + } + + if (deriv_calls == 0) { + exec_terminate_with_return(1, __FILE__, __LINE__, "derivative job never called"); + } + + if (integ_calls == 0) { + exec_terminate_with_return(1, __FILE__, __LINE__, "integration job never called"); + } + +} diff --git a/test/SIM_job_class_order/models/starter.h b/test/SIM_job_class_order/models/starter.h new file mode 100644 index 00000000..82ebcdb5 --- /dev/null +++ b/test/SIM_job_class_order/models/starter.h @@ -0,0 +1,33 @@ +/************************************************************************* +PURPOSE: (Starter class) +LIBRARY DEPENDENCY: + ( + (starter.cpp) + ) +**************************************************************************/ + +#include + +class Starter { +public: + Starter() {} + + void sched(); + void custom(); + void top(); + void end(); + void automatic(); + void automatic_last(); + void deriv(); + int integ(); + void test_calls(); + + int sched_calls = 0; + int custom_calls = 0; + int top_calls = 0; + int automatic_calls = 0; + int automatic_last_calls = 0; + int deriv_calls = 0; + int integ_calls = 0; + int end_calls = 0; +}; diff --git a/test_sims.yml b/test_sims.yml index 777e60ba..a5fb74ff 100644 --- a/test_sims.yml +++ b/test_sims.yml @@ -196,6 +196,13 @@ SIM_earlyterm: runs: RUN_test/input.py: returns: 0 +SIM_job_class_order: + path: test/SIM_job_class_order + build_command: "trick-CP -t" + binary: "T_main_{cpu}_test.exe" + runs: + RUN_test/input.py: + returns: 0 # Special cases