350 likes | 435 Views
Learn about LOTOS language fundamentals through worked examples and brief illustrations of process definitions, data types, and system specifications. Understand how parallel, choice, and sequential compositions are used in LOTOS for communication systems.
E N D
LOTOS introduced through a worked example (Drayton, Chetwynd, Blair circa 1990) • Communication systems form a large portion of safety critical systems • These systems are usually large and constantly evolving. • A number of formalisms and development languages of communication systems have been developed. • LOTOS (Language of Temporal Ordering Specification) is an international standard that lies heavily on the underlying Process Algebraic theory • LOTOS was accepted as an ISO standard in 1988
Brief examples - 1 • As an example, we could define the following two processes P_A[off_A, dial, connect] := off_A; dial; connect; … P_B[off_B, ring, connect] := ring; off_B; connect; … • This simple example corresponds to a normal telephone call setup. • If we want the previous processes to execute in parallel and to synchronize through their common action connect, we may write process P_A […] |[ connect ]| process P_B[…]
Brief Examples - 2 • Some execution sequences of the previous parallel composition of processes are off_A; dial; ring; off_B; connect; … off_A; ring; off_B; dial; connect; … ring; off_A; dial; off_B; connect; …
LOTOS language fundamentals • LOTOS language can be divided into two parts Behaviour – concepts such as parameter passing, choice non-determinism, sequential composition, etc. Data- concepts of sorts, operations, renaming, actualization • These will be further explained in the following slides
Parameter Passing • For example, off ! id1 binds the id of the phone that was picked up to the variable id1 • Similarly, the expression off ? any_id: id_sort accepts all id’s as parameters. This form is typically used in representing non-deterministic behaviour • It is possible to add arbitrarily many ! and ? operators to a single event. For example, dial ! id1 ? any_id:id_sort represents a situation where the phone id1 is picked up and it chooses non-deterministically a phone where to call.
Choice Operator • Any reasonable language should be able to represent a choice between possible futures. In LOTOS this is done through the choice operator []. dial ! ringtone; … [] dial ! engagedtone; … Represents a choice between behaviours. Each behaviour must end with a special exit or stop keyword.
Non-Determinism • For example dial ? any_id:id_sort represents non-deterministic behaviour where we bind an arbitrary identifier to the dial event
Example Process Definition • The following is an example of a process definition in LOTOS Process MakeCall [off, dial, connect, on] (phone_id:id_sort): exit := off ! dialtone ! phone_id; ((dial ! ringtone ! phone_id ? callee:id_sort; connect ! phone_id ! callee; on ! phone_id; exit) [] (dial ! engagedtone ! phone_id ? callee:id_sort; on ! phone_id; exit)) endproc
Data Types in LOTOS • The description of data is as important as the description of behaviour. The type definition is constructed as follows: type Identifier is … sorts …. opns ….. eqns …. • LOTOS has many predefined data types, such as NaturalNumber and Boolean
Data Types example • Operations and Defining Equations are defined as follows id_sort opns id1, id2, id3 : -> id_sort /* constants */ NatRep: id_sort -> nat /* going from id1 to 1 */ _eq_, _ne_ : id_sort, id_sort -> Boolean /* equality */ eqns of sort nat NatRep(id1) = succ(0); NatRep(id2) = succ(NatRep(id1)); NatRep(id3) = succ(NatRep(id2));
Data Types Example Continued • It is also possible to include variables in the defining equations forall x, y: id_sort ofsort bool x eq y = NatRep(x) eq NatRep(y); x ne y = not(x eq y);
Renaming a Data Type • LOTOS contains a predefined data type Set. If we want to utilize this to define a set (actually a list) of identifiers we have to declare a new data type and then give its actual definition • The declaration is done by type ListIds0 is Set renamedby sortnames ListIds for Set endtype • Then we must define the data type ListIds0 as follows type ListIds is ListIds0 actualizedby Identifier using sortnames id_sort for element bool for fbool nat for fnat endtype
Parallel Composition of Dependent Processes • If we want two processes to synchronize on ALL actions we may write Phones[…] || Exchange[…] • If we want to model interleaved behaviour (I.e. totally independent processes) we write process Phones[…] : noexit := Phone[….] (id1) ||| Phone[….] (id2) ||| Phone[….] (id3)
Sequential Composition of Processes • Some processes are related in such a way that the execution of one can start only after the other has finished (by the special action exit). In this case we talk of sequential composition • For example, we may write process Phone [….] (phone_id: id_sort): noexit := ( MakeCall[….] (phone_id) [] ReceiveCall[….] (phone_id) ) >> Phone[….] (phone_id) endproc
Complete LOTOS example – Multiphone System specification phone_system [off, on, dial, cancel, ring, stop_ring, connect] : noexit (* STANDARD LIBRARY TYPES INCLUDED *) library Boolean, NaturalNumber, Set, DecNatRepr endlib type Identifier is NaturalNumber sorts id_sort opns id1 (*! constructor), id2 (*! constructor), id3 (*! constructor), anything (*! constructor) : -> id_sort NatRep : id_sort -> Nat SystemPhone : id_sort -> Bool _eq_, _ne_, _lt_ : id_sort, id_sort -> Bool
Data Definitions - 2 eqns forall x, y : id_sort ofsort Nat NatRep(anything) = 0; NatRep(id1) = succ(0); NatRep(id2) = succ(NatRep(id1)); NatRep(id3) = succ(NatRep(id2)); Ofsort Bool SystemPhone(anything) = false; SystemPhone(x) = true; (* phones id1-3 are in system *) x eq anything = true; anything eq x = true; x eq y = NatRep(x) eq NatRep(y); x ne y = not(x eq y); x lt y = NatRep(x) lt NatRep(y); endtype
Data Definitions - 3 (* ------------------------------- *) type PhonePair is Identifier, DecNatRepr sorts PhonePair opns _to_ (*! constructor) : id_sort, id_sort -> PhonePair NatRep : PhonePair -> Nat first, second : PhonePair -> id_sort _eq_, _ne, _lt_ : PhonePair, PhonePair -> Bool
Data Definitions - 4 eqns forall a,b,c,d : id_sort, pair : PhonePair ofsort Nat NatRep(a to b) = (NatRep(a) * NatNum(1+Dec(0))) + NatRep(b); ofsort id_sort first(a to b) = a; second(a to b) = b; ofsort Bool (a to b) eq (c to d) = (a eq c) and (b eq d); (a to b) ne (c to d) = not((a eq c) and (b eq d)); (a to b) lt (c to d) = NatRep(a to b) lt NatRep (c to d); endtype
Data Definitions - 5 (* ----------------------------------------- *) type ListPairs0 is Set renamedby sortnames ListPairs for Set endtype type ListPairs1 is ListPairs0 actualizedby PhonePair using sortnames PhonePair for Element Bool for FBool Nat for FNat endtype
Data Definitions - 6 type ListPairs is ListPairs1 opns head : ListPairs -> PhonePair tail : ListPairs -> ListPairs fully_connect : id_sort, id_sort, ListPairs -> ListPairs fully_remove : id_sort, ListPairs -> ListPairs eqns forall x, y : id_sort, pair : PhonePair, list : ListPairs ofsort PhonePair (* note, head is never called with parameter {}. If it were would need something like "head({}) = Null" where null was a phone pair *) head(Cons(pair, list)) = pair; ofsort ListPairs tail({}) = {}; tail(Cons(pair, list)) = list;
Data Definitions - 6 fully_remove(x, list) = Remove (x to anything Remove(anything to x, list)); fully_connect(x,y, {}) = Insert(x to y, {}); x eq first(head(list)) => fully_connect(x,y,list) = Insert(second(head(list)) to y, Insert(head(list), fully_connect(x,y, tail(list)))); y eq first(head(list)) => fully_connect(x,y,list) = Insert(second(head(list)) to x, Insert(head(list), fully_connect(x,y,tail(list)))); (*... otherwise ...*) fully_connect(x, y, list) = Insert(head(list), fully_connect(x, y, tail(list))); endtype
Data Definitions - 7 (* ------------------------------------- *) type ListIds0 is Set renamedby sortnames ListIds for Set endtype type ListIds is ListIds0 actualizedby Identifier using sortnames id_sort for Element Bool for FBool Nat for FNat endtype
Data Definitions - 8 (* ------------------------------------------- *) type Signal is sorts Signal opns dialtone (*! constructor) ringtone (*! constructor) engagedtone (*! constructor) connect (*! constructor) after_ringtone (*! constructor) after_engaged_tone (*! constructor) endtype
Behaviour - 1 Behaviour Phones[off, on, dial, cancel, ring, stop_ring, connect] || Exchange[off, on, dial, cancel, ring, stop_ring, connect] ({} of ListIds, {} of ListPairs) where process Phones[off, on, dial, cancel, ring, stop_ring, connect] : noexit := Phone[off, on, dial, cancel, ring, stop_ring, connect](id1) ||| Phone[off, on, dial, cancel, ring, stop_ring, connect](id2) ||| Phone[off, on, dial, cancel, ring, stop_ring, connect](id3) endproc
Behaviour - 2 (* PHONE specifies the behaviour of a single phone *) process Phone[off, on, dial, cancel, ring, stop_ring, connect] (phone_id:id_sort) : noexit := ( MakeCall[off, on, dial, cancel, ring, stop_ring, connect] (phone_id) [] ReceiveCall[off, on, dial, cancel, ring, stop_ring, connect](phone_id)) >> Phone[off, on, dial, cancel, ring, stop_ring, connect](phone_id) endproc
Behaviour - 3 (* MAKECALL specifies the behaviour when someone makes a call *) process MakeCall[off, on, dial, cancel, ring, stop_ring, connect] (phone_id:id_sort) : exit := off !dialtone !phone_id; DialSomeone[off, on, dial, cancel, ring, stop_ring, connect] (phone_id) endproc
Behaviour - 4 (* RECEIVECALL specifies the behaviour when someone receives a call *) process ReceiveCall[off, on, dial, cancel, ring, stop_ring, connect] (phone_id:id_sort) : exit := ring ? caller : id_sort !phone_id; ((stop_ring !phone_id; exit ) [] (off ! connect ! caller ! phone_id; DialSomeone[off, on, dial, cancel, ring, stop_ring, connect] (phone_id) ) ) endproc
Behaviour - 5 (* DIALSOMEONE specifies the behaviour when one phone dials another *) process DialSomeone[off, on, dial, cancel, ring, stop_ring, connect] (phone_id:id_sort) : exit := ( dial !ringtone !phone_id ?callee:id_sort; NotEngaged[off, on, dial, cancel, ring, stop_ring, connect] (phone_id, callee)) [] ( dial !engagedtone !phone_id ?callee:id_sort; Engaged[off, on, dial, cancel, ring, stop_ring, connect] (phone_id, callee)) [] ( on !phone_id; exit ) endproc
Behaviour - 6 (* NOTENGAGED specifies the behaviour when the phone being dialled is not engaged *) process NotEngaged[off, on, dial, cancel, ring, stop_ring, connect] (phone_id, callee: id_sort) : exit := ( on !after_ringtone !phone_id !callee; exit ) [] ( connect ! phone_id ! callee; on !phone_id; exit; ) [] ( cancel !after_ringtone !phone_id !callee; DialSomeone[off, on, dial, cancel, ring, stop_ring, connect] (phone_id) ) endproc
Behaviour - 7 (* ENGAGED specifies the behaviour when the phone being dialled is engaged *) process Engaged[off, on, dial, cancel, ring, stop_ring, connect] (phone_id, callee : id_sort) : exit := ( cancel !after_engagedtone !phone_id; DialSomeone[off, on, dial, cancel, ring, stop_ring, connect] (phone_id) ) [] ( on !phone_id; exit ) endproc
Behaviour - 8 (* EXCHANGE specifies the behaviour to link the processes MakeCall and ReceiveCall in the correct way *) process Exchange[off, on, dial, cancel, ring, stop_ring, connect] (engaged: ListIds, connections: ListPairs) : noexit := SubExchange [off, on, dial, cancel, ring, stop_ring, connect] (engaged, connections) >> accept engaged:ListIds, connections:ListPairs in Exchange [off, on, dial, cancel, ring, stop_ring, connect] (engaged, connections) endproc
Behaviour - 9 (* SUBEXCHANGE specifies how the lists are to be updated with each possible action *) process SubExchange[off, on, dial, cancel, ring, stop_ring, connect] (engaged: ListIds, connections: ListPairs) : exit(ListIds, ListPairs) := (* ( off !dialtone ?phone_id:id_sort; *) ( off !dialtone !id1; exit(Insert(id1, engaged), connections)) [] ( on ?phone_id:id_sort; exit(Remove(phone_id, engaged), fully_remove(phone_id, connections))) [] ( on !after_ringtone ?from_id:id_sort ?to_id:id_sort; stop_ring !to_id; exit(Remove(from_id, engaged), fully_remove(from_id, connections)))
Behaviour - 10 [] (* (dial !ringtone ?from_id:id_sort ?to_id: id_sort) *) ( dial !ringtone !id1 ?to_id:id_sort [SystemPhone(to_id) and (to_id NotIn engaged)]; ring ! id1 ! to_id; exit(engaged, connections)) [] (*( dial !engagedtone ?from_id:id_sort ?to_id:id_sort)*) ( dial !engagedtone !id1 ?to_id:id_sort [SystemPhone(to_id) and (to_id IsIn engaged)]; exit(engaged, connections)) [] ( cancel !after_ringtone ?from_id:id_sort ?to_id:id_sort; stop_ring !to_id; exit(engaged,connections) )
Behaviour - 11 [] (off ! connect ? from_id:id_sort ? to_id:id_sort connect ! from_id ! to_id; exit(Insert(to_id, engaged), fully_connect(from_id, to_id, connections))) [] ( cancel !after_engagedtone ?phone_id:id_sort; exit(engaged, connections)) endproc endspec
Afterthoughts • LOTOS is an intuitive, programmer-friendly way of describing concurrent systems • For some, the axiomatic style of data definition might seem like overkill • One of the strengths of LOTOS is the fact that specifications do not require any special characters, but everything is found in ASCII. • One publicly available LOTOS tool is LOLA => http://wwwtios.cs.utwente.nl/lotos/lotos-news/lnews_03/node70.html