include "log_tmp.lus"

node UMS(on_A,on_B,on_C,ack_AB,ack_BC: bool)
     returns (grant_access,grant_exit,
	      do_AB,do_BC: bool);
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(property: bool);
var
   grant_access,grant_exit: bool;
   do_AB,do_BC: bool;
   no_collision,exclusive_req: bool;
   no_derail_AB,no_derail_BC: bool;
   empty_section, only_on_B: 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);
   
   -- ASSERTIONS
   assert not(ack_AB and ack_BC);
   assert true -> always_from_to(ack_AB,ack_AB,do_BC);
   assert true -> always_from_to(ack_BC,ack_BC,do_AB);
   assert empty_section -> true;
   assert true ->
	  implies(edge(not empty_section),
		  pre grant_access);
   assert true ->
	  implies(edge(on_C),
		  pre grant_exit);
   assert true -> implies(edge(not on_A),on_B);
   assert true -> implies(edge(not on_B),
			  on_A or on_C);

   -- UMS CALL
   (grant_access,grant_exit,do_AB,do_BC) =
	UMS(on_A,on_B,on_C,ack_AB,ack_BC);

   -- PROPERTIES
   no_collision =
	implies(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);
   property =
	no_collision and exclusive_req and
	no_derail_AB and no_derail_BC;
tel
