|
@@ -221,7 +221,7 @@ Element function get_enabled_transitions(model : Element, state : String, data :
|
|
if (bool_and(element_eq(attr, read_root()), read_attribute(model, transition, "after"))):
|
|
if (bool_and(element_eq(attr, read_root()), read_attribute(model, transition, "after"))):
|
|
if (dict_in(data["classes"][class]["timers"], transition)):
|
|
if (dict_in(data["classes"][class]["timers"], transition)):
|
|
// Registered timer already, let's check if it has expired
|
|
// Registered timer already, let's check if it has expired
|
|
- if (float_gt(data["classes"][class]["timers"][transition], time())):
|
|
|
|
|
|
+ if (float_gt(data["classes"][class]["timers"][transition], data["time_sim"])):
|
|
// Not enabled yet
|
|
// Not enabled yet
|
|
continue!
|
|
continue!
|
|
else:
|
|
else:
|
|
@@ -363,7 +363,6 @@ Boolean function step_class(model : Element, data : Element, class : String):
|
|
if (read_nr_out(transitions) > 0):
|
|
if (read_nr_out(transitions) > 0):
|
|
// Found an enabled transition, so store that one
|
|
// Found an enabled transition, so store that one
|
|
transition = random_choice(transitions)
|
|
transition = random_choice(transitions)
|
|
- log("Execute enabled transition: " + cast_v2s(read_attribute(model, list_read(transition, 0), "name")))
|
|
|
|
|
|
|
|
// Execute transition
|
|
// Execute transition
|
|
set_merge(new_states, execute_transition(model, data, class, transition))
|
|
set_merge(new_states, execute_transition(model, data, class, transition))
|
|
@@ -383,64 +382,9 @@ Boolean function step_class(model : Element, data : Element, class : String):
|
|
|
|
|
|
// Update states
|
|
// Update states
|
|
dict_overwrite(data["classes"][class], "states", new_states)
|
|
dict_overwrite(data["classes"][class], "states", new_states)
|
|
- //reschedule_timeouts(model, data, class)
|
|
|
|
|
|
|
|
return transitioned!
|
|
return transitioned!
|
|
|
|
|
|
-Void function reschedule_timeouts(model : Element, data : Element, class : String):
|
|
|
|
- Element timed_transitions
|
|
|
|
- Element old_timed_transitions
|
|
|
|
- String transition
|
|
|
|
- Element states
|
|
|
|
- String state
|
|
|
|
-
|
|
|
|
- timed_transitions = create_node()
|
|
|
|
- states = set_copy(data["classes"][class]["states"])
|
|
|
|
- log("Rescheduling timeouts")
|
|
|
|
-
|
|
|
|
- // Collect all timed transitions that are currently active
|
|
|
|
- while (read_nr_out(states) > 0):
|
|
|
|
- state = set_pop(states)
|
|
|
|
-
|
|
|
|
- // NOTE this set_merge does not eliminate duplicates, though this should happen later on when adding the timer (see other NOTE)
|
|
|
|
- set_merge(timed_transitions, filter_exists(model, allOutgoingAssociationInstances(model, state, "SCCD/transition"), "after"))
|
|
|
|
-
|
|
|
|
- // Remove timers that no longer exist
|
|
|
|
- old_timed_transitions = dict_keys(data["classes"][class]["timers"])
|
|
|
|
-
|
|
|
|
- log("Got timed transitions: " + set_to_string(timed_transitions))
|
|
|
|
- log("Got currently scheduled transitions: " + set_to_string(old_timed_transitions))
|
|
|
|
-
|
|
|
|
- while (read_nr_out(old_timed_transitions) > 0):
|
|
|
|
- transition = set_pop(old_timed_transitions)
|
|
|
|
- log("Check remove " + cast_v2s(transition))
|
|
|
|
-
|
|
|
|
- if (bool_not(set_in(timed_transitions, transition))):
|
|
|
|
- // Transition is no longer scheduled for any state, so remove
|
|
|
|
- dict_delete(data["classes"][class]["timers"], transition)
|
|
|
|
- log("Remove timer for transition " + cast_v2s(read_attribute(model, transition, "name")))
|
|
|
|
-
|
|
|
|
- // Schedule timers that are not already scheduled
|
|
|
|
- while (read_nr_out(timed_transitions) > 0):
|
|
|
|
- transition = set_pop(timed_transitions)
|
|
|
|
- log("Check add " + cast_v2s(transition))
|
|
|
|
-
|
|
|
|
- // NOTE Normally, a timer will not be added twice here, as the previous occurence will already find it
|
|
|
|
- if (bool_not(dict_in(data["classes"][class]["timers"], transition))):
|
|
|
|
- // Not yet scheduled this transition: do so now
|
|
|
|
- Element after
|
|
|
|
- Float after_duration
|
|
|
|
-
|
|
|
|
- after = read_attribute(model, transition, "after")
|
|
|
|
- after = get_func_AL_model(import_node(after))
|
|
|
|
- after_duration = after(data["classes"][class]["attributes"])
|
|
|
|
-
|
|
|
|
- dict_add(data["classes"][class]["timers"], transition, float_addition(data["start_time"], after_duration))
|
|
|
|
- log("Add timer for transition " + cast_v2s(read_attribute(model, transition, "name")))
|
|
|
|
- log("All done!")
|
|
|
|
-
|
|
|
|
- return !
|
|
|
|
-
|
|
|
|
String function get_parent(model : Element, state : String):
|
|
String function get_parent(model : Element, state : String):
|
|
Element tmp_set
|
|
Element tmp_set
|
|
tmp_set = allAssociationOrigins(model, state, "SCCD/composite_children")
|
|
tmp_set = allAssociationOrigins(model, state, "SCCD/composite_children")
|
|
@@ -605,7 +549,6 @@ Void function execute_actions(model : Element, source_states : Element, target_s
|
|
// First do exit actions
|
|
// First do exit actions
|
|
while (read_nr_out(exit) > 0):
|
|
while (read_nr_out(exit) > 0):
|
|
state = list_pop(exit, 0)
|
|
state = list_pop(exit, 0)
|
|
- log("EXIT " + cast_v2s(read_attribute(model, state, "name")))
|
|
|
|
|
|
|
|
// Set history when leaving
|
|
// Set history when leaving
|
|
if (read_type(model, state) == "SCCD/CompositeState"):
|
|
if (read_type(model, state) == "SCCD/CompositeState"):
|
|
@@ -635,15 +578,12 @@ Void function execute_actions(model : Element, source_states : Element, target_s
|
|
// Unschedule after events
|
|
// Unschedule after events
|
|
Element timed_transitions
|
|
Element timed_transitions
|
|
timed_transitions = filter_exists(model, allOutgoingAssociationInstances(model, state, "SCCD/transition"), "after")
|
|
timed_transitions = filter_exists(model, allOutgoingAssociationInstances(model, state, "SCCD/transition"), "after")
|
|
- log("Checking for unschedule of timed transitions: " + set_to_string(timed_transitions))
|
|
|
|
while (read_nr_out(timed_transitions) > 0):
|
|
while (read_nr_out(timed_transitions) > 0):
|
|
- log("Unschedule timer")
|
|
|
|
dict_delete(class_data["timers"], set_pop(timed_transitions))
|
|
dict_delete(class_data["timers"], set_pop(timed_transitions))
|
|
|
|
|
|
// Then do entry actions
|
|
// Then do entry actions
|
|
while (read_nr_out(entry) > 0):
|
|
while (read_nr_out(entry) > 0):
|
|
state = list_pop(entry, 0)
|
|
state = list_pop(entry, 0)
|
|
- log("ENTRY " + cast_v2s(read_attribute(model, state, "name")))
|
|
|
|
|
|
|
|
// Do entry actions
|
|
// Do entry actions
|
|
action = read_attribute(model, state, "onEntryScript")
|
|
action = read_attribute(model, state, "onEntryScript")
|
|
@@ -671,12 +611,10 @@ Void function execute_actions(model : Element, source_states : Element, target_s
|
|
String transition
|
|
String transition
|
|
Element after
|
|
Element after
|
|
timed_transitions = filter_exists(model, allOutgoingAssociationInstances(model, state, "SCCD/transition"), "after")
|
|
timed_transitions = filter_exists(model, allOutgoingAssociationInstances(model, state, "SCCD/transition"), "after")
|
|
- log("Checking for schedule of timed transitions: " + set_to_string(timed_transitions))
|
|
|
|
while (read_nr_out(timed_transitions) > 0):
|
|
while (read_nr_out(timed_transitions) > 0):
|
|
- log("Schedule timer")
|
|
|
|
transition = set_pop(timed_transitions)
|
|
transition = set_pop(timed_transitions)
|
|
after = get_func_AL_model(import_node(read_attribute(model, transition, "after")))
|
|
after = get_func_AL_model(import_node(read_attribute(model, transition, "after")))
|
|
- dict_add(class_data["timers"], transition, float_addition(data["start_time"], after(class_data["attributes"])))
|
|
|
|
|
|
+ dict_add(class_data["timers"], transition, float_addition(data["time_sim"], after(class_data["attributes"])))
|
|
|
|
|
|
return !
|
|
return !
|
|
|
|
|
|
@@ -690,12 +628,9 @@ Float function step(model : Element, data : Element):
|
|
Element keys
|
|
Element keys
|
|
String key
|
|
String key
|
|
|
|
|
|
- t_min = time() + 99999.0
|
|
|
|
|
|
+ t_min = 999999.0
|
|
classes = dict_keys(data["classes"])
|
|
classes = dict_keys(data["classes"])
|
|
|
|
|
|
- // TODO this should use simulated time or something
|
|
|
|
- dict_overwrite(data, "start_time", time())
|
|
|
|
-
|
|
|
|
transitioned = False
|
|
transitioned = False
|
|
while (read_nr_out(classes) > 0):
|
|
while (read_nr_out(classes) > 0):
|
|
class = set_pop(classes)
|
|
class = set_pop(classes)
|
|
@@ -713,17 +648,22 @@ Float function step(model : Element, data : Element):
|
|
|
|
|
|
if (transitioned):
|
|
if (transitioned):
|
|
// Do another step, as we can transition
|
|
// Do another step, as we can transition
|
|
- log("Transitioned, do another step!")
|
|
|
|
- return 0.0!
|
|
|
|
|
|
+ return data["time_sim"]!
|
|
else:
|
|
else:
|
|
- log("Idle!")
|
|
|
|
- return float_subtraction(t_min, data["start_time"])!
|
|
|
|
|
|
+ return t_min!
|
|
|
|
|
|
Boolean function main(model : Element):
|
|
Boolean function main(model : Element):
|
|
// Executes the provided SCCD model
|
|
// Executes the provided SCCD model
|
|
Element data
|
|
Element data
|
|
data = create_node()
|
|
data = create_node()
|
|
dict_add(data, "classes", create_node())
|
|
dict_add(data, "classes", create_node())
|
|
|
|
+
|
|
|
|
+ Float time_0
|
|
|
|
+ Float time_sim
|
|
|
|
+ Float time_wallclock
|
|
|
|
+ time_0 = time()
|
|
|
|
+ time_sim = 0.0
|
|
|
|
+ dict_add(data, "time_sim", 0.0)
|
|
|
|
|
|
// Prepare for input
|
|
// Prepare for input
|
|
output("Ready for input!")
|
|
output("Ready for input!")
|
|
@@ -740,7 +680,9 @@ Boolean function main(model : Element):
|
|
timeout = 0.0
|
|
timeout = 0.0
|
|
while (True):
|
|
while (True):
|
|
print_states(model, data)
|
|
print_states(model, data)
|
|
|
|
+ log("Request pause until " + cast_v2s(time() + timeout))
|
|
interrupt = input_timeout(timeout)
|
|
interrupt = input_timeout(timeout)
|
|
|
|
+ log("Got awakened at " + cast_v2s(time()))
|
|
|
|
|
|
if (value_eq(interrupt, "#EXIT#")):
|
|
if (value_eq(interrupt, "#EXIT#")):
|
|
// Stop execution
|
|
// Stop execution
|
|
@@ -753,12 +695,21 @@ Boolean function main(model : Element):
|
|
set_add(data["events"], create_tuple(interrupt, read_root()))
|
|
set_add(data["events"], create_tuple(interrupt, read_root()))
|
|
output("Processed event, ready for more!")
|
|
output("Processed event, ready for more!")
|
|
|
|
|
|
- timeout = step(model, data)
|
|
|
|
|
|
+ // Update the simulated time to the time of interrupt
|
|
|
|
+ time_sim = time() - time_0
|
|
|
|
+
|
|
|
|
+ // Else we timeout, and thus keep the time_sim
|
|
|
|
+ dict_overwrite(data, "time_sim", time_sim)
|
|
|
|
+
|
|
|
|
+ time_sim = step(model, data)
|
|
|
|
|
|
if (read_nr_out(data["classes"]) == 0):
|
|
if (read_nr_out(data["classes"]) == 0):
|
|
// No more active classes left: terminate!
|
|
// No more active classes left: terminate!
|
|
log("Finished SCCD execution")
|
|
log("Finished SCCD execution")
|
|
break!
|
|
break!
|
|
|
|
+
|
|
|
|
+ time_wallclock = time() - time_0
|
|
|
|
+ timeout = time_sim - time_wallclock
|
|
log("Pausing for " + cast_v2s(timeout))
|
|
log("Pausing for " + cast_v2s(timeout))
|
|
|
|
|
|
// We should never get here!
|
|
// We should never get here!
|