LUTE is a language to query AADL models and help designer to check model structure and system requirements. It is composed of different functions to query the components hierarchy as well as their characteristics (features, connections, etc.) and properties.
The language uses a theorem approach with a notation similar to mathematics. You can browse the component hierarchy using the foreach statement and define set. A set is a list of unordered components or values. The languages defines a predefined collection of sets and users can define their own.
Let's consider the following example :
theorem Memories_Properties foreach s in System_Set do foreach mainmem in {m in Memory_Set | Is_Direct_Subcomponent_Of (m, s)} do check (Property_Exists (mainmem,"Byte_Count")); end;
In the following, we browse the System_Set predefined set that contains all system components. Then, for each system component, we build a new set that contains all memory components contained in the system component under analysis. Then, for each memory component of this set, we check that the property Byte_Count is defined.
LUTE comes with a dedicated menu that proposes different options :
To run LUTE on your model, select the system implementation of your root system instance in the outline view and then, select the LUTE menu as shown in the following picture.
LUTE comes with its own console to help you editing your theorem. You can write your own theorem or just pick one predefined theorem in the list (and potentially improve/refine it), as shown in the following picture.
The following check that each process is bound to a processor and a memory.
theorem Partitions_Bindings foreach prs in Process_Set do segments := {x in Memory_Set | Is_Bound_To (prs, x)}; runtimes := {y in Processor_Set | Is_Bound_To (prs, y)}; check ( (Cardinal (segments) = 1 ) and (Cardinal (runtimes) = 1 )); end;
The following process check that for each process, the memory required by the thread can be provided by the memory component associated with the process.
theorem check_memory_requirements_partitions foreach prs in Process_Set do Thrs := {x in Thread_Set | Is_Direct_Subcomponent_Of (x, prs)}; mems := {x in Memory_Set | Is_Bound_To (prs, x)}; check ((Sum (Property (Thrs, "Source_Stack_Size")) + Sum (Property (Thrs, "Source_Data_Size")) + Sum (Property (Thrs, "Source_Code_Size"))) < (Sum (Property (mems, "byte_count"))) ); end;
The following theorem checks that two connected partitions have the same criticality level. The criticality level is defined on the virtual processor bound to each process.
theorem safety foreach Conn in Connection_Set do foreach P_Src in {x in Process_Set | Owner (Source(Conn)) = x} do foreach P_Dst in {y in Process_Set | Owner (Destination(Conn)) = y} do foreach Runtime_Src in {w in Virtual_Processor_Set | Is_Bound_To (P_Src, w)} do foreach Runtime_Dst in {z in Virtual_Processor_Set | Is_Bound_To (P_Dst, z)} do check ( (Property (Runtime_Src, "ARINC653::Criticality")) = (Property (Runtime_Dst, "ARINC653::Criticality"))); end;
theorem checkfamily foreach p in { element in Processor_Set | Is_Of_Type (element, "e500mc")} do check Property_Exists (p, "Processor_Properties::Processor_Family"); end;