---=============================================== -- 22c:181 Formal Methods in Software Engineering -- Spring 2013 -- -- Example adapted from -- -- By N Halbwachs, F Lagnier, C Ratel. -- Programming and verifying real-time systems by means -- of the synchronous data-flow language LUSTRE. -- IEEE TRANSACTIONS ON SOFTWARE ENGINEERING (1992) -- vol. 18 (9) pp. 785-793 -- --=============================================== -- Auxiliary temporal operators node edge( X: bool ) returns ( EDGE: bool ); let EDGE = X -> X and not pre X; tel -- after( A: bool ) is true iff A has accurred in the past node after( A: bool ) returns (after_A: bool ); let after_A = false -> pre (A or after_A); tel -- always_since(B, A) is true iff -- B has been continuously true since the last time A was true : node always_since(B, A: bool) returns (always_B_since_A: bool); let always_B_since_A = if A then B else if after(A) then B and (true -> pre always_B_since_A) else true; tel -- always_from_to(B, A, C) is true iff -- any time A has occurred in the past, -- either B has been continuously true, -- or C has occurred at least once since the last occurrence of A node always_from_to(B, A, C: bool) returns (X: bool); let X = after(A) => always_since(B, A) or once_since(C, A); tel -- once_since(C, A) is true iff -- C has been true at least once since the last time A was true node once_since(C, A: bool) returns (once_C_since_A: bool); let once_C_since_A = if A then C else if after(A) then C or (true -> pre once_C_since_A) else true; tel node UMS(on_A, on_B, on_C, ack_AB, ack_BC: bool) returns (grant_access, grant_exit, do_AB, do_BC: bool); -- -- ------<---------\ -- \ C -- A \ B -- ------>------------O---------- -- S -- -- initially, no trains in the section -- must connect segment A with segment B whenever the section is empty -- must connect segment B with segment C whenever there is a train on B -- requests remain active until switch is in the right positions -- access to section is granted iff it is empty and A connects with B -- exit is granted iff the only train is on B and B connects with C -- var empty_section, only_on_B: bool; let grant_access = empty_section and ack_AB; grant_exit = only_on_B and ack_BC; do_AB = not ack_AB and empty_section; do_BC = not ack_BC and only_on_B; empty_section = not (on_A or on_B or on_C); only_on_B = on_B and not (on_A or on_C); tel node UMS_verif( on_A, on_B, on_C, ack_AB, ack_BC: bool ) returns( no_collision, exclusive_req, no_derail_AB, no_derail_BC: bool ); var empty_section, only_on_B: bool; grant_access, grant_exit: bool; do_AB, do_BC: bool; let empty_section = not (on_A or on_B or on_C); only_on_B = on_B and not (on_A or on_C); -- Environmental assumptions assert not (ack_AB and ack_BC); assert always_from_to(ack_AB, ack_AB, do_BC) and always_from_to(ack_BC, ack_BC, do_AB); assert empty_section -> true; assert true -> edge(not empty_section) => pre grant_access; assert true -> edge(on_C) => pre grant_exit; -- UMS CALL (grant_access, grant_exit, do_AB, do_BC) = UMS(on_A, on_B, on_C, ack_AB, ack_BC); -- PROPERTIES no_collision = grant_access => empty_section; exclusive_req = not (do_AB and do_BC); no_derail_AB = always_from_to(ack_AB, grant_access, only_on_B); no_derail_BC = always_from_to(ack_BC, grant_exit, empty_section); --%MAIN --%PROPERTY no_collision; --%PROPERTY exclusive_req; --%PROPERTY no_derail_AB; --%PROPERTY no_derail_BC; tel -- /group/class/c_181/tools/lustre/linux/jkind -timeout 10 train.lus