--satisfies mutual exclusion and liveness for north and south green-lights. --But the west lane could get starved. MODULE main VAR N : boolean; Sy : boolean; W : boolean; N-Req : boolean; W-Req : boolean; S-Req : boolean; N-Go : boolean; W-Go : boolean; S-Go : boolean; NS-Lock : boolean; EW-Lock : boolean; turn : {nst, ewt}; --turn variable (similar to the mutex example) north : process north1(NS-Lock, EW-Lock, N-Req, N-Go,N,S-Go,S-Req,W-Req,turn); south : process south1(NS-Lock,EW-Lock,S-Req,S-Go,Sy,N-Go,N-Req,W-Req,turn); west : process west1(NS-Lock,EW-Lock,W-Req,W-Go,W,N-Req,S-Req,turn); ASSIGN init(NS-Lock) := 0; init(EW-Lock) := 0; init(N) := 0; init(Sy) := 0; init(W) := 0; init(W-Req) := 0; init(N-Req) := 0; init(S-Req) := 0; init(W-Go) := 0; init(N-Go) := 0; init(S-Go) := 0; SPEC AG !(W-Go & (N-Go | S-Go)) SPEC AG(N & !N-Go -> AF N-Go) SPEC AG(Sy & !S-Go -> AF S-Go) SPEC AG(W & !W-Go -> AF W-Go) MODULE north1(NS-Lock, EW-Lock, N-Req, N-Go,N,S-Go,S-Req,E-Req,turn) VAR state : {idle, entering , critical , exiting}; ASSIGN init(state) := idle; next(state) := case state = idle & N-Req = 1 : entering; state = entering & !EW-Lock & (!E-Req | turn=nst): critical; state = critical & !N : exiting; state = exiting : idle; 1 : state; esac; next(NS-Lock) := case state = entering & !EW-Lock & (!E-Req | turn=nst) : 1 ; state = exiting & !S-Go : 0; 1 : NS-Lock; esac; next(N-Req) := case !N-Req & N : 1; state = exiting : 0; 1 : N-Req; esac; next(N-Go) := case state = entering & !EW-Lock & (!E-Req | turn=nst) : 1; state = exiting : 0; 1 : N-Go; esac; next(N) := {0,1}; next(turn) := case state=exiting & turn=nst & !S-Req : ewt; 1 : turn; esac; FAIRNESS running & !(N-Go & N) -- Module for south traffic is same as north traffic MODULE south1(NS-Lock,EW-Lock,S-Req,S-Go,Sy,N-Go,N-Req,E-Req,turn) VAR state : {idle, entering , critical , exiting}; ASSIGN init(state) := idle; next(state) := case state = idle & S-Req : entering; state = entering & !EW-Lock & (!E-Req | turn=nst): critical; state = critical & !Sy : exiting; state = exiting : idle; 1 : state; esac; next(NS-Lock) := case state = entering & !EW-Lock & (!E-Req | turn=nst): 1 ; state = exiting & !N-Go : 0; 1 : NS-Lock; esac; next(S-Req) := case !S-Req & Sy : 1; state = exiting : 0; 1 : S-Req; esac; next(S-Go) := case state = entering & !EW-Lock & (!E-Req | turn=nst): 1; state = exiting : 0; 1 : S-Go; esac; next(Sy) := {0,1}; next(turn) := case state=exiting & turn=nst & !N-Req : ewt; 1 : turn; esac; FAIRNESS running & !(S-Go & Sy) -- The module for east bound traffic is a little bit different from -- south and north bound traffic MODULE west1(NS-Lock,EW-Lock,W-Req,W-Go,W, N-Req, S-Req, turn) VAR state : { idle , entering , critical , exiting}; ASSIGN init(state) := idle; next(state) := case state = idle & W-Req : entering; state = entering & !NS-Lock & ((!N-Req & !S-Req) | turn=ewt): critical; state = critical & !W : exiting; state = exiting : idle; 1 : state; esac; next(EW-Lock) := case state = entering & !NS-Lock & ((!N-Req & !S-Req) | turn=ewt): 1; state = exiting : 0; 1 : EW-Lock; esac; next(W-Req) := case !W-Req & W : 1; state = exiting : 0; 1 : W-Req; esac; next(W-Go) := case state = critical : 1; state = exiting : 0; 1 : W-Go; esac; next(W) := {0,1}; next(turn) := case state=exiting & turn=ewt : nst; 1 : turn; esac; FAIRNESS running & !(W-Go & W)