|
@@ -89,55 +89,138 @@ Element function sanitize(new_runtime_model : Element, old_runtime_model : Eleme
|
|
|
|
|
|
return new_runtime_model!
|
|
|
|
|
|
-Element function create_schedule(model : Element, start_time : Float):
|
|
|
- Element all_blocks
|
|
|
- Element visited
|
|
|
- Element to_visit
|
|
|
- Element incoming_links
|
|
|
+Element function create_schedule(model : Element):
|
|
|
+ // Create nice graph first
|
|
|
+ Element nodes
|
|
|
+ Element successors
|
|
|
String element_name
|
|
|
- String link
|
|
|
- String source
|
|
|
- String new_schedule
|
|
|
- Boolean ready
|
|
|
- Element schedule
|
|
|
-
|
|
|
- // TODO add algebraic loop detection (not solution...)
|
|
|
+ Element incoming_links
|
|
|
+ Element all_blocks
|
|
|
|
|
|
- schedule = create_node()
|
|
|
- all_blocks = allInstances(model, "Block")
|
|
|
- visited = create_node()
|
|
|
- to_visit = create_node()
|
|
|
+ nodes = allInstances(model, "Block")
|
|
|
+ successors = create_node()
|
|
|
+ while (read_nr_out(nodes) > 0):
|
|
|
+ element_name = set_pop(nodes)
|
|
|
+ if (bool_not(dict_in(successors, element_name))):
|
|
|
+ dict_add(successors, element_name, create_node())
|
|
|
|
|
|
- while (read_nr_out(all_blocks) > 0):
|
|
|
- element_name = set_pop(all_blocks)
|
|
|
- if (bool_not(set_in(visited, element_name))):
|
|
|
- list_append(to_visit, element_name)
|
|
|
-
|
|
|
- while (list_len(to_visit) > 0):
|
|
|
- element_name = list_read(to_visit, list_len(to_visit) - 1)
|
|
|
- if (is_nominal_instance(model, element_name, "ICBlock")):
|
|
|
- if (element_eq(read_attribute(model, element_name, "last_in"), read_root())):
|
|
|
- incoming_links = allIncomingAssociationInstances(model, element_name, "InitialCondition")
|
|
|
- else:
|
|
|
- incoming_links = create_node()
|
|
|
+ if (is_nominal_instance(model, element_name, "ICBlock")):
|
|
|
+ if (element_eq(read_attribute(model, element_name, "last_in"), read_root())):
|
|
|
+ incoming_links = allIncomingAssociationInstances(model, element_name, "InitialCondition")
|
|
|
else:
|
|
|
- incoming_links = allIncomingAssociationInstances(model, element_name, "Link")
|
|
|
- ready = True
|
|
|
+ incoming_links = create_node()
|
|
|
+ if (is_nominal_instance(model, element_name, "DerivatorBlock")):
|
|
|
+ Element new_incoming_links
|
|
|
+ new_incoming_links = allIncomingAssociationInstances(model, element_name, "Link")
|
|
|
+ while (read_nr_out(new_incoming_links) > 0):
|
|
|
+ list_append(incoming_links, set_pop(new_incoming_links))
|
|
|
+ else:
|
|
|
+ incoming_links = allIncomingAssociationInstances(model, element_name, "Link")
|
|
|
+
|
|
|
+ while (read_nr_out(incoming_links) > 0):
|
|
|
+ String source
|
|
|
+ source = readAssociationSource(model, set_pop(incoming_links))
|
|
|
+ if (bool_not(dict_in(successors, source))):
|
|
|
+ dict_add(successors, source, create_node())
|
|
|
+ set_add(successors[source], element_name)
|
|
|
+
|
|
|
+ Element values
|
|
|
+ values = create_node()
|
|
|
+ dict_add(values, "S", create_node())
|
|
|
+ dict_add(values, "index", 0)
|
|
|
+ dict_add(values, "indices", create_node())
|
|
|
+ dict_add(values, "lowlink", create_node())
|
|
|
+ dict_add(values, "onStack", create_node())
|
|
|
+ dict_add(values, "successors", successors)
|
|
|
+ dict_add(values, "SCC", create_node())
|
|
|
+
|
|
|
+ nodes = allInstances(model, "Block")
|
|
|
+ while (read_nr_out(nodes) > 0):
|
|
|
+ strongconnect(set_pop(nodes), values)
|
|
|
+
|
|
|
+ log("Computed SCC!")
|
|
|
+ log("Print list:")
|
|
|
+ Integer i
|
|
|
+ Integer j
|
|
|
+ Element lst
|
|
|
+ i = 0
|
|
|
+ while (i < read_nr_out(values["SCC"])):
|
|
|
+ log("[")
|
|
|
+ lst = list_read(values["SCC"], i)
|
|
|
+ j = 0
|
|
|
+ while (j < read_nr_out(lst)):
|
|
|
+ log(" " + cast_v2s(list_read(lst, j)))
|
|
|
+ j = j + 1
|
|
|
+ log("]")
|
|
|
+ i = i + 1
|
|
|
+ log("=== END")
|
|
|
+ return values["SCC"]!
|
|
|
+
|
|
|
+Void function dict_overwrite(d : Element, key : Element, value : Element):
|
|
|
+ if (dict_in(d, key)):
|
|
|
+ dict_delete(d, key)
|
|
|
+ if (dict_in_node(d, key)):
|
|
|
+ dict_delete_node(d, key)
|
|
|
+ dict_add(d, key, value)
|
|
|
+
|
|
|
+ return !
|
|
|
+
|
|
|
+Integer function min(a : Integer, b : Integer):
|
|
|
+ if (a < b):
|
|
|
+ return a!
|
|
|
+ else:
|
|
|
+ return b!
|
|
|
|
|
|
- while (list_len(incoming_links) > 0):
|
|
|
- link = set_pop(incoming_links)
|
|
|
- source = readAssociationSource(model, link)
|
|
|
- if (bool_not(set_in(visited, source))):
|
|
|
- list_append(to_visit, source)
|
|
|
- ready = False
|
|
|
+Void function strongconnect(v : String, values : Element):
|
|
|
+ if (dict_in(values["indices"], v)):
|
|
|
+ return!
|
|
|
+ log("Compute strong connected components")
|
|
|
+ log("Source: " + v)
|
|
|
|
|
|
- if (ready):
|
|
|
- list_append(schedule, element_name)
|
|
|
- list_delete(to_visit, list_len(to_visit) - 1)
|
|
|
- set_add(visited, element_name)
|
|
|
+ dict_overwrite(values["indices"], v, values["index"])
|
|
|
+ dict_overwrite(values["lowlink"], v, values["index"])
|
|
|
+ dict_overwrite(values, "index", cast_s2i(cast_v2s(values["index"])) + 1)
|
|
|
|
|
|
- log("Schedule length: " + cast_v2s(read_nr_out(schedule)))
|
|
|
- return schedule!
|
|
|
+ list_append(values["S"], v)
|
|
|
+ dict_overwrite(values["onStack"], v, True)
|
|
|
+
|
|
|
+ Element successors
|
|
|
+ String w
|
|
|
+ successors = values["successors"][v]
|
|
|
+ while (read_nr_out(successors) > 0):
|
|
|
+ w = set_pop(successors)
|
|
|
+ log("Found successor " + w)
|
|
|
+ if (bool_not(dict_in(values["indices"], w))):
|
|
|
+ strongconnect(w, values)
|
|
|
+ log("Old lowlink: " + cast_v2s(values["lowlink"][v]))
|
|
|
+ dict_overwrite(values["lowlink"], v, min(values["lowlink"][v], values["lowlink"][w]))
|
|
|
+ log("Set lowlink of " + v)
|
|
|
+ log(" to " + cast_v2s(values["lowlink"][v]))
|
|
|
+ elif (dict_in(values["onStack"], w)):
|
|
|
+ if (values["onStack"][w]):
|
|
|
+ dict_overwrite(values["lowlink"], v, min(values["lowlink"][v], values["indices"][w]))
|
|
|
+
|
|
|
+ if (value_eq(values["lowlink"][v], values["indices"][v])):
|
|
|
+ Element scc
|
|
|
+ scc = create_node()
|
|
|
+ // It will always differ now
|
|
|
+ w = list_pop(values["S"])
|
|
|
+ list_append(scc, w)
|
|
|
+ while (w != v):
|
|
|
+ w = list_pop(values["S"])
|
|
|
+ list_append(scc, w)
|
|
|
+ dict_overwrite(values["onStack"], w, False)
|
|
|
+ list_insert(values["SCC"], scc, 0)
|
|
|
+
|
|
|
+ return!
|
|
|
+
|
|
|
+Element function list_pop(list : Element):
|
|
|
+ Integer top
|
|
|
+ Element t
|
|
|
+ top = list_len(list) - 1
|
|
|
+ t = list_read(list, top)
|
|
|
+ list_delete(list, top)
|
|
|
+ return t!
|
|
|
|
|
|
String function readType(model : Element, name : String):
|
|
|
return reverseKeyLookup(model["metamodel"]["model"], dict_read_node(model["type_mapping"], model["model"][name]))!
|
|
@@ -274,8 +357,8 @@ Void function execute_cbd(design_model : Element):
|
|
|
else:
|
|
|
output("CONFORMANCE_FAIL")
|
|
|
|
|
|
- schedule_init = create_schedule(runtime_model, read_attribute(runtime_model, "time", "start_time"))
|
|
|
- schedule_run = create_schedule(runtime_model, -1)
|
|
|
+ schedule_init = create_schedule(runtime_model)
|
|
|
+ schedule_run = read_root()
|
|
|
|
|
|
while (True):
|
|
|
// If we are running, we just don't block for input and automatically do a step if there is no input
|
|
@@ -301,6 +384,8 @@ Void function execute_cbd(design_model : Element):
|
|
|
if (read_attribute(runtime_model, "time", "start_time") == read_attribute(runtime_model, "time", "current_time")):
|
|
|
schedule = schedule_init
|
|
|
else:
|
|
|
+ if (element_eq(schedule_run, read_root())):
|
|
|
+ schedule_run = create_schedule(runtime_model)
|
|
|
schedule = schedule_run
|
|
|
step_simulation(runtime_model, schedule)
|
|
|
else:
|
|
@@ -361,8 +446,10 @@ Void function execute_cbd(design_model : Element):
|
|
|
// Conforming, so do the retyping and sanitization step
|
|
|
runtime_model = retype_to_runtime(design_model)
|
|
|
runtime_model = sanitize(runtime_model, old_runtime_model)
|
|
|
- schedule_init = create_schedule(runtime_model, read_attribute(runtime_model, "time", "start_time"))
|
|
|
- schedule_run = create_schedule(runtime_model, -1)
|
|
|
+ log("Create schedule")
|
|
|
+ schedule_init = create_schedule(runtime_model)
|
|
|
+ log("Remove schedule")
|
|
|
+ schedule_run = read_root()
|
|
|
old_runtime_model = runtime_model
|
|
|
output("CONFORMANCE_OK")
|
|
|
else:
|