diff --git a/examples/cbd/models.py b/examples/cbd/models.py new file mode 100644 index 0000000..775fca5 --- /dev/null +++ b/examples/cbd/models.py @@ -0,0 +1,55 @@ +import os +from framework.conformance import Conformance, render_conformance_check_result +from concrete_syntax.textual_od import parser + + +# get file contents as string +def read_file(filename): + dir = os.path.dirname(__file__) + with open(dir+'/'+filename) as file: + return file.read() + +# def parse_and_check(state, cs_file, mm): +# m_cs = read_file(cs_file) +# try: +# _parse_and_check(state, m_cs, mm) +# except Exception as e: +# e.add_note(f"While parsing '{cs_file}'") +# raise +# return m + +def parse_and_check(state, m_cs, mm, descr: str): + try: + m = parser.parse_od( + state, + m_text=m_cs, + mm=mm, + ) + conf = Conformance(state, m, mm) + errors = conf.check_nominal() + if len(errors) > 0: + raise Exception(render_conformance_check_result(errors)) + except Exception as e: + e.add_note("While parsing model " + descr) + raise + return m + +def get_metamodels(state, scd_mmm): + mm_cs = read_file('models/mm_design.od') + mm_rt_cs = mm_cs + read_file('models/mm_runtime.od') + + mm = parse_and_check(state, mm_cs, scd_mmm, "Design meta-model") + mm_rt = parse_and_check(state, mm_rt_cs, scd_mmm, "Runtime meta-model") + + return (mm, mm_rt) + +def get_fibonacci(state, scd_mmm): + mm, mm_rt = get_metamodels(state, scd_mmm) + + m_cs = read_file('models/m_fibonacci.od') + m_rt_initial_cs = m_cs + read_file('models/m_fibonacci_initial.od') + + m = parse_and_check(state, m_cs, mm, "Fibonacci model") + m_rt_initial = parse_and_check(state, m_rt_initial_cs, mm_rt, "Fibonacci initial state") + + return (mm, mm_rt, m, m_rt_initial) diff --git a/examples/cbd/models/m_fibonacci.od b/examples/cbd/models/m_fibonacci.od new file mode 100644 index 0000000..32b746a --- /dev/null +++ b/examples/cbd/models/m_fibonacci.od @@ -0,0 +1,34 @@ +adder:Function { + func = ``` + n2_out = in0 + in1 + ```; +} +n0_in:IntInPort +n1_in:IntInPort +n2_out:IntOutPort +:hasInPort (adder -> n0_in) +:hasInPort (adder -> n1_in) +:hasOutPort (adder -> n2_out) + + + +d0:Delay +d0_in:IntInPort +d0_out:IntOutPort +:hasInPort (d0 -> d0_in) +:hasOutPort (d0 -> d0_out) + + + +d1:Delay +d1_in:IntInPort +d1_out:IntOutPort +:hasInPort (d1 -> d1_in) +:hasOutPort (d1 -> d1_out) + + + +:intLink (n2_out -> d1_in) +:intLink (d1_out -> n1_in) +:intLink (d1_out -> d0_in) +:intLink (d1_out -> n0_in) diff --git a/examples/cbd/models/m_fibonacci_initial.od b/examples/cbd/models/m_fibonacci_initial.od new file mode 100644 index 0000000..b94bfe2 --- /dev/null +++ b/examples/cbd/models/m_fibonacci_initial.od @@ -0,0 +1,8 @@ +d0s:IntState { + state = 0; +} +d1s:IntState { + state = 1; +} +:delay2State (d0 -> d0s) +:delay2State (d1 -> d1s) diff --git a/examples/cbd/models/mm_design.od b/examples/cbd/models/mm_design.od new file mode 100644 index 0000000..c9d2446 --- /dev/null +++ b/examples/cbd/models/mm_design.od @@ -0,0 +1,129 @@ +Block:Class { + abstract = True; +} + +InPort:Class { + abstract = True; +} +OutPort:Class { + abstract = True; +} + +hasInPort:Association (Block -> InPort) { + # Every Port contained by exactly one Block: + source_lower_cardinality = 1; + source_upper_cardinality = 1; +} +hasOutPort:Association (Block -> OutPort) { + # Every Port contained by exactly one Block: + source_lower_cardinality = 1; + source_upper_cardinality = 1; +} + +link:Association (OutPort -> InPort) { + #abstract = True; + + # Every InPort connected to exactly one OutPort + source_lower_cardinality = 1; + source_upper_cardinality = 1; +} + + +# In- and Out-Ports are labeled: + +# hasInPort_label:AttributeLink (hasInPort -> String) { +# name = "label"; +# optional = False; +# } +# hasOutPort_label:AttributeLink (hasOutPort -> String) { +# name = "label"; +# optional = False; +# } + + + +# Function Block: pure function that computes outputs based on inputs + +Function:Class +:Inheritance (Function -> Block) + +Function_func:AttributeLink (Function -> ActionCode) { + name = "func"; + optional = False; +} + +DetailedFunction:Class +:Inheritance (DetailedFunction -> Function) + +VeryDetailedFunction:Class +:Inheritance (VeryDetailedFunction -> DetailedFunction) + + + +# Delay Block + +Delay:Class { + constraint = ``` + errors = [] + num_inports = len(get_outgoing(this, "hasInPort")) + num_outports = len(get_outgoing(this, "hasOutPort")) + if num_inports != 1: + errors.append(f"Delay block must have one inport, instead got {num_inports}") + in_type = None + else: + in_type = get_type_name(get_target(get_outgoing(this, "hasInPort")[0])) + if num_outports != 1: + errors.append(f"Delay block must have one inport, instead got {num_outports}") + out_type = None + else: + out_type = get_type_name(get_target(get_outgoing(this, "hasOutPort")[0])) + if in_type != None and out_type != None and in_type[0:3] != out_type[0:3]: + errors.append(f"Inport type ({in_type}) differs from outport type ({out_type})") + errors + ```; +} +:Inheritance (Delay -> Block) + + + + +# Object Diagrams are statically typed, so we must create in/out-ports, and MemorySlots for all primitive types: + + +# Port types + +BoolInPort:Class +IntInPort:Class +StrInPort:Class + +BoolOutPort:Class +IntOutPort:Class +StrOutPort:Class + +:Inheritance (BoolInPort -> InPort) +:Inheritance (IntInPort -> InPort) +:Inheritance (StrInPort -> InPort) + +:Inheritance (BoolOutPort -> OutPort) +:Inheritance (IntOutPort -> OutPort) +:Inheritance (StrOutPort -> OutPort) + +# Link types + +boolLink:Association (BoolOutPort -> BoolInPort) +intLink:Association (IntOutPort -> IntInPort) +strLink:Association (StrOutPort -> StrInPort) + +:Inheritance (boolLink -> link) +:Inheritance (intLink -> link) +:Inheritance (strLink -> link) + +# Delay block types + +BoolDelay:Class +IntDelay:Class +StrDelay:Class + +:Inheritance (BoolDelay -> Delay) +:Inheritance (IntDelay -> Delay) +:Inheritance (StrDelay -> Delay) diff --git a/examples/cbd/models/mm_runtime.od b/examples/cbd/models/mm_runtime.od new file mode 100644 index 0000000..9f2d14d --- /dev/null +++ b/examples/cbd/models/mm_runtime.od @@ -0,0 +1,55 @@ +# Link state ("signal") +# is optional: absent for yet-to-compute signals + +intLink_signal:AttributeLink (intLink -> Integer) { + name = "signal"; + optional = True; +} +boolLink_signal:AttributeLink (boolLink -> Boolean) { + name = "signal"; + optional = True; +} +strLink_signal:AttributeLink (strLink -> String) { + name = "signal"; + optional = True; +} + + + +# Delay block state +# mandatory - otherwise we cannot determine the output signal of a delay block + +State:Class { + abstract = True; +} + +delay2State:Association (Delay -> State) { + source_lower_cardinality = 1; + source_upper_cardinality = 1; + target_lower_cardinality = 1; + target_upper_cardinality = 1; +} + +BoolState:Class +IntState:Class +StrState:Class + +:Inheritance (BoolState -> State) +:Inheritance (IntState -> State) +:Inheritance (StrState -> State) + + +BoolState_state:AttributeLink (BoolState -> Boolean) { + name = "state"; + optional = False; +} + +IntState_state:AttributeLink (IntState -> Integer) { + name = "state"; + optional = False; +} + +StrState_state:AttributeLink (StrState -> String) { + name = "state"; + optional = False; +} diff --git a/examples/cbd/runner.py b/examples/cbd/runner.py new file mode 100644 index 0000000..2895137 --- /dev/null +++ b/examples/cbd/runner.py @@ -0,0 +1,8 @@ +from state.devstate import DevState +from bootstrap.scd import bootstrap_scd +import models + +state = DevState() +scd_mmm = bootstrap_scd(state) + +mm, mm_rt, m, m_rt_initial = models.get_fibonacci(state, scd_mmm) \ No newline at end of file