(WIP) add CBD language
This commit is contained in:
parent
a89fe4bb71
commit
641e4b9810
6 changed files with 289 additions and 0 deletions
55
examples/cbd/models.py
Normal file
55
examples/cbd/models.py
Normal file
|
|
@ -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)
|
||||||
34
examples/cbd/models/m_fibonacci.od
Normal file
34
examples/cbd/models/m_fibonacci.od
Normal file
|
|
@ -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)
|
||||||
8
examples/cbd/models/m_fibonacci_initial.od
Normal file
8
examples/cbd/models/m_fibonacci_initial.od
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
d0s:IntState {
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
d1s:IntState {
|
||||||
|
state = 1;
|
||||||
|
}
|
||||||
|
:delay2State (d0 -> d0s)
|
||||||
|
:delay2State (d1 -> d1s)
|
||||||
129
examples/cbd/models/mm_design.od
Normal file
129
examples/cbd/models/mm_design.od
Normal file
|
|
@ -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)
|
||||||
55
examples/cbd/models/mm_runtime.od
Normal file
55
examples/cbd/models/mm_runtime.od
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
8
examples/cbd/runner.py
Normal file
8
examples/cbd/runner.py
Normal file
|
|
@ -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)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue