#define MaxSeq 3 #define MaxSeq_plus_1 4 #define inc(x) x = (x + 1) % (MaxSeq + 1) #define CHECKIT #ifdef CHECKIT mtype = { red, white, blue }; /* Wolper's test */ chan source = [0] of { mtype }; chan q[2] = [MaxSeq] of { mtype, byte, byte }; mtype rcvd = white; mtype sent = white; #else chan q[2] = [MaxSeq] of { byte, byte }; #endif active [2] proctype p5() { byte NextFrame, AckExp, FrameExp, r, s, nbuf, i; chan in, out; #ifdef CHECKIT mtype ball; byte frames[MaxSeq_plus_1]; #endif d_step { in = q[_pid]; out = q[1-_pid] }; xr in; xs out; do :: atomic { nbuf < MaxSeq -> nbuf++; #ifdef CHECKIT if :: _pid%2 -> source?ball :: else fi; frames[NextFrame] = ball; out!ball, NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1); if :: _pid%2 -> sent = ball; :: else fi; #else out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1); #endif #ifdef VERBOSE printf("MSC: nbuf: %d\n", nbuf); #endif inc(NextFrame) } #ifdef CHECKIT :: atomic { in?ball,r,s -> #else :: atomic { in?r,s -> #endif if :: r == FrameExp -> #ifdef VERBOSE printf("MSC: accept %d\n", r); #endif #ifdef CHECKIT if :: _pid%2 :: else -> rcvd = ball fi; #endif inc(FrameExp) :: else #ifdef VERBOSE -> printf("MSC: reject\n") #endif fi }; d_step { do :: ((AckExp <= s) && (s < NextFrame)) || ((AckExp <= s) && (NextFrame < AckExp)) || ((s < NextFrame) && (NextFrame < AckExp)) -> nbuf--; #ifdef VERBOSE printf("MSC: nbuf: %d\n", nbuf); #endif inc(AckExp) :: else -> #ifdef VERBOSE printf("MSC: %d %d %d\n", AckExp, s, NextFrame); #endif break od; skip } :: timeout -> d_step { NextFrame = AckExp; #ifdef VERBOSE printf("MSC: timeout\n"); #endif i = 1; do :: i <= nbuf -> #ifdef CHECKIT if :: _pid%2 -> ball = frames[NextFrame] :: else fi; out!ball, NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1); #else out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1); #endif inc(NextFrame); i++ :: else -> break od; i = 0 } od } #ifdef CHECKIT active proctype Source() { do :: source!white :: source!red -> break od; do :: source!white :: source!blue -> break od; end: do :: source!white od } #define sw (sent == white) #define sr (sent == red) #define sb (sent == blue) #define rw (rcvd == white) #define rr (rcvd == red) #define rb (rcvd == blue) #define LTL 3 #if LTL==1 never { /* ![](sr -> <> rr) */ /* the never claim is generated by spin -f "![](sr -> <> rr)" and then edited a little for readability the same is true for all others below */ do :: 1 :: !rr && sr -> goto accept od; accept: if :: !rr -> goto accept fi } #endif #if LTL==2 never { /* !rr U rb */ do :: !rr :: rb -> break /* move to implicit 2nd state */ od } #endif #if LTL==3 never { /* (![](sr -> <> rr)) || (!rr U rb) */ if :: 1 -> goto T0_S5 :: !rr && sr -> goto accept_S8 :: !rr -> goto T0_S2 :: rb -> goto accept_all fi; accept_S8: if :: !rr -> goto T0_S8 fi; T0_S2: if :: !rr -> goto T0_S2 :: rb -> goto accept_all fi; T0_S8: if :: !rr -> goto accept_S8 fi; T0_S5: if :: 1 -> goto T0_S5 :: !rr && sr -> goto accept_S8 fi; accept_all: skip } #endif #endif