├── tests ├── regression │ ├── test1.exp2 │ ├── test10.exp2 │ ├── test11.exp2 │ ├── test2.exp2 │ ├── test3.exp2 │ ├── test4.exp2 │ ├── test5.exp2 │ ├── test6.exp2 │ ├── test7.exp2 │ ├── test8.exp2 │ ├── test9.exp2 │ ├── test11.exp │ ├── test3.scr │ ├── test7.scr │ ├── test1.scr │ ├── test2.scr │ ├── test4.scr │ ├── test11.scr │ ├── test5.scr │ ├── test6.scr │ ├── test8.scr │ ├── test9.scr │ ├── test10.scr │ ├── test1.exp │ ├── test3.exp │ ├── test4.exp │ ├── test2.exp │ ├── test10.exp │ ├── test7.exp │ ├── test9.exp │ ├── test5.exp │ └── test6.exp ├── README.md ├── pluspy └── regres.scr ├── pluspy ├── .gitignore ├── modules ├── README.md ├── book │ ├── FIFO.tla │ ├── TestFIFO.tla │ ├── TestBoundedFIFO.tla │ ├── TestChannel.tla │ ├── TestInnerFIFO.tla │ ├── TestInnerFIFO2.tla │ ├── BoundedFIFO.tla │ ├── HourClock.tla │ ├── Channel.tla │ ├── InnerFIFO2.tla │ ├── InnerFIFO.tla │ └── Peterson.tla ├── lib │ ├── Naturals.tla │ ├── TLCExt.tla │ ├── Input.tla │ ├── Integers.tla │ ├── IOUtils.tla │ ├── Core.tla │ ├── FiniteSets.tla │ ├── Messaging.tla │ ├── Sequences.tla │ ├── Bags.tla │ └── TLC.tla └── other │ ├── TestBQ.tla │ ├── Prime.tla │ ├── TestBinBosco.tla │ ├── TestBosco.tla │ ├── Qsort.tla │ ├── BinBosco2.tla │ ├── BinBosco.tla │ ├── BlockingQueueSplit.tla │ ├── Bosco.tla │ ├── BlockingQueue.tla │ ├── NBosco.tla │ └── Exprs.tla ├── .github └── workflows │ └── main.yml ├── LICENSE ├── test_pluspy.py └── README.md /tests/regression/test1.exp2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/regression/test10.exp2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/regression/test11.exp2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/regression/test2.exp2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/regression/test3.exp2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/regression/test4.exp2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/regression/test5.exp2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/regression/test6.exp2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/regression/test7.exp2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/regression/test8.exp2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/regression/test9.exp2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pluspy: -------------------------------------------------------------------------------- 1 | python3 pluspy.py $@ 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | modules/other/BinBosco.toolbox/ 2 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | This directory contains tests. 2 | 3 | Run ./regres.scr to run some regression tests 4 | -------------------------------------------------------------------------------- /tests/regression/test11.exp: -------------------------------------------------------------------------------- 1 | <<>> 2 | Initial context: <<>> 3 | No state change after successful step 4 | MAIN DONE 5 | -------------------------------------------------------------------------------- /tests/pluspy: -------------------------------------------------------------------------------- 1 | PLUSPYPATH=../modules/lib:../modules/book:../modules/other 2 | export PLUSPYPATH 3 | python3 ../pluspy.py $@ 4 | -------------------------------------------------------------------------------- /modules/README.md: -------------------------------------------------------------------------------- 1 | This directory contains TLA+ modules: 2 | 3 | lib: "standard" modules to be used for applications 4 | book: some examples from Leslie's Specifying Systems book 5 | other: some examples provided by RVR and others 6 | -------------------------------------------------------------------------------- /tests/regres.scr: -------------------------------------------------------------------------------- 1 | for i in 1 2 3 4 5 6 7 9 10 11 2 | do 3 | echo running test $i 4 | sh regression/test$i.scr 5 | case $? in 6 | 0) 7 | ;; 8 | *) 9 | echo test $i failed 10 | exit 1 11 | esac 12 | done 13 | -------------------------------------------------------------------------------- /modules/book/FIFO.tla: -------------------------------------------------------------------------------- 1 | ------------------------ MODULE FIFO ------------------------- 2 | CONSTANT Message 3 | VARIABLES in, out 4 | Inner(q) == INSTANCE InnerFIFO 5 | Spec == \EE q: Inner(q)!Spec 6 | ============================================================== 7 | -------------------------------------------------------------------------------- /tests/regression/test3.scr: -------------------------------------------------------------------------------- 1 | ./pluspy -S0 -c100 Prime > test3.out 2>test3.out2 2 | if cmp -s test3.out regression/test3.exp 3 | then 4 | if cmp -s test3.out2 regression/test3.exp2 5 | then 6 | rm -rf test3.out test3.out2 7 | exit 0 8 | fi 9 | fi 10 | exit 1 11 | -------------------------------------------------------------------------------- /tests/regression/test7.scr: -------------------------------------------------------------------------------- 1 | ./pluspy -S0 -c100 Qsort > test7.out 2>test7.out2 2 | if cmp -s test7.out regression/test7.exp 3 | then 4 | if cmp -s test7.out2 regression/test7.exp2 5 | then 6 | rm -rf test7.out test7.out2 7 | exit 0 8 | fi 9 | fi 10 | exit 1 11 | -------------------------------------------------------------------------------- /modules/book/TestFIFO.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE TestFIFO ----------------------------- 2 | VARIABLES in, out 3 | 4 | Inner == INSTANCE FIFO WITH Message <- { "red", "blue" } 5 | 6 | Spec == Inner!Spec 7 | ============================================================================ 8 | -------------------------------------------------------------------------------- /tests/regression/test1.scr: -------------------------------------------------------------------------------- 1 | ./pluspy -S0 -c100 HourClock > test1.out 2>test1.out2 2 | if cmp -s test1.out regression/test1.exp 3 | then 4 | if cmp -s test1.out2 regression/test1.exp2 5 | then 6 | rm -rf test1.out test1.out2 7 | exit 0 8 | fi 9 | fi 10 | exit 1 11 | -------------------------------------------------------------------------------- /tests/regression/test2.scr: -------------------------------------------------------------------------------- 1 | ./pluspy -S0 -c100 Peterson > test2.out 2>test2.out2 2 | if cmp -s test2.out regression/test2.exp 3 | then 4 | if cmp -s test2.out2 regression/test2.exp2 5 | then 6 | rm -rf test2.out test2.out2 7 | exit 0 8 | fi 9 | fi 10 | exit 1 11 | -------------------------------------------------------------------------------- /tests/regression/test4.scr: -------------------------------------------------------------------------------- 1 | ./pluspy -S0 -c100 TestChannel > test4.out 2>test4.out2 2 | if cmp -s test4.out regression/test4.exp 3 | then 4 | if cmp -s test4.out2 regression/test4.exp2 5 | then 6 | rm -rf test4.out test4.out2 7 | exit 0 8 | fi 9 | fi 10 | exit 1 11 | -------------------------------------------------------------------------------- /tests/regression/test11.scr: -------------------------------------------------------------------------------- 1 | ./pluspy -S0 -c100 Exprs > test11.out 2>test11.out2 2 | if cmp -s test11.out regression/test11.exp 3 | then 4 | if cmp -s test11.out2 regression/test11.exp2 5 | then 6 | rm -rf test11.out test11.out2 7 | exit 0 8 | fi 9 | fi 10 | exit 1 11 | -------------------------------------------------------------------------------- /tests/regression/test5.scr: -------------------------------------------------------------------------------- 1 | ./pluspy -S0 -c100 TestInnerFIFO > test5.out 2>test5.out2 2 | if cmp -s test5.out regression/test5.exp 3 | then 4 | if cmp -s test5.out2 regression/test5.exp2 5 | then 6 | rm -rf test5.out test5.out2 7 | exit 0 8 | fi 9 | fi 10 | exit 1 11 | -------------------------------------------------------------------------------- /tests/regression/test6.scr: -------------------------------------------------------------------------------- 1 | ./pluspy -S0 -c100 TestInnerFIFO2 > test6.out 2>test6.out2 2 | if cmp -s test6.out regression/test6.exp 3 | then 4 | if cmp -s test6.out2 regression/test6.exp2 5 | then 6 | rm -rf test6.out test6.out2 7 | exit 0 8 | fi 9 | fi 10 | exit 1 11 | -------------------------------------------------------------------------------- /tests/regression/test8.scr: -------------------------------------------------------------------------------- 1 | ./pluspy -S0 -c100 TestBinBosco > test8.out 2>test8.out2 2 | if cmp -s test8.out regression/test8.exp 3 | then 4 | if cmp -s test8.out2 regression/test8.exp2 5 | then 6 | rm -rf test8.out test8.out2 7 | exit 0 8 | fi 9 | fi 10 | exit 1 11 | -------------------------------------------------------------------------------- /tests/regression/test9.scr: -------------------------------------------------------------------------------- 1 | ./pluspy -S0 -c100 -i Spec TestFIFO > test9.out 2>test9.out2 2 | if cmp -s test9.out regression/test9.exp 3 | then 4 | if cmp -s test9.out2 regression/test9.exp2 5 | then 6 | rm -rf test9.out test9.out2 7 | exit 0 8 | fi 9 | fi 10 | exit 1 11 | -------------------------------------------------------------------------------- /tests/regression/test10.scr: -------------------------------------------------------------------------------- 1 | ./pluspy -S0 -c100 -i Spec TestBoundedFIFO > test10.out 2>test10.out2 2 | if cmp -s test10.out regression/test10.exp 3 | then 4 | if cmp -s test10.out2 regression/test10.exp2 5 | then 6 | rm -rf test10.out test10.out2 7 | exit 0 8 | fi 9 | fi 10 | exit 1 11 | -------------------------------------------------------------------------------- /modules/book/TestBoundedFIFO.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE TestBoundedFIFO ----------------------------- 2 | VARIABLES in, out 3 | 4 | Inner == INSTANCE BoundedFIFO WITH Message <- { "red", "blue" }, N <- 2 5 | 6 | Spec == Inner!Spec 7 | ============================================================================ 8 | -------------------------------------------------------------------------------- /modules/book/TestChannel.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE TestChannel ----------------------------- 2 | VARIABLE chan 3 | C == INSTANCE Channel WITH Data <- { "red", "blue" } 4 | 5 | Init == C!Init 6 | Next == C!Next 7 | Spec == Init /\ [][Next]_<> 8 | ============================================================================ 9 | -------------------------------------------------------------------------------- /modules/book/TestInnerFIFO.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE TestInnerFIFO ----------------------------- 2 | VARIABLES in, out, q 3 | 4 | Inner == INSTANCE InnerFIFO WITH Message <- { "red", "blue" } 5 | 6 | Init == Inner!Init 7 | Next == Inner!Next 8 | Spec == Init /\ [][Next]_<> 9 | ============================================================================ 10 | -------------------------------------------------------------------------------- /modules/book/TestInnerFIFO2.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE TestInnerFIFO2 ----------------------------- 2 | VARIABLES in, out, q 3 | 4 | Inner == INSTANCE InnerFIFO2 WITH Message <- { "red", "blue" } 5 | 6 | Init == Inner!Init 7 | Next == Inner!Next 8 | Spec == Init /\ [][Next]_<> 9 | ============================================================================ 10 | -------------------------------------------------------------------------------- /modules/book/BoundedFIFO.tla: -------------------------------------------------------------------------------- 1 | -------------------- MODULE BoundedFIFO --------------------- 2 | EXTENDS Naturals, Sequences 3 | VARIABLES in, out 4 | CONSTANT Message, N 5 | ASSUME (N \in Nat) /\ (N > 0) 6 | Inner(q) == INSTANCE InnerFIFO 7 | BNext(q) == /\ Inner(q)!Next 8 | /\ Inner(q)!BufRcv => (Len(q) < N) 9 | 10 | Spec == \EE q: Inner(q)!Init /\ [][BNext(q)]_<> 11 | ============================================================= 12 | -------------------------------------------------------------------------------- /modules/lib/Naturals.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE Naturals ---- 2 | EXTENDS Core 3 | 4 | Nat == CHOOSE x: x \notin {"Nat"} 5 | 6 | s - t == FALSE 7 | s < t == FALSE 8 | s > t == FALSE 9 | s >= t == FALSE 10 | s \geq t == FALSE 11 | s <= t == FALSE 12 | s =< t == FALSE 13 | s \leq t == FALSE 14 | s + t == FALSE 15 | s * t == FALSE 16 | s / t == FALSE 17 | s \div t == FALSE 18 | s % t == FALSE 19 | s ^ t == FALSE 20 | 21 | s .. t == FALSE 22 | =============================== 23 | -------------------------------------------------------------------------------- /modules/lib/TLCExt.tla: -------------------------------------------------------------------------------- 1 | ------------------------------- MODULE TLCExt ---------------------------------- 2 | LOCAL INSTANCE Naturals 3 | LOCAL INSTANCE IOUtils 4 | ----------------------------------------------------------------------------- 5 | JSignalReturn(t, d) == d 6 | /\ IOPut("local", t, d) 7 | JReturn(d) == d 8 | JWait(t) == 9 | /\ IOWait("local", t) 10 | /\ IOGet("local", t) \notin {} 11 | ============================================================================= 12 | -------------------------------------------------------------------------------- /modules/lib/Input.tla: -------------------------------------------------------------------------------- 1 | ------------------------ MODULE Input ------------------------ 2 | \* This module is an interface to get terminal input 3 | 4 | \*++:SPEC 5 | Receive(p, Deliver(_, _)) == \E x: Deliver(p, x) 6 | ========================================================================= 7 | 8 | \*++:PlusPy 9 | LOCAL INSTANCE IOUtils 10 | 11 | Receive(p, Deliver(_, _)) == 12 | /\ IOWait("fd", "stdin") 13 | /\ Deliver(p, IOGet("fd", "stdin")) 14 | ========================================================================= 15 | -------------------------------------------------------------------------------- /modules/book/HourClock.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE HourClock ----------------------------- 2 | EXTENDS Naturals 3 | VARIABLE hr 4 | HCini == hr \in (1..12) 5 | HCnxt == hr' = IF hr = 12 THEN 1 ELSE hr + 1 6 | HC == HCini /\ [][HCnxt]_hr 7 | 8 | (* Added for simplicity of pluspy testing *) 9 | Init == HCini 10 | Next == HCnxt 11 | Spec == HC 12 | 13 | ============================================================================= 14 | \* Modification History 15 | \* Last modified Sat Feb 01 19:29:17 EST 2020 by rvr 16 | \* Created Sat Feb 01 19:26:43 EST 2020 by rvr 17 | -------------------------------------------------------------------------------- /modules/lib/Integers.tla: -------------------------------------------------------------------------------- 1 | -------------------------------- MODULE Integers ---------------------------- 2 | (***************************************************************************) 3 | (* A dummy module that declares the operators that are defined in the *) 4 | (* real Integers module. *) 5 | (***************************************************************************) 6 | EXTENDS Naturals 7 | 8 | Int == CHOOSE x: x \notin {"Int"} 9 | -. a == 0 - a 10 | ============================================================================= 11 | -------------------------------------------------------------------------------- /modules/other/TestBQ.tla: -------------------------------------------------------------------------------- 1 | ------------------------- MODULE TestBQ ------------------------- 2 | VARIABLES buffer, waitSetC, waitSetP 3 | 4 | Producers == { "p1", "p2", "p3" } 5 | Consumers == { "c1", "c2", "c3" } 6 | 7 | BQ == INSTANCE BlockingQueueSplit WITH BufCapacity <- 2 8 | 9 | producer(p) == BQ!Put(p, p) 10 | consumer(c) == BQ!Get(c) 11 | 12 | Init == BQ!Init 13 | Next == \/ \E p \in Producers: producer(p) 14 | \/ \E c \in Consumers: consumer(c) 15 | 16 | Spec == Init /\ [][Next]_<> 17 | ============================================================================= 18 | -------------------------------------------------------------------------------- /modules/lib/IOUtils.tla: -------------------------------------------------------------------------------- 1 | ------------------------------- MODULE IOUtils ---------------------------------- 2 | \* Input/Output. This module essentially uses a hidden sequence variable H 3 | 4 | \* Append << intf, mux, data >> to the end of sequence H 5 | IOPut(intf, mux, data) == TRUE \* H' = Append(H, <>) 6 | 7 | \* Wait until there is an element of the form <> in sequence H 8 | IOWait(intf, mux) == TRUE \* \E i \in Nat, d \in Data: H[i] = <> 9 | 10 | \* Remove the first element of the form <> from sequence H 11 | \* and return data 12 | IOGet(intf, mux) == TRUE \* hard to formalize... 13 | ============================================================================= 14 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: PlusPy 2 | 3 | on: 4 | push: 5 | # Sequence of patterns matched against refs/heads 6 | branches: 7 | - master # Push events on master branch. 8 | pull_request: 9 | branches: 10 | - master # Pull requests opened on the master branch. 11 | 12 | jobs: 13 | 14 | tests: 15 | runs-on: ubuntu-latest 16 | steps: 17 | # Get PlusPy's sources from Github repository 18 | - uses: actions/checkout@v2 19 | 20 | # Run PlusPy's regression tests. 21 | - name: Run regression tests 22 | working-directory: ./tests/ 23 | run: | 24 | echo $PWD 25 | which python3 26 | python3 --version 27 | ./regres.scr 28 | -------------------------------------------------------------------------------- /modules/other/Prime.tla: -------------------------------------------------------------------------------- 1 | ------------------------------- MODULE Prime ------------------------------- 2 | EXTENDS Naturals, Sequences 3 | VARIABLE count, p 4 | 5 | isPrime(x) == x > 1 /\ \A r \in 2..(x-1): x%r /= 0 6 | 7 | TypeInvariant == isPrime(p) /\ count \in Nat 8 | 9 | Init == p = 2 /\ count = 1 10 | Next == /\ p' = CHOOSE q \in (p+1)..(2*p-1): 11 | isPrime(q) /\ \A r \in (p+1)..(q-1): ~isPrime(r) 12 | /\ count' = count + 1 13 | 14 | Spec == Init /\ [] [Next]_<> 15 | 16 | THEOREM Spec => []TypeInvariant 17 | 18 | ============================================================================= 19 | \* Modification History 20 | \* Last modified Mon Jan 27 14:20:50 EST 2020 by rvr 21 | \* Created Mon Jan 27 14:05:36 EST 2020 by rvr 22 | -------------------------------------------------------------------------------- /modules/lib/Core.tla: -------------------------------------------------------------------------------- 1 | ------------ MODULE Core ------------ 2 | 3 | STRING == CHOOSE x: x \notin {"STRING"} 4 | 5 | (* 6 | s /\ t == FALSE 7 | s \/ t == FALSE 8 | s = t == FALSE 9 | s \in t == FALSE 10 | s \notin t == FALSE 11 | *) 12 | 13 | s <=> t == FALSE 14 | s \equiv t == FALSE 15 | s # t == FALSE 16 | s /= t == FALSE 17 | 18 | s \subset t == FALSE 19 | s \subseteq t == FALSE 20 | s \supset t == FALSE 21 | s \supseteq t == FALSE 22 | s \ t == FALSE 23 | s \cap t == FALSE 24 | s \intersect t == FALSE 25 | s \cup t == FALSE 26 | s \union t == FALSE 27 | 28 | DOMAIN s == FALSE 29 | UNION s == FALSE 30 | SUBSET s == FALSE 31 | ~ s == FALSE 32 | \lnot s == FALSE 33 | \neg s == FALSE 34 | 35 | s => t == (~s) \/ t 36 | 37 | ========================================= 38 | -------------------------------------------------------------------------------- /modules/other/TestBinBosco.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE TestBinBosco ----------------------------- 2 | EXTENDS Naturals 3 | VARIABLES processes, mi, msgs 4 | 5 | Processes == 6 | { 7 | "localhost:5001", "localhost:5002", "localhost:5003", "localhost:5004" 8 | } 9 | 10 | Inputs == 11 | [ [ p \in Processes |-> "" ] EXCEPT 12 | !["localhost:5001"] = "red", 13 | !["localhost:5002"] = "blue", 14 | !["localhost:5003"] = "red", 15 | !["localhost:5004"] = "blue" 16 | ] 17 | 18 | BB == INSTANCE BinBosco WITH 19 | Processes <- Processes, 20 | Quorums <- { Processes \ {p}: p \in Processes }, 21 | Data <- { "red", "blue" }, 22 | procs <- processes 23 | 24 | Init == BB!Init 25 | Next == BB!Next 26 | Proc(p) == BB!Proc(p) 27 | Spec == Init /\ [][Next]_<> 28 | ============================================================================ 29 | -------------------------------------------------------------------------------- /modules/other/TestBosco.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE TestBosco ----------------------------- 2 | EXTENDS Naturals 3 | VARIABLES processes, mi, msgs 4 | 5 | Processes == 6 | { 7 | "localhost:5001", "localhost:5002", "localhost:5003", "localhost:5004" 8 | } 9 | 10 | Inputs == 11 | [ [ p \in Processes |-> "" ] EXCEPT 12 | !["localhost:5001"] = "red", 13 | !["localhost:5002"] = "blue", 14 | !["localhost:5003"] = "red", 15 | !["localhost:5004"] = "blue" 16 | ] 17 | 18 | B == INSTANCE Bosco WITH 19 | Processes <- Processes, 20 | Quorums <- { Processes \ {p}: p \in Processes }, 21 | Data <- { "red", "blue", "green", "orange", "black" }, 22 | procs <- processes 23 | 24 | Init == B!Init 25 | Next == B!Next 26 | Proc(p) == B!Proc(p) 27 | Spec == Init /\ [][Next]_<> 28 | ============================================================================ 29 | -------------------------------------------------------------------------------- /modules/book/Channel.tla: -------------------------------------------------------------------------------- 1 | ------------------------------ MODULE Channel ------------------------------ 2 | EXTENDS Naturals 3 | CONSTANT Data 4 | VARIABLE chan 5 | 6 | TypeInvariant == chan \in [ val: Data, rdy: {0, 1}, ack: {0, 1} ] 7 | 8 | ----------------------------------------------------------------------------- 9 | 10 | (* RVR 11 | Init == /\ TypeInvariant 12 | /\ chan.ack = chan.rdy 13 | *) 14 | Init == \E d \in Data, v \in 0..1: chan = [ val |-> d, rdy |-> v, ack |-> v ] 15 | 16 | Send(d) == /\ chan.rdy = chan.ack 17 | /\ chan' = [chan EXCEPT !.val = d, !.rdy = 1 - @] 18 | 19 | Rcv == /\ chan.rdy /= chan.ack 20 | /\ chan' = [chan EXCEPT !.ack = 1 - @] 21 | 22 | Next == (\E x \in Data: Send(x)) \/ Rcv 23 | 24 | Spec == Init /\ [][Next]_chan 25 | 26 | ----------------------------------------------------------------------------- 27 | 28 | THEOREM Spec => []TypeInvariant 29 | 30 | ============================================================================= 31 | \* Modification History 32 | \* Last modified Thu Mar 19 08:54:34 EDT 2020 by rvr 33 | \* Created Sun Feb 02 14:35:33 EST 2020 by rvr 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 TLA+ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /modules/lib/FiniteSets.tla: -------------------------------------------------------------------------------- 1 | ---------------------------- MODULE FiniteSets ----------------------------- 2 | LOCAL INSTANCE Naturals 3 | LOCAL INSTANCE Sequences 4 | (*************************************************************************) 5 | (* Imports the definitions from Naturals and Sequences, but doesn't *) 6 | (* export them. *) 7 | (*************************************************************************) 8 | 9 | IsFiniteSet(S) == 10 | (*************************************************************************) 11 | (* A set S is finite iff there is a finite sequence containing all its *) 12 | (* elements. *) 13 | (*************************************************************************) 14 | \E seq \in Seq(S) : \A s \in S : \E n \in 1..Len(seq) : seq[n] = s 15 | 16 | Cardinality(S) == 17 | (*************************************************************************) 18 | (* Cardinality is defined only for finite sets. *) 19 | (*************************************************************************) 20 | LET CS[T \in SUBSET S] == IF T = {} THEN 0 21 | ELSE 1 + CS[T \ {CHOOSE x : x \in T}] 22 | IN CS[S] 23 | 24 | ============================================================================= 25 | -------------------------------------------------------------------------------- /modules/other/Qsort.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE Qsort ----------------------------- 2 | EXTENDS Naturals, Sequences, FiniteSets 3 | 4 | \* CONSTANT input 5 | input == << 0, 383, 886, 777, 915, 793, 335, 386, 492, 649, 421, 362, 27, 690, 59, 763, 926, 540, 426, 172, 736, 211, 368, 567, 429, 782, 530, 862, 123, 67, 135, 929, 802, 22, 58, 69, 167, 393, 456, 11, 42, 229, 373 >> 6 | 7 | VARIABLES todo, output 8 | 9 | \* Specification (works reasonably well for sets of cardinality <= 6 10 | \* Takes a set as argument, produces a sorted tuple 11 | Sort(S) == CHOOSE s \in [ 1..Cardinality(S) -> S]: 12 | \A i, j \in DOMAIN s: (i < j) => (s[i] < s[j]) 13 | 14 | Flatten[s \in Seq(Seq(Nat))] == 15 | IF s = <<>> THEN <<>> 16 | ELSE Head(s) \o Flatten[Tail(s)] 17 | 18 | Partition(s) == 19 | LET LE(x) == x <= Head(s) 20 | GT(x) == x > Head(s) 21 | IN << SelectSeq(Tail(s), LE), << Head(s) >>, SelectSeq(Tail(s), GT) >> 22 | 23 | Init == todo = << input >> /\ output = "under construction" 24 | Next == 25 | IF \E i \in 1..Len(todo): Len(todo[i]) > 1 /\ 26 | todo' = SubSeq(todo, 1, i-1) \o Partition(todo[i]) \o 27 | SubSeq(todo, i+1, Len(todo)) 28 | THEN UNCHANGED output 29 | ELSE output' = Flatten[todo] /\ UNCHANGED todo 30 | 31 | Spec == Init /\ [][Next]_<> 32 | ============================================================================= 33 | -------------------------------------------------------------------------------- /modules/book/InnerFIFO2.tla: -------------------------------------------------------------------------------- 1 | ---------------------------- MODULE InnerFIFO2 ------------------------------- 2 | EXTENDS Naturals, Sequences 3 | CONSTANT Message 4 | VARIABLES in, out, q 5 | MyChan(c) == INSTANCE Channel WITH Data <- Message, chan <- c 6 | ----------------------------------------------------------------------------- 7 | Init == /\ MyChan(in)!Init 8 | /\ MyChan(out)!Init 9 | /\ q = << >> 10 | 11 | TypeInvariant == /\ MyChan(in)!TypeInvariant 12 | /\ MyChan(out)!TypeInvariant 13 | (*RVR /\ q \in Seq(Message) *) 14 | 15 | SSend(msg) == /\ MyChan(in)!Send(msg) \* Send msg on channel `in'. 16 | /\ UNCHANGED <> 17 | 18 | BufRcv == /\ MyChan(in)!Rcv \* Receive message from channel `in'. 19 | /\ q' = Append(q, in.val) \* and append it to tail of q. 20 | /\ UNCHANGED out 21 | 22 | BufSend == /\ q # << >> \* Enabled only if q is nonempty. 23 | /\ MyChan(out)!Send(Head(q)) \* Send Head(q) on channel `out' 24 | /\ q' = Tail(q) \* and remove it from q. 25 | /\ UNCHANGED in 26 | 27 | RRcv == /\ MyChan(out)!Rcv \* Receive message from channel `out'. 28 | /\ UNCHANGED <> 29 | 30 | Next == \/ \E msg \in Message : SSend(msg) 31 | \/ BufRcv 32 | \/ BufSend 33 | \/ RRcv 34 | 35 | Spec == Init /\ [][Next]_<> 36 | ----------------------------------------------------------------------------- 37 | THEOREM Spec => []TypeInvariant 38 | TypeInvariant == TRUE 39 | ============================================================================= 40 | -------------------------------------------------------------------------------- /modules/book/InnerFIFO.tla: -------------------------------------------------------------------------------- 1 | ---------------------------- MODULE InnerFIFO ------------------------------- 2 | EXTENDS Naturals, Sequences 3 | CONSTANT Message 4 | VARIABLES in, out, q 5 | InChan == INSTANCE Channel WITH Data <- Message, chan <- in 6 | OutChan == INSTANCE Channel WITH Data <- Message, chan <- out 7 | ----------------------------------------------------------------------------- 8 | Init == /\ InChan!Init 9 | /\ OutChan!Init 10 | /\ q = << >> 11 | 12 | TypeInvariant == /\ InChan!TypeInvariant 13 | /\ OutChan!TypeInvariant 14 | (*RVR /\ q \in Seq(Message) *) 15 | 16 | SSend(msg) == /\ InChan!Send(msg) \* Send msg on channel `in'. 17 | /\ UNCHANGED <> 18 | 19 | BufRcv == /\ InChan!Rcv \* Receive message from channel `in'. 20 | /\ q' = Append(q, in.val) \* and append it to tail of q. 21 | /\ UNCHANGED out 22 | 23 | BufSend == /\ q # << >> \* Enabled only if q is nonempty. 24 | /\ OutChan!Send(Head(q)) \* Send Head(q) on channel `out' 25 | /\ q' = Tail(q) \* and remove it from q. 26 | /\ UNCHANGED in 27 | 28 | RRcv == /\ OutChan!Rcv \* Receive message from channel `out'. 29 | /\ UNCHANGED <> 30 | 31 | Next == \/ \E msg \in Message : SSend(msg) 32 | \/ BufRcv 33 | \/ BufSend 34 | \/ RRcv 35 | 36 | Spec == Init /\ [][Next]_<> 37 | ----------------------------------------------------------------------------- 38 | THEOREM Spec => []TypeInvariant 39 | TypeInvariant == TRUE 40 | ============================================================================= 41 | -------------------------------------------------------------------------------- /modules/other/BinBosco2.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE BinBosco2 ----------------------------- 2 | 3 | EXTENDS Naturals, FiniteSets 4 | (* See below... 5 | CONSTANTS Processes, Quorums, Data, Inputs 6 | ASSUME \A q \in Quorums: q \subseteq Processes 7 | ASSUME \A q1, q2, q3 \in Quorums: q1 \intersect q2 \intersect q3 /= {} 8 | ASSUME Inputs \in [Processes -> Data ] 9 | ASSUME Cardinality(Data) \in { 1, 2 } 10 | *) 11 | VARIABLE mystate, Messages 12 | 13 | (* TODO. Use "INSTANCE" to do this *) 14 | Processes == { 0, 1, 2, 3 } 15 | Quorums == { { 0, 1, 2 }, { 0, 1, 3 }, { 0, 2, 3 }, { 1, 2, 3 } } 16 | Data == { "red", "blue" } 17 | Inputs == << "red", "blue", "red", "blue" >> 18 | 19 | Init == 20 | /\ mystate = [ round |-> 0, estimate |-> 0 ] 21 | /\ Messages = {} 22 | 23 | Start(p) == 24 | /\ mystate.round = 0 25 | /\ mystate' = [ round |-> 1, estimate |-> Inputs[p] ] 26 | /\ Messages' = Messages \union { [ src |-> p, vote |-> mystate' ] } 27 | 28 | Step(p, q1, q2, e) == 29 | /\ \A p2 \in q1 \intersect q2: [ src |-> p2, vote |-> [ round |-> mystate.round, estimate |-> e ] ] \in Messages 30 | /\ mystate' = [ round |-> mystate.round + 1, estimate |-> e ] 31 | /\ Messages' = Messages \union { [ src |-> p, vote |-> mystate' ] } 32 | 33 | Catchup(p, m) == 34 | /\ m.vote.round > mystate.round 35 | /\ mystate' = m.vote 36 | /\ Messages' = Messages \union { [ src |-> p, vote |-> mystate' ] } 37 | 38 | Proc(p) == 39 | \/ Start(p) 40 | \/ \E q1, q2 \in Quorums, e \in Data: Step(p, q1, q2, e) 41 | \/ \E m \in Messages: Catchup(p, m) 42 | 43 | Next == \E p \in Processes: Proc(p) 44 | 45 | Spec == Init /\ [][Next]_<> 46 | 47 | ============================================================================= 48 | -------------------------------------------------------------------------------- /modules/other/BinBosco.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE BinBosco ----------------------------- 2 | EXTENDS Naturals, FiniteSets, TLC 3 | CONSTANTS Processes, Inputs, Quorums, Data 4 | 5 | ASSUME \A q \in Quorums: q \subseteq Processes 6 | ASSUME \A q1, q2, q3 \in Quorums: q1 \intersect q2 \intersect q3 /= {} 7 | ASSUME Cardinality(Data) \in { 1, 2 } 8 | 9 | VARIABLES procs, mi, msgs 10 | 11 | Rnd == Nat 12 | 13 | \* Type of vote 14 | Vote == [ round: Rnd, estimate: Data ] 15 | 16 | \* Type of message 17 | Message == [ src: Processes, vote: Vote ] 18 | 19 | Network == INSTANCE Messaging 20 | 21 | Init == 22 | /\ procs = [ p \in Processes |-> [ round |-> 0, estimate |-> Inputs[p] ] ] 23 | /\ msgs = [ p \in Processes |-> {} ] 24 | /\ Network!Init 25 | 26 | Start(p) == 27 | /\ procs[p].round = 0 28 | /\ procs' = [ procs EXCEPT ![p] = [ round |-> 1, estimate |-> procs[p].estimate ] ] 29 | /\ Network!Send( 30 | {< p, vote |-> procs'[p] ]>> : q \in Processes }) 31 | /\ UNCHANGED msgs 32 | 33 | Step(p, q1, q2, e) == 34 | /\ procs[p].round < 5 (* useful for testing *) 35 | /\ \A p2 \in q1 \intersect q2: [ src |-> p2, vote |-> [ round |-> procs[p].round, estimate |-> e ] ] \in msgs[p] 36 | /\ procs' = [ procs EXCEPT ![p] = [ round |-> procs[p].round + 1, estimate |-> e ] ] 37 | /\ Network!Send( 38 | {< p, vote |-> procs'[p] ]>> : q \in Processes }) 39 | /\ UNCHANGED msgs 40 | 41 | \* Get rid of messages no longer needed (for better output and scalability) 42 | Cleanup(p, m) == 43 | /\ m.vote.round < procs[p].round 44 | /\ msgs' = [ msgs EXCEPT ![p] = @ \ {m} ] 45 | /\ UNCHANGED <> 46 | 47 | Catchup(p, m) == 48 | /\ m.vote.round > procs[p].round 49 | /\ procs' = [ procs EXCEPT ![p] = m.vote ] 50 | /\ Network!Send( 51 | {< p, vote |-> procs'[p] ]>> : q \in Processes }) 52 | /\ UNCHANGED msgs 53 | 54 | Deliver(p, m) == 55 | \* /\ PrintT("DELIVER " \o ToString(p) \o " " \o ToString(m)) 56 | /\ msgs' = [ msgs EXCEPT ![p] = @ \union { m } ] 57 | /\ UNCHANGED procs 58 | 59 | Proc(p) == 60 | \/ Start(p) 61 | \/ \E q1, q2 \in Quorums, e \in Data: Step(p, q1, q2, e) 62 | \/ Network!Receive(p, Deliver) 63 | \/ \E m \in msgs[p]: (Cleanup(p, m) \/ Catchup(p, m)) 64 | 65 | Next == \E p \in Processes: Proc(p) 66 | 67 | Spec == Init /\ [][Next]_<> 68 | 69 | ============================================================================= 70 | -------------------------------------------------------------------------------- /test_pluspy.py: -------------------------------------------------------------------------------- 1 | import pluspy 2 | import unittest 3 | 4 | 5 | class TestLexer(unittest.TestCase): 6 | def test_ignore_preamble(self): 7 | cases = [ 8 | { 9 | "name": "preamble", 10 | "input": ''' 11 | This is some prose preceding the module definition. 12 | 13 | \* WORKAROUND: Comment prose before the module definition. 14 | 15 | ---- MODULE AsyncGameOfLifeDistributed ----- 16 | 17 | VARIABLE x 18 | Spec == x = TRUE /\ [][x'\in BOOLEAN]_x 19 | ==== 20 | ''', 21 | }, 22 | { 23 | "name": "preamble with four dashes", 24 | "input": ''' 25 | ---- What is this 26 | 27 | \* A comment 28 | 29 | And more preamble there is. 30 | 31 | ------------------------------- MODULE Somename ------------------------------- 32 | ''', 33 | }, 34 | { 35 | "name": "preamble with commented module", 36 | "input": '''' 37 | ---- What is this 38 | 39 | \* A comment 40 | \* ---- MODULE foo ---- 41 | And more preamble there is. 42 | 43 | ------------------------------- MODULE Foo ------------------------------- 44 | 45 | 46 | ================================ ============================================= 47 | ''' 48 | }, 49 | ] 50 | 51 | for case in cases: 52 | results = pluspy.lexer(case["input"], "nofile.tla") 53 | a, b, _, d = results[0], results[1], results[2], results[3] 54 | self.assertEqual( 55 | "----", pluspy.lexeme(a), 56 | "failed test {} expected {}, actual {}".format( 57 | case["name"], "----", a 58 | ), 59 | ) 60 | self.assertEqual( 61 | "MODULE", pluspy.lexeme(b), 62 | "failed test {} expected {}, actual {}".format( 63 | case["name"], "MODULE", b 64 | ), 65 | ) 66 | self.assertEqual( 67 | "----", pluspy.lexeme(d), 68 | "failed test {} expected {}, actual {}".format( 69 | case["name"], "----", a 70 | ), 71 | ) 72 | 73 | 74 | -------------------------------------------------------------------------------- /modules/lib/Messaging.tla: -------------------------------------------------------------------------------- 1 | ------------------------ MODULE Messaging ------------------------ 2 | \* This module specifies a reliable FIFO point-to-point messaging 3 | \* interface between a set of processes 4 | 5 | LOCAL INSTANCE Naturals 6 | LOCAL INSTANCE Sequences 7 | CONSTANT Processes, Message 8 | VARIABLE mi 9 | 10 | \*++:SPEC 11 | 12 | \* mi contains the state of the messaging interface. 13 | \* It is a map of processes to queues of undelivered messages 14 | LOCAL TypeInvariant == mi \in [Processes -> Seq(Message)] 15 | 16 | LOCAL InitialState(procs) == [ p \in procs |-> <<>> ] 17 | 18 | \* Initially no messages are undelivered 19 | Init == mi = InitialState(Processes) 20 | 21 | \* Function takes intf, the state of the messaging interface, and msgs, a 22 | \* set of << destination, message >> pairs, and updates the state by adding 23 | \* the message to the right (destination) queue of undelivered messages. 24 | LOCAL doSend[intf \in [Processes -> Seq(Message)], 25 | msgs \in SUBSET 26 | {<> : proc \in Processes, msg \in Message}] == 27 | IF msgs = {} THEN intf 28 | ELSE 29 | LET m == CHOOSE m \in msgs : TRUE 30 | IN doSend[[intf EXCEPT ![m[1]] = Append(@, m[2])], msgs \ {m}] 31 | 32 | \* Helper operator for Send() 33 | LOCAL SendAll(intf, msgs) == doSend[intf, msgs] 34 | 35 | \* msgs is a set of << destination, payload >> pairs. The intention 36 | \* is to deliver each payload to the given destination process. 37 | Send(msgs) == mi' = SendAll(mi, msgs) 38 | 39 | \* Helper operators for Receive() 40 | LOCAL WaitForMessage(intf, p) == intf[p] /= <<>> 41 | LOCAL NextMessage(intf, p) == Head(intf[p]) 42 | LOCAL DeliveredMessage(intf, p) == [ intf EXCEPT ![p] = Tail(@) ] 43 | 44 | \* Process p is trying to receive a message. If its queue of undelivered 45 | \* messages is non-empty, invoke Deliver(p, m) with m being the first 46 | \* message on its queue. Deliver should return TRUE if successful. 47 | \* If so, remove the message from the queue. 48 | Receive(p, Deliver(_, _)) == 49 | /\ WaitForMessage(mi, p) 50 | /\ Deliver(p, NextMessage(mi, p)) 51 | /\ mi' = DeliveredMessage(mi, p) 52 | 53 | ========================================================================= 54 | 55 | \*++:PlusPy 56 | 57 | LOCAL INSTANCE IOUtils 58 | 59 | \* Initially no messages are undelivered 60 | Init == mi = TRUE 61 | 62 | \* msgs is a set of << destination, payload >> pairs. The intention 63 | \* is to deliver each payload to the given destination process. 64 | Send(msgs) == mi' = \A x \in msgs: IOPut("tcp", x[1], x[2]) 65 | 66 | \* Process p is trying to receive a message. If its queue of undelivered 67 | \* messages is non-empty, invoke Deliver(p, m) with m being the first 68 | \* message on its queue. Deliver should return TRUE if successful. 69 | \* If so, remove the message from the queue. 70 | Receive(p, Deliver(_, _)) == 71 | /\ IOWait("tcp", p) 72 | /\ Deliver(p, IOGet("tcp", p)) 73 | /\ UNCHANGED mi 74 | 75 | ========================================================================= 76 | -------------------------------------------------------------------------------- /tests/regression/test1.exp: -------------------------------------------------------------------------------- 1 | Initial context: [ hr |-> 7 ] 2 | Next state: 0 [ hr |-> 8 ] 3 | Next state: 1 [ hr |-> 9 ] 4 | Next state: 2 [ hr |-> 10 ] 5 | Next state: 3 [ hr |-> 11 ] 6 | Next state: 4 [ hr |-> 12 ] 7 | Next state: 5 [ hr |-> 1 ] 8 | Next state: 6 [ hr |-> 2 ] 9 | Next state: 7 [ hr |-> 3 ] 10 | Next state: 8 [ hr |-> 4 ] 11 | Next state: 9 [ hr |-> 5 ] 12 | Next state: 10 [ hr |-> 6 ] 13 | Next state: 11 [ hr |-> 7 ] 14 | Next state: 12 [ hr |-> 8 ] 15 | Next state: 13 [ hr |-> 9 ] 16 | Next state: 14 [ hr |-> 10 ] 17 | Next state: 15 [ hr |-> 11 ] 18 | Next state: 16 [ hr |-> 12 ] 19 | Next state: 17 [ hr |-> 1 ] 20 | Next state: 18 [ hr |-> 2 ] 21 | Next state: 19 [ hr |-> 3 ] 22 | Next state: 20 [ hr |-> 4 ] 23 | Next state: 21 [ hr |-> 5 ] 24 | Next state: 22 [ hr |-> 6 ] 25 | Next state: 23 [ hr |-> 7 ] 26 | Next state: 24 [ hr |-> 8 ] 27 | Next state: 25 [ hr |-> 9 ] 28 | Next state: 26 [ hr |-> 10 ] 29 | Next state: 27 [ hr |-> 11 ] 30 | Next state: 28 [ hr |-> 12 ] 31 | Next state: 29 [ hr |-> 1 ] 32 | Next state: 30 [ hr |-> 2 ] 33 | Next state: 31 [ hr |-> 3 ] 34 | Next state: 32 [ hr |-> 4 ] 35 | Next state: 33 [ hr |-> 5 ] 36 | Next state: 34 [ hr |-> 6 ] 37 | Next state: 35 [ hr |-> 7 ] 38 | Next state: 36 [ hr |-> 8 ] 39 | Next state: 37 [ hr |-> 9 ] 40 | Next state: 38 [ hr |-> 10 ] 41 | Next state: 39 [ hr |-> 11 ] 42 | Next state: 40 [ hr |-> 12 ] 43 | Next state: 41 [ hr |-> 1 ] 44 | Next state: 42 [ hr |-> 2 ] 45 | Next state: 43 [ hr |-> 3 ] 46 | Next state: 44 [ hr |-> 4 ] 47 | Next state: 45 [ hr |-> 5 ] 48 | Next state: 46 [ hr |-> 6 ] 49 | Next state: 47 [ hr |-> 7 ] 50 | Next state: 48 [ hr |-> 8 ] 51 | Next state: 49 [ hr |-> 9 ] 52 | Next state: 50 [ hr |-> 10 ] 53 | Next state: 51 [ hr |-> 11 ] 54 | Next state: 52 [ hr |-> 12 ] 55 | Next state: 53 [ hr |-> 1 ] 56 | Next state: 54 [ hr |-> 2 ] 57 | Next state: 55 [ hr |-> 3 ] 58 | Next state: 56 [ hr |-> 4 ] 59 | Next state: 57 [ hr |-> 5 ] 60 | Next state: 58 [ hr |-> 6 ] 61 | Next state: 59 [ hr |-> 7 ] 62 | Next state: 60 [ hr |-> 8 ] 63 | Next state: 61 [ hr |-> 9 ] 64 | Next state: 62 [ hr |-> 10 ] 65 | Next state: 63 [ hr |-> 11 ] 66 | Next state: 64 [ hr |-> 12 ] 67 | Next state: 65 [ hr |-> 1 ] 68 | Next state: 66 [ hr |-> 2 ] 69 | Next state: 67 [ hr |-> 3 ] 70 | Next state: 68 [ hr |-> 4 ] 71 | Next state: 69 [ hr |-> 5 ] 72 | Next state: 70 [ hr |-> 6 ] 73 | Next state: 71 [ hr |-> 7 ] 74 | Next state: 72 [ hr |-> 8 ] 75 | Next state: 73 [ hr |-> 9 ] 76 | Next state: 74 [ hr |-> 10 ] 77 | Next state: 75 [ hr |-> 11 ] 78 | Next state: 76 [ hr |-> 12 ] 79 | Next state: 77 [ hr |-> 1 ] 80 | Next state: 78 [ hr |-> 2 ] 81 | Next state: 79 [ hr |-> 3 ] 82 | Next state: 80 [ hr |-> 4 ] 83 | Next state: 81 [ hr |-> 5 ] 84 | Next state: 82 [ hr |-> 6 ] 85 | Next state: 83 [ hr |-> 7 ] 86 | Next state: 84 [ hr |-> 8 ] 87 | Next state: 85 [ hr |-> 9 ] 88 | Next state: 86 [ hr |-> 10 ] 89 | Next state: 87 [ hr |-> 11 ] 90 | Next state: 88 [ hr |-> 12 ] 91 | Next state: 89 [ hr |-> 1 ] 92 | Next state: 90 [ hr |-> 2 ] 93 | Next state: 91 [ hr |-> 3 ] 94 | Next state: 92 [ hr |-> 4 ] 95 | Next state: 93 [ hr |-> 5 ] 96 | Next state: 94 [ hr |-> 6 ] 97 | Next state: 95 [ hr |-> 7 ] 98 | Next state: 96 [ hr |-> 8 ] 99 | Next state: 97 [ hr |-> 9 ] 100 | Next state: 98 [ hr |-> 10 ] 101 | Next state: 99 [ hr |-> 11 ] 102 | MAIN DONE 103 | -------------------------------------------------------------------------------- /modules/lib/Sequences.tla: -------------------------------------------------------------------------------- 1 | ------------------------------ MODULE Sequences ----------------------------- 2 | (***************************************************************************) 3 | (* Defines operators on finite sequences, where a sequence of length n is *) 4 | (* represented as a function whose domain is the set 1..n (the set *) 5 | (* {1, 2, ... , n}). This is also how TLA+ defines an n-tuple, so *) 6 | (* tuples are sequences. *) 7 | (***************************************************************************) 8 | 9 | LOCAL INSTANCE Naturals 10 | (*************************************************************************) 11 | (* Imports the definitions from Naturals, but don't export them. *) 12 | (*************************************************************************) 13 | 14 | Seq(S) == UNION {[1..n -> S] : n \in Nat} 15 | (*************************************************************************) 16 | (* The set of all sequences of elements in S. *) 17 | (*************************************************************************) 18 | 19 | Len(s) == CHOOSE n \in Nat : DOMAIN s = 1..n 20 | (*************************************************************************) 21 | (* The length of sequence s. *) 22 | (*************************************************************************) 23 | 24 | s \o t == [i \in 1..(Len(s) + Len(t)) |-> IF i \leq Len(s) THEN s[i] 25 | ELSE t[i-Len(s)]] 26 | (*************************************************************************) 27 | (* The sequence obtained by concatenating sequences s and t. *) 28 | (*************************************************************************) 29 | 30 | Append(s, e) == s \o <> 31 | (**************************************************************************) 32 | (* The sequence obtained by appending element e to the end of sequence s. *) 33 | (**************************************************************************) 34 | 35 | Head(s) == s[1] 36 | 37 | Tail(s) == CASE s # << >> -> [i \in 1..(Len(s)-1) |-> s[i+1]] 38 | (*************************************************************************) 39 | (* The usual head (first) and tail (rest) operators. (Definition of Tail *) 40 | (* changed on 4 Jun 2013 because original defined Tail(<< >>) = << >> . *) 41 | (*************************************************************************) 42 | 43 | SubSeq(s, m, n) == [i \in 1..(1+n-m) |-> s[i+m-1]] 44 | (*************************************************************************) 45 | (* The sequence <>. *) 46 | (*************************************************************************) 47 | 48 | SelectSeq(s, Test(_)) == 49 | (*************************************************************************) 50 | (* The subsequence of s consisting of all elements s[i] such that *) 51 | (* Test(s[i]) is true. *) 52 | (*************************************************************************) 53 | LET F[i \in 0..Len(s)] == 54 | (*******************************************************************) 55 | (* F[i] equals SelectSeq(SubSeq(s, 1, i), Test] *) 56 | (*******************************************************************) 57 | IF i = 0 THEN << >> 58 | ELSE IF Test(s[i]) THEN Append(F[i-1], s[i]) 59 | ELSE F[i-1] 60 | IN F[Len(s)] 61 | 62 | ============================================================================= 63 | -------------------------------------------------------------------------------- /modules/book/Peterson.tla: -------------------------------------------------------------------------------- 1 | ------------------------------ MODULE Peterson ------------------------------ 2 | EXTENDS Naturals 3 | 4 | (* --algorithm Peterson { 5 | variables flag = [i \in {0, 1} |-> FALSE], turn = 0; 6 | \* Declares the global variables flag and turn and their initial values; 7 | \* flag is a 2-element array with initially flag[0] = flag[1] = FALSE. 8 | fair process (proc \in {0,1}) { 9 | \* Declares two processes with identifier self equal to 0 and 1. 10 | \* The keyword fair means that no process can stop forever if it can 11 | \* always take a step. 12 | a1: while (TRUE) { 13 | skip ; \* the noncritical section 14 | a2: flag[self] := TRUE ; 15 | a3: turn := 1 - self ; 16 | a4: while (TRUE) { 17 | a4a: if (flag[1-self] = FALSE) {goto cs}; 18 | a4b: if (turn = self) {goto cs} } ; 19 | cs: skip ; \* the critical section 20 | a5: flag[self] := FALSE ; 21 | a6: turn := self 22 | } 23 | } 24 | } 25 | *) 26 | \* BEGIN TRANSLATION 27 | VARIABLES flag, turn, pc 28 | 29 | vars == << flag, turn, pc >> 30 | 31 | ProcSet == ({0,1}) 32 | 33 | Init == (* Global variables *) 34 | /\ flag = [i \in {0, 1} |-> FALSE] 35 | /\ turn = 0 36 | /\ pc = [self \in ProcSet |-> "a1"] 37 | 38 | a1(self) == /\ pc[self] = "a1" 39 | /\ TRUE 40 | /\ pc' = [pc EXCEPT ![self] = "a2"] 41 | /\ UNCHANGED << flag, turn >> 42 | 43 | a2(self) == /\ pc[self] = "a2" 44 | /\ flag' = [flag EXCEPT ![self] = TRUE] 45 | /\ pc' = [pc EXCEPT ![self] = "a3"] 46 | /\ UNCHANGED turn 47 | 48 | a3(self) == /\ pc[self] = "a3" 49 | /\ turn' = 1 - self 50 | /\ pc' = [pc EXCEPT ![self] = "a4"] 51 | /\ UNCHANGED flag 52 | 53 | a4(self) == /\ pc[self] = "a4" 54 | /\ pc' = [pc EXCEPT ![self] = "a4a"] 55 | /\ UNCHANGED << flag, turn >> 56 | 57 | a4a(self) == /\ pc[self] = "a4a" 58 | /\ IF flag[1-self] = FALSE 59 | THEN /\ pc' = [pc EXCEPT ![self] = "cs"] 60 | ELSE /\ pc' = [pc EXCEPT ![self] = "a4b"] 61 | /\ UNCHANGED << flag, turn >> 62 | 63 | a4b(self) == /\ pc[self] = "a4b" 64 | /\ IF turn = self 65 | THEN /\ pc' = [pc EXCEPT ![self] = "cs"] 66 | ELSE /\ pc' = [pc EXCEPT ![self] = "a4"] 67 | /\ UNCHANGED << flag, turn >> 68 | 69 | cs(self) == /\ pc[self] = "cs" 70 | /\ pc' = [pc EXCEPT ![self] = "a5"] 71 | /\ UNCHANGED << flag, turn >> 72 | 73 | a5(self) == /\ pc[self] = "a5" 74 | /\ flag' = [flag EXCEPT ![self] = FALSE] 75 | /\ pc' = [pc EXCEPT ![self] = "a6"] 76 | /\ UNCHANGED turn 77 | 78 | a6(self) == /\ pc[self] = "a6" 79 | /\ turn' = self 80 | /\ pc' = [pc EXCEPT ![self] = "a1"] 81 | /\ UNCHANGED flag 82 | 83 | proc(self) == a1(self) \/ a2(self) \/ a3(self) \/ a4(self) \/ a4a(self) 84 | \/ a4b(self) \/ cs(self) \/ a5(self) \/ a6(self) 85 | 86 | Next == (\E self \in {0,1}: proc(self)) 87 | 88 | Spec == /\ Init /\ [][Next]_vars 89 | /\ \A self \in {0,1} : WF_vars(proc(self)) 90 | 91 | \* END TRANSLATION 92 | 93 | THEOREM Spec => [] (pc[0] /= "cs") \/ (pc[1] /= "cs") 94 | 95 | THEOREM Spec => \A i \in {0,1} : []<>(pc[i] = "cs") 96 | 97 | ============================================================================= 98 | \* Modification History 99 | \* Last modified Sat Mar 14 05:47:06 EDT 2020 by rvr 100 | \* Created Sat Feb 29 21:49:27 EST 2020 by rvr 101 | -------------------------------------------------------------------------------- /modules/other/BlockingQueueSplit.tla: -------------------------------------------------------------------------------- 1 | ------------------------- MODULE BlockingQueueSplit ------------------------- 2 | EXTENDS Naturals, Sequences, FiniteSets, TLCExt 3 | 4 | CONSTANTS Producers, (* the (nonempty) set of producers *) 5 | Consumers, (* the (nonempty) set of consumers *) 6 | BufCapacity (* the maximum number of messages in the bounded buffer *) 7 | 8 | ASSUME Assumption == 9 | /\ Producers # {} (* at least one producer *) 10 | /\ Consumers # {} (* at least one consumer *) 11 | /\ Producers \intersect Consumers = {} (* no thread is both consumer and producer *) 12 | /\ BufCapacity \in (Nat \ {0}) (* buffer capacity is at least 1 *) 13 | 14 | ----------------------------------------------------------------------------- 15 | 16 | VARIABLES buffer, waitSetC, waitSetP 17 | vars == <> 18 | 19 | RunningThreads == (Producers \cup Consumers) \ (waitSetC \cup waitSetP) 20 | 21 | NotifyOther(ws, d) == 22 | \/ /\ ws = {} 23 | /\ UNCHANGED ws 24 | /\ JReturn(d) 25 | \/ /\ ws # {} 26 | /\ \E t \in ws: ws' = ws \ {t} /\ JSignalReturn(t, d) 27 | 28 | (* @see java.lang.Object#wait *) 29 | Wait(ws, t) == /\ ws' = ws \cup {t} 30 | /\ JWait(t) 31 | 32 | ----------------------------------------------------------------------------- 33 | 34 | Put(t, d) == 35 | /\ \/ /\ Len(buffer) < BufCapacity 36 | /\ NotifyOther(waitSetC, "done") 37 | /\ buffer' = Append(buffer, d) 38 | /\ UNCHANGED waitSetP 39 | \/ /\ Len(buffer) = BufCapacity 40 | /\ Wait(waitSetP, t) 41 | /\ UNCHANGED <> 42 | /\ t \notin waitSetP 43 | 44 | Get(t) == 45 | /\ t \notin waitSetC 46 | /\ \/ /\ buffer # <<>> 47 | /\ buffer' = Tail(buffer) 48 | /\ NotifyOther(waitSetP, Head(buffer)) 49 | /\ UNCHANGED waitSetC 50 | \/ /\ buffer = <<>> 51 | /\ Wait(waitSetC, t) 52 | /\ UNCHANGED <> 53 | 54 | ----------------------------------------------------------------------------- 55 | 56 | TypeInv == /\ Len(buffer) \in 0..BufCapacity 57 | /\ waitSetP \in SUBSET Producers 58 | /\ waitSetC \in SUBSET Consumers 59 | 60 | (* Initially, the buffer is empty and no thread is waiting. *) 61 | Init == /\ buffer = <<>> 62 | /\ waitSetC = {} 63 | /\ waitSetP = {} 64 | 65 | (* Then, pick a thread out of all running threads and have it do its thing. *) 66 | Next == \/ \E p \in Producers: Put(p, p) \* Add some data to buffer 67 | \/ \E c \in Consumers: Get(c) 68 | 69 | Spec == Init /\ [][Next]_vars 70 | 71 | 72 | (*RVR: no support for TLAPS yet 73 | 74 | (* BlockingQueueSplit refines BlockingQueue. The refinement mapping is *) 75 | (* straight forward in this case. The union of waitSetC and waitSetP *) 76 | (* maps to waitSet in the high-level spec BlockingQueue. *) 77 | A == INSTANCE BlockingQueue WITH waitSet <- (waitSetC \cup waitSetP) 78 | 79 | (* A!Spec is not a valid value in the config BlockingQueueSplit.cfg. *) 80 | ASpec == A!Spec 81 | 82 | ----------------------------------------------------------------------------- 83 | 84 | INSTANCE TLAPS 85 | 86 | (* Scaffolding: TypeInv is inductive. *) 87 | LEMMA ITypeInv == Spec => []TypeInv 88 | <1> USE Assumption DEF TypeInv 89 | <1>1. Init => TypeInv 90 | BY SMT DEF Init 91 | <1>2. TypeInv /\ [Next]_vars => TypeInv' 92 | BY SMT DEF Next, vars, Put, Get, Wait, NotifyOther 93 | <1>3. QED 94 | BY <1>1, <1>2, PTL DEF Spec 95 | 96 | THEOREM Implements == Spec => A!Spec 97 | <1> USE Assumption, A!Assumption 98 | <1>1. Init => A!Init 99 | BY Isa DEF Init, A!Init 100 | <1>2. TypeInv /\ [Next]_vars => [A!Next]_A!vars 101 | BY SMT DEF TypeInv, Next, vars, Put, Get, Wait, NotifyOther, A!Next, 102 | A!vars, A!Put, A!Get, A!Wait, A!NotifyOther 103 | <1>3. QED BY <1>1, <1>2, PTL, ITypeInv DEF Spec, A!Spec 104 | 105 | RVR*) 106 | 107 | ============================================================================= 108 | -------------------------------------------------------------------------------- /tests/regression/test3.exp: -------------------------------------------------------------------------------- 1 | Initial context: [ count |-> 1, p |-> 2 ] 2 | Next state: 0 [ count |-> 2, p |-> 3 ] 3 | Next state: 1 [ count |-> 3, p |-> 5 ] 4 | Next state: 2 [ count |-> 4, p |-> 7 ] 5 | Next state: 3 [ count |-> 5, p |-> 11 ] 6 | Next state: 4 [ count |-> 6, p |-> 13 ] 7 | Next state: 5 [ count |-> 7, p |-> 17 ] 8 | Next state: 6 [ count |-> 8, p |-> 19 ] 9 | Next state: 7 [ count |-> 9, p |-> 23 ] 10 | Next state: 8 [ count |-> 10, p |-> 29 ] 11 | Next state: 9 [ count |-> 11, p |-> 31 ] 12 | Next state: 10 [ count |-> 12, p |-> 37 ] 13 | Next state: 11 [ count |-> 13, p |-> 41 ] 14 | Next state: 12 [ count |-> 14, p |-> 43 ] 15 | Next state: 13 [ count |-> 15, p |-> 47 ] 16 | Next state: 14 [ count |-> 16, p |-> 53 ] 17 | Next state: 15 [ count |-> 17, p |-> 59 ] 18 | Next state: 16 [ count |-> 18, p |-> 61 ] 19 | Next state: 17 [ count |-> 19, p |-> 67 ] 20 | Next state: 18 [ count |-> 20, p |-> 71 ] 21 | Next state: 19 [ count |-> 21, p |-> 73 ] 22 | Next state: 20 [ count |-> 22, p |-> 79 ] 23 | Next state: 21 [ count |-> 23, p |-> 83 ] 24 | Next state: 22 [ count |-> 24, p |-> 89 ] 25 | Next state: 23 [ count |-> 25, p |-> 97 ] 26 | Next state: 24 [ count |-> 26, p |-> 101 ] 27 | Next state: 25 [ count |-> 27, p |-> 103 ] 28 | Next state: 26 [ count |-> 28, p |-> 107 ] 29 | Next state: 27 [ count |-> 29, p |-> 109 ] 30 | Next state: 28 [ count |-> 30, p |-> 113 ] 31 | Next state: 29 [ count |-> 31, p |-> 127 ] 32 | Next state: 30 [ count |-> 32, p |-> 131 ] 33 | Next state: 31 [ count |-> 33, p |-> 137 ] 34 | Next state: 32 [ count |-> 34, p |-> 139 ] 35 | Next state: 33 [ count |-> 35, p |-> 149 ] 36 | Next state: 34 [ count |-> 36, p |-> 151 ] 37 | Next state: 35 [ count |-> 37, p |-> 157 ] 38 | Next state: 36 [ count |-> 38, p |-> 163 ] 39 | Next state: 37 [ count |-> 39, p |-> 167 ] 40 | Next state: 38 [ count |-> 40, p |-> 173 ] 41 | Next state: 39 [ count |-> 41, p |-> 179 ] 42 | Next state: 40 [ count |-> 42, p |-> 181 ] 43 | Next state: 41 [ count |-> 43, p |-> 191 ] 44 | Next state: 42 [ count |-> 44, p |-> 193 ] 45 | Next state: 43 [ count |-> 45, p |-> 197 ] 46 | Next state: 44 [ count |-> 46, p |-> 199 ] 47 | Next state: 45 [ count |-> 47, p |-> 211 ] 48 | Next state: 46 [ count |-> 48, p |-> 223 ] 49 | Next state: 47 [ count |-> 49, p |-> 227 ] 50 | Next state: 48 [ count |-> 50, p |-> 229 ] 51 | Next state: 49 [ count |-> 51, p |-> 233 ] 52 | Next state: 50 [ count |-> 52, p |-> 239 ] 53 | Next state: 51 [ count |-> 53, p |-> 241 ] 54 | Next state: 52 [ count |-> 54, p |-> 251 ] 55 | Next state: 53 [ count |-> 55, p |-> 257 ] 56 | Next state: 54 [ count |-> 56, p |-> 263 ] 57 | Next state: 55 [ count |-> 57, p |-> 269 ] 58 | Next state: 56 [ count |-> 58, p |-> 271 ] 59 | Next state: 57 [ count |-> 59, p |-> 277 ] 60 | Next state: 58 [ count |-> 60, p |-> 281 ] 61 | Next state: 59 [ count |-> 61, p |-> 283 ] 62 | Next state: 60 [ count |-> 62, p |-> 293 ] 63 | Next state: 61 [ count |-> 63, p |-> 307 ] 64 | Next state: 62 [ count |-> 64, p |-> 311 ] 65 | Next state: 63 [ count |-> 65, p |-> 313 ] 66 | Next state: 64 [ count |-> 66, p |-> 317 ] 67 | Next state: 65 [ count |-> 67, p |-> 331 ] 68 | Next state: 66 [ count |-> 68, p |-> 337 ] 69 | Next state: 67 [ count |-> 69, p |-> 347 ] 70 | Next state: 68 [ count |-> 70, p |-> 349 ] 71 | Next state: 69 [ count |-> 71, p |-> 353 ] 72 | Next state: 70 [ count |-> 72, p |-> 359 ] 73 | Next state: 71 [ count |-> 73, p |-> 367 ] 74 | Next state: 72 [ count |-> 74, p |-> 373 ] 75 | Next state: 73 [ count |-> 75, p |-> 379 ] 76 | Next state: 74 [ count |-> 76, p |-> 383 ] 77 | Next state: 75 [ count |-> 77, p |-> 389 ] 78 | Next state: 76 [ count |-> 78, p |-> 397 ] 79 | Next state: 77 [ count |-> 79, p |-> 401 ] 80 | Next state: 78 [ count |-> 80, p |-> 409 ] 81 | Next state: 79 [ count |-> 81, p |-> 419 ] 82 | Next state: 80 [ count |-> 82, p |-> 421 ] 83 | Next state: 81 [ count |-> 83, p |-> 431 ] 84 | Next state: 82 [ count |-> 84, p |-> 433 ] 85 | Next state: 83 [ count |-> 85, p |-> 439 ] 86 | Next state: 84 [ count |-> 86, p |-> 443 ] 87 | Next state: 85 [ count |-> 87, p |-> 449 ] 88 | Next state: 86 [ count |-> 88, p |-> 457 ] 89 | Next state: 87 [ count |-> 89, p |-> 461 ] 90 | Next state: 88 [ count |-> 90, p |-> 463 ] 91 | Next state: 89 [ count |-> 91, p |-> 467 ] 92 | Next state: 90 [ count |-> 92, p |-> 479 ] 93 | Next state: 91 [ count |-> 93, p |-> 487 ] 94 | Next state: 92 [ count |-> 94, p |-> 491 ] 95 | Next state: 93 [ count |-> 95, p |-> 499 ] 96 | Next state: 94 [ count |-> 96, p |-> 503 ] 97 | Next state: 95 [ count |-> 97, p |-> 509 ] 98 | Next state: 96 [ count |-> 98, p |-> 521 ] 99 | Next state: 97 [ count |-> 99, p |-> 523 ] 100 | Next state: 98 [ count |-> 100, p |-> 541 ] 101 | Next state: 99 [ count |-> 101, p |-> 547 ] 102 | MAIN DONE 103 | -------------------------------------------------------------------------------- /modules/other/Bosco.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE Bosco ----------------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | CONSTANTS Processes, Quorums, Data 5 | ASSUME \A q \in Quorums: q \subseteq Processes 6 | ASSUME \A q1, q2, q3 \in Quorums: q1 \intersect q2 \intersect q3 /= {} 7 | VARIABLE procs \* map of processes to (round, estimate) pairs 8 | VARIABLE msgs \* map of processes to received messages 9 | VARIABLE mi \* messaging interface 10 | 11 | \* Type of vote 12 | Vote == [ round: Nat, estimate: Data ] 13 | 14 | \* Type of message 15 | Message == [ src: Processes, vote: Vote ] 16 | 17 | Network == INSTANCE Messaging 18 | Stdin == INSTANCE Input 19 | 20 | INFINITY == "INFINITY" 21 | 22 | \* Extend the Less Than relation to deal with INFINITY 23 | LT(x, y) == 24 | \/ x /= INFINITY /\ y = INFINITY 25 | \/ x /= INFINITY /\ y /= INFINITY /\ x < y 26 | 27 | \* Initialize the variables 28 | Init == 29 | /\ procs = [ p \in Processes |-> [ round |-> 0 ] ] 30 | /\ msgs = [ p \in Processes |-> {} ] 31 | /\ Network!Init 32 | /\ Print("Enter a proposal: ", TRUE) 33 | 34 | \* Broadcast a message including the new state of p 35 | Send(p) == 36 | /\ Network!Send( 37 | {< p, vote |-> procs'[p] ]>> : q \in Processes }) 38 | /\ UNCHANGED <> 39 | 40 | \* From round 0, just go to round 1 and send a message 41 | Start(p, e) == 42 | /\ procs[p].round = 0 43 | /\ procs' = [ procs EXCEPT ![p] = [ round |-> 1, estimate |-> e ] ] 44 | /\ Send(p) 45 | 46 | \* Decide if there is a unanimous quorum 47 | Decide(p, q, e) == 48 | \* If process p isn't already decided 49 | /\ procs[p].round /= INFINITY 50 | 51 | \* And all processes in q have voted e in this round 52 | /\ \A p2 \in q: [ src |-> p2, vote |-> 53 | [ round |-> procs[p].round, estimate |-> e ] ] \in msgs[p] 54 | 55 | \* Then decide e 56 | /\ procs' = [ procs EXCEPT ![p] = [ round |-> INFINITY, estimate |-> e ] ] 57 | /\ Send(p) 58 | 59 | \* Proceed to the next round if there is a unanimous intersection of quorums 60 | Maybe(p, q, e) == 61 | \* If process p isn't already decided 62 | /\ procs[p].round /= INFINITY 63 | 64 | \* And all processes in q have voted in this round 65 | /\ \A p2 \in q: \E e2 \in Data: [ src |-> p2, vote |-> 66 | [ round |-> procs[p].round, estimate |-> e2 ] ] \in msgs[p] 67 | 68 | \* And there exists a quorum q2 such that all processes in q*q2 have 69 | \* voted for e in this round 70 | /\ \E q2 \in Quorums: \A p2 \in q \intersect q2: [ src |-> p2, vote |-> 71 | [ round |-> procs[p].round, estimate |-> e ] ] \in msgs[p] 72 | 73 | \* But the quorum is not unanimous 74 | /\ \E p2 \in q, e2 \in Data: e2 /= e /\ [ src |-> p2, vote |-> 75 | [ round |-> procs[p].round, estimate |-> e2 ] ] \in msgs[p] 76 | 77 | \* Then proceed to the next round with e 78 | /\ procs' = [ procs EXCEPT ![p] = [ round |-> @.round + 1, estimate |-> e ] ] 79 | /\ Send(p) 80 | 81 | Undecide(p, q, e) == 82 | \* If process p isn't already decided 83 | /\ procs[p].round /= INFINITY 84 | 85 | \* And all processes in q have voted in this round 86 | /\ \A p2 \in q: \E e2 \in Data: [ src |-> p2, vote |-> 87 | [ round |-> procs[p].round, estimate |-> e2 ] ] \in msgs[p] 88 | 89 | \* And some process in q voted for e in this round 90 | /\ \E p2 \in q: [ src |-> p2, vote |-> 91 | [ round |-> procs[p].round, estimate |-> e ] ] \in msgs[p] 92 | 93 | \* And there does not exists a quorum q2 and a value e2 such that all 94 | \* processes in q*q2 have voted for e2 in this round 95 | /\ \lnot \E q2 \in Quorums, e2 \in Data: \A p2 \in q \intersect q2: 96 | [ src |-> p2, vote |-> 97 | [ round |-> procs[p].round, estimate |-> e2 ] ] \in msgs[p] 98 | 99 | \* Then proceed to the next round with e 100 | /\ procs' = [ procs EXCEPT ![p] = [ round |-> @.round + 1, estimate |-> e ] ] 101 | /\ Send(p) 102 | 103 | \* Get rid of messages no longer needed (for better output and scalability) 104 | Cleanup(p, m) == 105 | /\ LT(m.vote.round, procs[p].round) 106 | /\ msgs' = [ msgs EXCEPT ![p] = @ \ {m} ] 107 | /\ UNCHANGED << procs, mi >> 108 | 109 | Deliver(p, m) == 110 | /\ msgs' = [ msgs EXCEPT ![p] = @ \union { m } ] 111 | /\ UNCHANGED << procs >> 112 | 113 | Proc(p) == 114 | \/ Network!Receive(p, Deliver) 115 | \/ Stdin!Receive(p, Start) 116 | \/ \E q \in Quorums, e \in Data: 117 | \/ Decide(p, q, e) 118 | \/ Maybe(p, q, e) 119 | \/ Undecide(p, q, e) 120 | \/ \E m \in msgs[p]: 121 | \/ Cleanup(p, m) 122 | 123 | Next == \E p \in Processes: Proc(p) 124 | 125 | Spec == Init /\ [][Next]_<> 126 | 127 | ============================================================================= 128 | -------------------------------------------------------------------------------- /modules/other/BlockingQueue.tla: -------------------------------------------------------------------------------- 1 | --------------------------- MODULE BlockingQueue --------------------------- 2 | EXTENDS Naturals, Sequences, FiniteSets 3 | 4 | CONSTANTS Producers, (* the (nonempty) set of producers *) 5 | Consumers, (* the (nonempty) set of consumers *) 6 | BufCapacity (* the maximum number of messages in the bounded buffer *) 7 | 8 | ASSUME Assumption == 9 | /\ Producers # {} (* at least one producer *) 10 | /\ Consumers # {} (* at least one consumer *) 11 | /\ Producers \intersect Consumers = {} (* no thread is both consumer and producer *) 12 | /\ BufCapacity \in (Nat \ {0}) (* buffer capacity is at least 1 *) 13 | 14 | ----------------------------------------------------------------------------- 15 | 16 | VARIABLES buffer, waitSet 17 | vars == <> 18 | 19 | RunningThreads == (Producers \cup Consumers) \ waitSet 20 | 21 | NotifyOther(t) == 22 | LET S == IF t \in Producers THEN waitSet \ Producers ELSE waitSet \ Consumers 23 | IN IF S # {} 24 | THEN \E x \in S : waitSet' = waitSet \ {x} 25 | ELSE UNCHANGED waitSet 26 | 27 | (* @see java.lang.Object#wait *) 28 | Wait(t) == /\ waitSet' = waitSet \cup {t} 29 | /\ UNCHANGED <> 30 | 31 | ----------------------------------------------------------------------------- 32 | 33 | Put(t, d) == 34 | /\ t \notin waitSet 35 | /\ \/ /\ Len(buffer) < BufCapacity 36 | /\ buffer' = Append(buffer, d) 37 | /\ NotifyOther(t) 38 | \/ /\ Len(buffer) = BufCapacity 39 | /\ Wait(t) 40 | 41 | Get(t) == 42 | /\ t \notin waitSet 43 | /\ \/ /\ buffer # <<>> 44 | /\ buffer' = Tail(buffer) 45 | /\ NotifyOther(t) 46 | \/ /\ buffer = <<>> 47 | /\ Wait(t) 48 | 49 | ----------------------------------------------------------------------------- 50 | 51 | (* Initially, the buffer is empty and no thread is waiting. *) 52 | Init == /\ buffer = <<>> 53 | /\ waitSet = {} 54 | 55 | (* Then, pick a thread out of all running threads and have it do its thing. *) 56 | Next == \/ \E p \in Producers: Put(p, p) \* Add some data to buffer 57 | \/ \E c \in Consumers: Get(c) 58 | 59 | ----------------------------------------------------------------------------- 60 | 61 | (* TLA+ is untyped, thus lets verify the range of some values in each state. *) 62 | TypeInv == /\ buffer \in Seq(Producers) 63 | /\ Len(buffer) \in 0..BufCapacity 64 | /\ waitSet \in SUBSET (Producers \cup Consumers) 65 | 66 | (* No Deadlock *) 67 | Invariant == waitSet # (Producers \cup Consumers) 68 | 69 | ----------------------------------------------------------------------------- 70 | 71 | MySeq(P) == UNION {[1..n -> P] : n \in 0..BufCapacity} 72 | 73 | (*RVR: no support for TLAPS YET 74 | 75 | INSTANCE TLAPS 76 | 77 | Spec == Init /\ [][Next]_vars 78 | 79 | (* Whitelist all the known facts and definitions (except IInv below) *) 80 | USE Assumption DEF vars, RunningThreads, 81 | Init, Next, Spec, 82 | Put, Get, 83 | Wait, NotifyOther, 84 | TypeInv, Invariant 85 | 86 | \* TypeInv will be a conjunct of the inductive invariant, so prove it inductive. 87 | \* An invariant I is inductive, iff Init => I and I /\ [Next]_vars => I. Note 88 | \* though, that TypeInv itself won't imply Invariant though! TypeInv alone 89 | \* does not help us prove Invariant. 90 | \* Luckily, TLAPS does not require us to decompose the proof into substeps. 91 | LEMMA TypeCorrect == Spec => []TypeInv 92 | <1>1. Init => TypeInv BY SMT 93 | <1>2. TypeInv /\ [Next]_vars => TypeInv' BY SMT 94 | <1>. QED BY <1>1, <1>2, PTL 95 | 96 | \* The naive thing to do is to check if the conjunct of TypeInv /\ Invariant 97 | \* is inductive. 98 | IInv == /\ TypeInv!2 99 | /\ TypeInv!3 100 | /\ Invariant 101 | \* When the buffer is empty, a consumer will be added to the waitSet. 102 | \* However, this does not crate a deadlock, because at least one producer 103 | \* will not be in the waitSet. 104 | /\ buffer = <<>> => \E p \in Producers : p \notin waitSet 105 | \* Vice versa, when buffer is full, a producer will be added to waitSet, 106 | \* but at least one consumer won't be in waitSet. 107 | /\ Len(buffer) = BufCapacity => \E c \in Consumers : c \notin waitSet 108 | 109 | THEOREM DeadlockFreedom == Spec => []Invariant 110 | <1>1. Init => IInv BY SMT DEF IInv 111 | <1>2. IInv /\ [Next]_vars => IInv' BY DEF IInv 112 | <1>3. IInv => Invariant BY DEF IInv 113 | <1>4. QED BY <1>1,<1>2,<1>3,PTL 114 | 115 | MCIInv == TypeInv!1 /\ IInv 116 | 117 | ----------------------------------------------------------------------------- 118 | 119 | PutEnabled == \A p \in Producers : ENABLED Put(p, p) 120 | 121 | FairSpec == Spec /\ WF_vars(Next) 122 | /\ \A p \in Producers : WF_vars(Put(p, p)) 123 | 124 | (* All producers will continuously be serviced. For this to be violated, *) 125 | (* ASSUME Cardinality(Producers) > 1 has to hold (a single producer cannot *) 126 | (* starve itself). *) 127 | Starvation == \A p \in Producers: []<>(<>_vars) 128 | 129 | RVR*) 130 | 131 | ============================================================================= 132 | -------------------------------------------------------------------------------- /modules/other/NBosco.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE NBosco ----------------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | CONSTANTS Processes, Quorums, Data 5 | ASSUME \A q \in Quorums: q \subseteq Processes 6 | ASSUME \A q1, q2, q3 \in Quorums: q1 \intersect q2 \intersect q3 /= {} 7 | VARIABLE procs \* map of processes to (round, estimate) pairs 8 | VARIABLE inboxes \* map of processes to received messages 9 | VARIABLE outboxes \* map of processes to sent messages 10 | VARIABLE Proposals \* interface variable containing proposals 11 | 12 | \* Type of vote 13 | Vote == [ round: Nat, estimate: Data ] 14 | 15 | \* Type of message 16 | Message == [ src: Processes, vote: Vote ] 17 | 18 | INFINITY == "INFINITY" 19 | 20 | \* Extend the Less Than relation to deal with INFINITY 21 | LT(x, y) == 22 | \/ x /= INFINITY /\ y = INFINITY 23 | \/ x /= INFINITY /\ y /= INFINITY /\ x < y 24 | 25 | \* Initialize the variables 26 | Init == 27 | /\ procs = [ p \in Processes |-> [ round |-> 0 ] ] 28 | \* /\ PrintT("INIT" \o ToString(procs)) 29 | /\ inboxes = [ p \in Processes |-> {} ] 30 | /\ outboxes = [ p \in Processes |-> {} ] 31 | /\ Proposals = {} 32 | 33 | \* Broadcast a message including the new state of p 34 | Send(p) == 35 | /\ outboxes' = [ outboxes EXCEPT ![p] = @ \cup 36 | {< p, vote |-> procs'[p] ]>> : q \in Processes } ] 37 | /\ UNCHANGED <> 38 | 39 | \* From round 0, just go to round 1 and send a message 40 | Start(p, e) == 41 | /\ procs[p].round = 0 42 | \* /\ PrintT("GOT PROPOSAL") 43 | /\ procs' = [ procs EXCEPT ![p] = [ round |-> 1, estimate |-> e ] ] 44 | /\ Send(p) 45 | 46 | \* Decide if there is a unanimous quorum 47 | Decide(p, q, e) == 48 | \* If process p isn't already decided 49 | /\ procs[p].round /= INFINITY 50 | 51 | \* And all processes in q have voted e in this round 52 | /\ \A p2 \in q: [ src |-> p2, vote |-> 53 | [ round |-> procs[p].round, estimate |-> e ] ] \in inboxes[p] 54 | 55 | \* Then decide e 56 | /\ procs' = [ procs EXCEPT ![p] = [ round |-> INFINITY, estimate |-> e ] ] 57 | /\ Send(p) 58 | 59 | \* Proceed to the next round if there is a unanimous intersection of quorums 60 | Maybe(p, q, e) == 61 | \* If process p isn't already decided 62 | /\ procs[p].round /= INFINITY 63 | 64 | \* And all processes in q have voted in this round 65 | /\ \A p2 \in q: \E e2 \in Proposals: [ src |-> p2, vote |-> 66 | [ round |-> procs[p].round, estimate |-> e2 ] ] \in inboxes[p] 67 | 68 | \* And there exists a quorum q2 such that all processes in q*q2 have 69 | \* voted for e in this round 70 | /\ \E q2 \in Quorums: \A p2 \in q \intersect q2: [ src |-> p2, vote |-> 71 | [ round |-> procs[p].round, estimate |-> e ] ] \in inboxes[p] 72 | 73 | \* But the quorum is not unanimous 74 | /\ \E p2 \in q, e2 \in Proposals: e2 /= e /\ [ src |-> p2, vote |-> 75 | [ round |-> procs[p].round, estimate |-> e2 ] ] \in inboxes[p] 76 | 77 | \* Then proceed to the next round with e 78 | /\ procs' = [ procs EXCEPT ![p] = [ round |-> @.round + 1, estimate |-> e ] ] 79 | /\ Send(p) 80 | 81 | Undecide(p, q, e) == 82 | \* If process p isn't already decided 83 | /\ procs[p].round /= INFINITY 84 | 85 | \* And all processes in q have voted in this round 86 | /\ \A p2 \in q: \E e2 \in Proposals: [ src |-> p2, vote |-> 87 | [ round |-> procs[p].round, estimate |-> e2 ] ] \in inboxes[p] 88 | 89 | \* And some process in q voted for e in this round 90 | /\ \E p2 \in q: [ src |-> p2, vote |-> 91 | [ round |-> procs[p].round, estimate |-> e ] ] \in inboxes[p] 92 | 93 | \* And there does not exists a quorum q2 and a value e2 such that all 94 | \* processes in q*q2 have voted for e2 in this round 95 | /\ \lnot \E q2 \in Quorums, e2 \in Proposals: \A p2 \in q \intersect q2: 96 | [ src |-> p2, vote |-> 97 | [ round |-> procs[p].round, estimate |-> e2 ] ] \in inboxes[p] 98 | 99 | \* Then proceed to the next round with e 100 | /\ procs' = [ procs EXCEPT ![p] = [ round |-> @.round + 1, estimate |-> e ] ] 101 | /\ Send(p) 102 | 103 | Catchup(p, m) == 104 | /\ LT(procs[p].round, m.vote.round) 105 | /\ procs' = [ procs EXCEPT ![p] = m.vote ] 106 | /\ Send(p) 107 | 108 | \* Get rid of messages no longer needed (for better output and scalability) 109 | Cleanup(p, m) == 110 | /\ LT(m.vote.round, procs[p].round) 111 | /\ inboxes' = [ inboxes EXCEPT ![p] = @ \ {m} ] 112 | /\ UNCHANGED << procs, outboxes, Proposals >> 113 | 114 | Deliver(p, m) == 115 | \* /\ PrintT("DELIVER " \o String(p) \o " " \o String(m)) 116 | /\ inboxes' = [ inboxes EXCEPT ![p] = @ \union { m } ] 117 | /\ outboxes' = [ outboxes EXCEPT ![p] = @ \ { m } ] 118 | /\ UNCHANGED << procs, Proposals >> 119 | 120 | Network(p) == 121 | /\ \E dm \in outboxes[p]: Deliver(dm[1], dm[2]) 122 | 123 | Proc(p) == 124 | \/ \E e \in Proposals: Start(p, e) 125 | \/ \E q \in Quorums, e \in Proposals: 126 | \/ Decide(p, q, e) 127 | \/ Maybe(p, q, e) 128 | \/ Undecide(p, q, e) 129 | \/ \E m \in inboxes[p]: 130 | \/ Catchup(p, m) 131 | \/ Cleanup(p, m) 132 | 133 | Next == \E p \in Processes: Proc(p) \/ Network(p) 134 | 135 | Spec == Init /\ [][Next]_<> 136 | 137 | ============================================================================= 138 | -------------------------------------------------------------------------------- /tests/regression/test4.exp: -------------------------------------------------------------------------------- 1 | Initial context: [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ] ] 2 | Next state: 0 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ] ] 3 | Next state: 1 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ] ] 4 | Next state: 2 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 5 | Next state: 3 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 6 | Next state: 4 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 7 | Next state: 5 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 8 | Next state: 6 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ] ] 9 | Next state: 7 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ] ] 10 | Next state: 8 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 11 | Next state: 9 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 12 | Next state: 10 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 13 | Next state: 11 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 14 | Next state: 12 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ] ] 15 | Next state: 13 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ] ] 16 | Next state: 14 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 17 | Next state: 15 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 18 | Next state: 16 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 19 | Next state: 17 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 20 | Next state: 18 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ] ] 21 | Next state: 19 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ] ] 22 | Next state: 20 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ] ] 23 | Next state: 21 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ] ] 24 | Next state: 22 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 25 | Next state: 23 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 26 | Next state: 24 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ] ] 27 | Next state: 25 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ] ] 28 | Next state: 26 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 29 | Next state: 27 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 30 | Next state: 28 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 31 | Next state: 29 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 32 | Next state: 30 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ] ] 33 | Next state: 31 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ] ] 34 | Next state: 32 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ] ] 35 | Next state: 33 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ] ] 36 | Next state: 34 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 37 | Next state: 35 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 38 | Next state: 36 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ] ] 39 | Next state: 37 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ] ] 40 | Next state: 38 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 41 | Next state: 39 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 42 | Next state: 40 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 43 | Next state: 41 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 44 | Next state: 42 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ] ] 45 | Next state: 43 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ] ] 46 | Next state: 44 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 47 | Next state: 45 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 48 | Next state: 46 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 49 | Next state: 47 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 50 | Next state: 48 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ] ] 51 | Next state: 49 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ] ] 52 | Next state: 50 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 53 | Next state: 51 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 54 | Next state: 52 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 55 | Next state: 53 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 56 | Next state: 54 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ] ] 57 | Next state: 55 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ] ] 58 | Next state: 56 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 59 | Next state: 57 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 60 | Next state: 58 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ] ] 61 | Next state: 59 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ] ] 62 | Next state: 60 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 63 | Next state: 61 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 64 | Next state: 62 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 65 | Next state: 63 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 66 | Next state: 64 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ] ] 67 | Next state: 65 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ] ] 68 | Next state: 66 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 69 | Next state: 67 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 70 | Next state: 68 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 71 | Next state: 69 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 72 | Next state: 70 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 73 | Next state: 71 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 74 | Next state: 72 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 75 | Next state: 73 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 76 | Next state: 74 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ] ] 77 | Next state: 75 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ] ] 78 | Next state: 76 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ] ] 79 | Next state: 77 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ] ] 80 | Next state: 78 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 81 | Next state: 79 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 82 | Next state: 80 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 83 | Next state: 81 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 84 | Next state: 82 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 85 | Next state: 83 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 86 | Next state: 84 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 87 | Next state: 85 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 88 | Next state: 86 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ] ] 89 | Next state: 87 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ] ] 90 | Next state: 88 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 91 | Next state: 89 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 92 | Next state: 90 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ] ] 93 | Next state: 91 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ] ] 94 | Next state: 92 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ] ] 95 | Next state: 93 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ] ] 96 | Next state: 94 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ] ] 97 | Next state: 95 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ] ] 98 | Next state: 96 [ chan |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ] ] 99 | Next state: 97 [ chan |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ] ] 100 | Next state: 98 [ chan |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ] ] 101 | Next state: 99 [ chan |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ] ] 102 | MAIN DONE 103 | -------------------------------------------------------------------------------- /modules/other/Exprs.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE Exprs ----------------------------- 2 | EXTENDS Integers, Sequences, FiniteSets, Bags, TLC 3 | 4 | fact[n \in Nat] == IF n = 0 THEN 1 ELSE n * fact[n - 1] 5 | fact2[n \in 0..4] == IF n = 0 THEN 1 ELSE n * fact2[n - 1] 6 | 7 | Tests == 8 | << 9 | << FALSE /\ FALSE, FALSE >>, 10 | << FALSE /\ TRUE, FALSE >>, 11 | << TRUE /\ FALSE, FALSE >>, 12 | << TRUE /\ TRUE, TRUE >>, 13 | 14 | << FALSE \/ FALSE, FALSE >>, 15 | << FALSE \/ TRUE, TRUE >>, 16 | << TRUE \/ FALSE, TRUE >>, 17 | << TRUE \/ TRUE, TRUE >>, 18 | 19 | << FALSE => FALSE, TRUE >>, 20 | << FALSE => TRUE, TRUE >>, 21 | << TRUE => FALSE, FALSE >>, 22 | << TRUE => TRUE, TRUE >>, 23 | 24 | << FALSE <=> FALSE, TRUE >>, 25 | << FALSE <=> TRUE, FALSE >>, 26 | << TRUE <=> FALSE, FALSE >>, 27 | << TRUE <=> TRUE, TRUE >>, 28 | 29 | << FALSE \equiv FALSE, TRUE >>, 30 | << FALSE \equiv TRUE, FALSE >>, 31 | << TRUE \equiv FALSE, FALSE >>, 32 | << TRUE \equiv TRUE, TRUE >>, 33 | 34 | << ~TRUE, FALSE >>, 35 | << ~FALSE, TRUE >>, 36 | << \lnot TRUE, FALSE >>, 37 | << \lnot FALSE, TRUE >>, 38 | << \neg TRUE, FALSE >>, 39 | << \neg FALSE, TRUE >>, 40 | << ~TRUE \/ TRUE, TRUE >>, 41 | << ~(TRUE \/ TRUE), FALSE >>, 42 | 43 | << 1 \in 1..2, TRUE >>, 44 | << 1 \in 2..2, FALSE >>, 45 | << 1 \notin 1..2, FALSE >>, 46 | << 1 \notin 2..2, TRUE >>, 47 | 48 | << 1 = 1, TRUE >>, 49 | << 1 = 2, FALSE >>, 50 | << 1 /= 1, FALSE >>, 51 | << 1 /= 2, TRUE >>, 52 | << 1 # 1, FALSE >>, 53 | << 1 # 2, TRUE >>, 54 | 55 | << SUBSET {}, {{}} >>, 56 | << SUBSET {1}, {{}, {1}} >>, 57 | << SUBSET {1, 2}, {{}, {1}, {2}, {1, 2}} >>, 58 | 59 | << UNION {}, {} >>, 60 | << UNION {{}}, {} >>, 61 | << UNION {{1}}, {1} >>, 62 | << UNION {{1},{2}}, {1, 2} >>, 63 | 64 | << { 1 } \subset { }, FALSE >>, 65 | << { 1 } \subset { 1 }, FALSE >>, 66 | << { 1 } \subset { 2 }, FALSE >>, 67 | << { 1 } \subset { 1, 2 }, TRUE >>, 68 | << { 1 } \subseteq { }, FALSE >>, 69 | << { 1 } \subseteq { 1 }, TRUE >>, 70 | << { 1 } \subseteq { 2 }, FALSE >>, 71 | << { 1 } \subseteq { 1, 2 }, TRUE >>, 72 | 73 | << { } \supset { 1 }, FALSE >>, 74 | << { 1 } \supset { 1 }, FALSE >>, 75 | << { 2 } \supset { 1 }, FALSE >>, 76 | << { 1, 2 } \supset { 1 }, TRUE >>, 77 | << { } \supseteq { 1 }, FALSE >>, 78 | << { 1 } \supseteq { 1 }, TRUE >>, 79 | << { 2 } \supseteq { 1 }, FALSE >>, 80 | << { 1, 2 } \supseteq { 1 }, TRUE >>, 81 | 82 | << { 1, 2 } \union { 2, 3 }, { 1, 2, 3} >>, 83 | << { 1, 2 } \cup { 2, 3 }, { 1, 2, 3} >>, 84 | << { 1, 2 } \intersect { 2, 3 }, { 2 } >>, 85 | << { 1, 2 } \cap { 2, 3 }, { 2 } >>, 86 | << { 1, 2 } \ { 2, 3 }, { 1 } >>, 87 | 88 | << 1 + 2, 3 >>, 89 | << -. 3, -3 >>, 90 | << - (1 + 2), -3 >>, 91 | << - (1 + 2) + 4, 1 >>, 92 | << 1 + 2 * 3, 7 >>, 93 | << 1 * 2 + 3, 5 >>, 94 | << 1..2, { 1, 2 } >>, 95 | << 1..-2, {} >>, 96 | << 8 \div 4, 2 >>, 97 | << 5 % 4, 1 >>, 98 | << 2^3, 8 >>, 99 | 100 | << 1 < 1, FALSE >>, 101 | << 1 < 2, TRUE >>, 102 | << 1 <= 0, FALSE >>, 103 | << 1 <= 1, TRUE >>, 104 | << 1 =< 0, FALSE >>, 105 | << 1 =< 1, TRUE >>, 106 | << 1 \leq 0, FALSE >>, 107 | << 1 \leq 1, TRUE >>, 108 | << 1 > 1, FALSE >>, 109 | << 1 > 0, TRUE >>, 110 | << 1 >= 1, TRUE >>, 111 | << 1 >= 2, FALSE >>, 112 | << 1 \geq 1, TRUE >>, 113 | << 1 \geq 2, FALSE >>, 114 | 115 | << (1..2) \X (3..4), { << 1, 3 >>, << 1, 4 >>, 116 | << 2, 3 >>, << 2, 4 >> } >>, 117 | << (1..2) \times (3..4), { << 1, 3 >>, << 1, 4 >>, 118 | << 2, 3 >>, << 2, 4 >> } >>, 119 | << (1..2) \X (3..4) \X (5..6), { << 1, 3, 5 >>, << 1, 3, 6 >>, 120 | << 1, 4, 5 >>, << 1, 4, 6 >>, << 2, 3, 5 >>, 121 | << 2, 3, 6 >>, << 2, 4, 5 >>, << 2, 4, 6 >> } >>, 122 | 123 | << << 2 >>[1], 2 >>, 124 | << << "a", "b", "c" >>[2], "b" >>, 125 | << Len(<< 1, 1, 1 >>), 3 >>, 126 | << Head(<< 1, 2, 3 >>), 1 >>, 127 | << Tail(<< 1, 2, 3 >>), << 2, 3 >> >>, 128 | << Append(<< 1, 2 >>, 3), << 1, 2, 3 >> >>, 129 | << << 1 >> \o << 2, 3 >>, << 1, 2, 3 >> >>, 130 | << SubSeq(<< 1, 2, 3 >>, 1, 2), << 1, 2 >> >>, 131 | << SelectSeq(<< FALSE, TRUE >>, ~), << FALSE >> >>, 132 | << SortSeq(<< >>, <), << >> >>, 133 | << SortSeq(<< 3, 1, 2 >>, <), << 1, 2, 3 >> >>, 134 | << SortSeq(<< 3, 1, 2 >>, >), << 3, 2, 1 >> >>, 135 | 136 | << "", <<>> >>, 137 | << DOMAIN "", {} >>, 138 | << DOMAIN "abc", 1..3 >>, 139 | << "a", << "a"[1] >> >>, 140 | << "a" \o "b", "ab" >>, 141 | << [ "ab" EXCEPT ![1] = "b"[1] ], "bb" >>, 142 | << [ "ab" EXCEPT ![1] = 1 ], << 1, "b"[1] >> >>, 143 | << SubSeq("Hello", 2, 4), "ell" >>, 144 | << Len("hello"), 5 >>, 145 | 146 | << { 1, 1, 1 }, { 1 } >>, 147 | << Cardinality({}), 0 >>, 148 | << Cardinality({ "a", "b", "c" }), 3 >>, 149 | 150 | << { x \in 1..5: x % 2 = 0 }, { 2, 4 } >>, 151 | << { 2*x: x \in 1..3 }, { 2, 4, 6 } >>, 152 | << [ a: 1..2, b:3..4 ], { [ a |-> 1, b |-> 3 ], 153 | [ a |-> 1, b |-> 4 ], [ a |-> 2, b |-> 3 ], 154 | [ a |-> 2, b |-> 4 ] } >>, 155 | << [ x \in 1..2 |-> 3 ], << 3, 3 >> >>, 156 | << [ x \in { "a", "b" } |-> 3 ], [ a |-> 3, b |-> 3 ] >>, 157 | 158 | << \E x \in 1..5: x <= 1, TRUE >>, 159 | << \E x \in 1..5: x <= 0, FALSE >>, 160 | << \A x \in 1..5: x <= 5, TRUE >>, 161 | << \A x \in 1..5: x <= 4, FALSE >>, 162 | 163 | << IF FALSE THEN 1 ELSE 2, 2 >>, 164 | << IF TRUE THEN 1 ELSE 2, 1 >>, 165 | << CASE FALSE -> 1 [] TRUE -> 2, 2 >>, 166 | << CASE TRUE -> 1 [] FALSE -> 2, 1 >>, 167 | << CASE FALSE -> 1 [] OTHER -> 2, 2 >>, 168 | << CASE TRUE -> 1 [] OTHER -> 2, 1 >>, 169 | 170 | << LET x == 3 IN 2*x, 6 >>, 171 | << LET d(x) == 2*x IN d(3), 6 >>, 172 | << CHOOSE x: x = 3, 3 >>, 173 | << CHOOSE x: x \in { 3 }, 3 >>, 174 | << CHOOSE x \in 1..5: x = 3, 3 >>, 175 | << CHOOSE x \in 1..5: x > 2 /\ x < 4, 3 >>, 176 | 177 | << SetToBag(1..3), << 1, 1, 1 >> >>, 178 | << SetToBag(1..3) (+) SetToBag(2..4), << 1, 2, 2, 1 >> >>, 179 | << BagToSet(SetToBag(1..3) (+) SetToBag(2..4)), 1..4 >>, 180 | << BagIn(2, SetToBag(1..3)), TRUE >>, 181 | << BagIn(0, SetToBag(1..3)), FALSE >>, 182 | << EmptyBag, <<>> >>, 183 | << CopiesIn(1, SetToBag(1..3) (+) SetToBag(2..4)), 1 >>, 184 | << CopiesIn(3, SetToBag(1..3) (+) SetToBag(2..4)), 2 >>, 185 | << CopiesIn(5, SetToBag(1..3) (+) SetToBag(2..4)), 0 >>, 186 | 187 | << fact[0], 1 >>, 188 | << fact[4], 24 >>, 189 | << fact2[0], 1 >>, 190 | << fact2[4], 24 >>, 191 | << fact2, [ i \in 0..4 |-> fact[i] ] >>, 192 | << CHOOSE f: f = [ n \in 0..4 |-> 193 | IF n = 0 THEN 1 ELSE n * f[n-1] ], fact2 >>, 194 | 195 | << 0, 0 >> 196 | >> 197 | 198 | Incorrect(test) == test[1] /= test[2] 199 | 200 | \* TODO. Come up with expression that says which tests failed 201 | Failed == SelectSeq(Tests, Incorrect) 202 | 203 | Init == PrintT(ToString(Failed)) /\ (Failed = <<>>) 204 | Next == TRUE 205 | 206 | Spec == Init /\ [][Next]_<<>> 207 | ======================================================================= 208 | -------------------------------------------------------------------------------- /modules/lib/Bags.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE Bags -------------------------------- 2 | (**************************************************************************) 3 | (* A bag, also called a multiset, is a set that can contain multiple *) 4 | (* copies of the same element. A bag can have infinitely many elements, *) 5 | (* but only finitely many copies of any single element. *) 6 | (* *) 7 | (* We represent a bag in the usual way as a function whose range is a *) 8 | (* subset of the positive integers. An element e belongs to bag B iff e *) 9 | (* is in the domain of B, in which case bag B contains B[e] copies of e. *) 10 | (**************************************************************************) 11 | EXTENDS TLC 12 | LOCAL INSTANCE Naturals 13 | 14 | IsABag(B) == 15 | (************************************************************************) 16 | (* True iff B is a bag. *) 17 | (************************************************************************) 18 | B \in [DOMAIN B -> {n \in Nat : n > 0}] 19 | 20 | BagToSet(B) == DOMAIN B 21 | (************************************************************************) 22 | (* The set of elements at least one copy of which is in B. *) 23 | (************************************************************************) 24 | 25 | SetToBag(S) == [e \in S |-> 1] 26 | (************************************************************************) 27 | (* The bag that contains one copy of every element of the set S. *) 28 | (************************************************************************) 29 | 30 | BagIn(e,B) == e \in BagToSet(B) 31 | (************************************************************************) 32 | (* The \in operator for bags. *) 33 | (************************************************************************) 34 | 35 | EmptyBag == SetToBag({}) 36 | 37 | B1 (+) B2 == 38 | (************************************************************************) 39 | (* The union of bags B1 and B2. *) 40 | (************************************************************************) 41 | [e \in (DOMAIN B1) \cup (DOMAIN B2) |-> 42 | (IF e \in DOMAIN B1 THEN B1[e] ELSE 0) 43 | + (IF e \in DOMAIN B2 THEN B2[e] ELSE 0) ] 44 | 45 | B1 (-) B2 == 46 | (************************************************************************) 47 | (* The bag B1 with the elements of B2 removed--that is, with one copy *) 48 | (* of an element removed from B1 for each copy of the same element in *) 49 | (* B2. If B2 has at least as many copies of e as B1, then B1 (-) B2 *) 50 | (* has no copies of e. *) 51 | (************************************************************************) 52 | LET B == [e \in DOMAIN B1 |-> IF e \in DOMAIN B2 THEN B1[e] - B2[e] 53 | ELSE B1[e]] 54 | IN [e \in {d \in DOMAIN B : B[d] > 0} |-> B[e]] 55 | 56 | LOCAL Sum(f) == 57 | (******************************************************************) 58 | (* The sum of f[x] for all x in DOMAIN f. The definition assumes *) 59 | (* that f is a Nat-valued function and that f[x] equals 0 for all *) 60 | (* but a finite number of elements x in DOMAIN f. *) 61 | (******************************************************************) 62 | LET DSum[S \in SUBSET DOMAIN f] == 63 | LET elt == CHOOSE e \in S : TRUE 64 | IN IF S = {} THEN 0 65 | ELSE f[elt] + DSum[S \ {elt}] 66 | IN DSum[DOMAIN f] 67 | 68 | BagUnion(S) == 69 | (************************************************************************) 70 | (* The bag union of all elements of the set S of bags. *) 71 | (************************************************************************) 72 | [e \in UNION {BagToSet(B) : B \in S} |-> 73 | Sum( [B \in S |-> IF BagIn(e, B) THEN B[e] ELSE 0] ) ] 74 | 75 | B1 \sqsubseteq B2 == 76 | (************************************************************************) 77 | (* The subset operator for bags. B1 \sqsubseteq B2 iff, for all e, bag *) 78 | (* B2 has at least as many copies of e as bag B1 does. *) 79 | (************************************************************************) 80 | /\ (DOMAIN B1) \subseteq (DOMAIN B2) 81 | /\ \A e \in DOMAIN B1 : B1[e] \leq B2[e] 82 | 83 | SubBag(B) == 84 | (************************************************************************) 85 | (* The set of all subbags of bag B. *) 86 | (* *) 87 | (* The following definition is not the one described in the TLA+ book, *) 88 | (* but rather one that TLC can evaluate. *) 89 | (************************************************************************) 90 | 91 | LET RemoveFromDom(x, f) == [y \in (DOMAIN f) \ {x} |-> f[y]] 92 | Combine(x, BagSet) == 93 | BagSet \cup 94 | {[y \in (DOMAIN f) \cup {x} |-> IF y = x THEN i ELSE f[y]] : 95 | f \in BagSet, i \in 1..B[x]} 96 | Biggest == LET Range == {B[x] : x \in DOMAIN B} 97 | IN IF Range = {} THEN 0 98 | ELSE CHOOSE r \in Range : 99 | \A s \in Range : r \geq s 100 | RSB[BB \in UNION {[S -> 1..Biggest] : S \in SUBSET DOMAIN B}] == 101 | IF BB = << >> THEN {<< >>} 102 | ELSE LET x == CHOOSE x \in DOMAIN BB : TRUE 103 | IN Combine(x, RSB[RemoveFromDom(x, BB)]) 104 | IN RSB[B] 105 | 106 | (******************* Here is the definition from the TLA+ book. ******** 107 | LET AllBagsOfSubset == 108 | (******************************************************************) 109 | (* The set of all bags SB such that BagToSet(SB) \subseteq *) 110 | (* BagToSet(B). *) 111 | (******************************************************************) 112 | UNION {[SB -> {n \in Nat : n > 0}] : SB \in SUBSET BagToSet(B)} 113 | IN {SB \in AllBagsOfSubset : \A e \in DOMAIN SB : SB[e] \leq B[e]} 114 | ***************************************************************************) 115 | 116 | BagOfAll(F(_), B) == 117 | (************************************************************************) 118 | (* The bag analog of the set {F(x) : x \in B} for a set B. It's the bag *) 119 | (* that contains, for each element e of B, one copy of F(e) for every *) 120 | (* copy of e in B. This defines a bag iff, for any value v, the set of *) 121 | (* e in B such that F(e) = v is finite. *) 122 | (************************************************************************) 123 | [e \in {F(d) : d \in BagToSet(B)} |-> 124 | Sum( [d \in BagToSet(B) |-> IF F(d) = e THEN B[d] ELSE 0] ) ] 125 | 126 | BagCardinality(B) == 127 | (************************************************************************) 128 | (* If B is a finite bag (one such that BagToSet(B) is a finite set), *) 129 | (* then this is its cardinality (the total number of copies of elements *) 130 | (* in B). Its value is unspecified if B is infinite. *) 131 | (************************************************************************) 132 | Sum(B) 133 | 134 | CopiesIn(e, B) == 135 | (************************************************************************) 136 | (* If B is a bag, then CopiesIn(e, B) is the number of copies of e in *) 137 | (* B. If ~BagIn(e, B), then CopiesIn(e, B) = 0. *) 138 | (************************************************************************) 139 | IF BagIn(e, B) THEN B[e] ELSE 0 140 | ============================================================================= 141 | 142 | (* Last modified on Fri 26 Jan 2007 at 8:45:03 PST by lamport *) 143 | 144 | (* 145 | 6 Apr 99 : Modified version for standard module set 146 | 7 Dec 98 : Corrected error found by Stephan Merz. 147 | 6 Dec 98 : Modified comments based on suggestions by Lyle Ramshaw. 148 | 5 Dec 98 : Initial version. 149 | *) 150 | -------------------------------------------------------------------------------- /modules/lib/TLC.tla: -------------------------------------------------------------------------------- 1 | ------------------------------- MODULE TLC ---------------------------------- 2 | (***************************************************************************) 3 | (* This is a standard module for use with the TLC model checker. *) 4 | (* Operators not explained by comments here are explained in the book *) 5 | (* "Specifying Systems". *) 6 | (* *) 7 | (* The definitions of all the operators in this module are overridden by *) 8 | (* TLC with methods defined in the Java class tlc2.module.TLC. Each *) 9 | (* definition is overridden with the method of the same name, except that *) 10 | (* the mapping from infix operators to Java methods is specified in the *) 11 | (* static block at the beginning of the Java class. *) 12 | (***************************************************************************) 13 | LOCAL INSTANCE Naturals 14 | LOCAL INSTANCE Sequences 15 | LOCAL INSTANCE FiniteSets 16 | ----------------------------------------------------------------------------- 17 | Print(out, val) == val 18 | PrintT(out) == TRUE 19 | (************************************************************************) 20 | (* This expression equals TRUE, but evaluating it causes TLC to print *) 21 | (* the value of out. *) 22 | (************************************************************************) 23 | 24 | Assert(val, out) == IF val = TRUE THEN TRUE 25 | ELSE CHOOSE v : TRUE 26 | JavaTime == CHOOSE n : n \in Nat 27 | 28 | (***************************************************************************) 29 | (* TLC can read and set a special list of values while evaluating *) 30 | (* expressions using the operators TLCSet and TLCGet. When TLC evaluates *) 31 | (* TLCSet(i,v), for any positive integer i and arbitrary value v, it *) 32 | (* obtains the value TRUE and sets element number i of the list to v. *) 33 | (* When TLC evaluates TLCGet(i), the value it obtains is the current value *) 34 | (* of the element number i of this list. *) 35 | (* *) 36 | (* One use of this feature is to check TLC's progress during long *) 37 | (* computations. For example, suppose TLC is evaluating a formula *) 38 | (* \A x \in S : P where S is a large set, so it evaluates P many times. *) 39 | (* You can use TLCGet, TLCSet, and Print to print something after every *) 40 | (* 1000 times TLC evaluates P. *) 41 | (* *) 42 | (* As explained in the description of the TLCEval operator below, you may *) 43 | (* also want to use this feature to count how many times TLC is evaluating *) 44 | (* an expression e. To use value number i as the counter, just replace e *) 45 | (* by *) 46 | (* *) 47 | (* IF TLCSet(i, TLCGet(i)+1) THEN e ELSE 42 *) 48 | (* *) 49 | (* (The ELSE expression is never evaluated.) *) 50 | (* *) 51 | (* TLCGet accepts some pre-defined string values to query TLC state. The *) 52 | (* values are as follows: *) 53 | (* *) 54 | (* - TLCGet("distinct") evaluates to the total number of distinct states *) 55 | (* found by TLC so far, globally. *) 56 | (* - TLCGet("queue") evaluates to the number of states currently in the *) 57 | (* queue to be checked. *) 58 | (* - TLCGet("duration") evaluates to the number of seconds elapsed since *) 59 | (* model checking began. *) 60 | (* - TLCGet("diameter") evaluates to the length of the longest behavior *) 61 | (* found by TLC so far, globally (equals one in the initial predicate).*) 62 | (* - TLCGet("level") is the length of the current behavior (equals zero *) 63 | (* in the evaluation of the initial predicate). *) 64 | (* *) 65 | (* For reasons of efficiency, TLCGet and TLCSet behave somewhat strangely *) 66 | (* when TLC is run with multiple worker threads. Each worker thread *) 67 | (* maintains its own individual copy of the list of values on which it *) 68 | (* evaluates TLCGet and TLCSet. The worker threads are activated only *) 69 | (* after the computation and invariance checking of the initial states. *) 70 | (* Before then, evaluating TLCSet(i,v) sets the element i of the list *) 71 | (* maintained by all threads. Thus, the lists of all the worker threads *) 72 | (* can be initialized by putting the appropriate TLCSet expression in an *) 73 | (* ASSUME expression or in the initial predicate. *) 74 | (***************************************************************************) 75 | 76 | TLCGet(i) == CHOOSE n : TRUE 77 | TLCSet(i, v) == TRUE 78 | ----------------------------------------------------------------------------- 79 | d :> e == [x \in {d} |-> e] 80 | f @@ g == [x \in (DOMAIN f) \cup (DOMAIN g) |-> 81 | IF x \in DOMAIN f THEN f[x] ELSE g[x]] 82 | 83 | Permutations(S) == 84 | {f \in [S -> S] : \A w \in S : \E v \in S : f[v]=w} 85 | ----------------------------------------------------------------------------- 86 | (***************************************************************************) 87 | (* In the following definition, we use Op as the formal parameter rather *) 88 | (* than \prec because TLC Version 1 can't handle infix formal parameters. *) 89 | (***************************************************************************) 90 | SortSeq(s, Op(_, _)) == 91 | LET Perm == CHOOSE p \in Permutations(1 .. Len(s)) : 92 | \A i, j \in 1..Len(s) : 93 | (i < j) => Op(s[p[i]], s[p[j]]) \/ (s[p[i]] = s[p[j]]) 94 | IN [i \in 1..Len(s) |-> s[Perm[i]]] 95 | 96 | (***************************************************************************) 97 | (* TLC evaluates RandomElement(S) to be a pseudo-randomly chosen element *) 98 | (* of the set S, where each element of S is chosen with equal probability. *) 99 | (* This feature was added to enable the computation of statistical *) 100 | (* properties of a specification's executions by running TLC in simulation *) 101 | (* mode. We don't know if anyone has ever done this. *) 102 | (* *) 103 | (* In breadth-first search model checking, the pseudo-random choices made *) 104 | (* when computing possible steps satisfying the next-state relation are *) 105 | (* determined by the first state of the step. Thus, the choices made for *) 106 | (* a particular state will be the same in successive runs of TLC. This is *) 107 | (* done to permit TLC to generate an error trace if an error is found. *) 108 | (* This applies only when TLC is run in breadth-first search mode. The *) 109 | (* random choices made in simulation mode are independent of the state for *) 110 | (* which they are made. *) 111 | (***************************************************************************) 112 | RandomElement(s) == CHOOSE x \in s : TRUE 113 | 114 | (***************************************************************************) 115 | (* The constant value Any has the special property that, for any value v, *) 116 | (* TLC evaluates the expression v \in Any to equal TRUE. The special *) 117 | (* value Any was introduced because TLA+ originally allowed only functions *) 118 | (* to be defined recursively, and it was sometimes convenient to define a *) 119 | (* function with domain Any. It is retained for backwards compatibility. *) 120 | (***************************************************************************) 121 | Any == CHOOSE x : TRUE 122 | 123 | ToString(v) == (CHOOSE x \in [a : v, b : STRING] : TRUE).b 124 | (************************************************************************) 125 | (* This equals a string that is the TLA+ representation of the value *) 126 | (* that TLC obtains by evaluating v. *) 127 | (************************************************************************) 128 | 129 | (***************************************************************************) 130 | (* TLC often uses lazy evaluation. For example, it may not enumerate the *) 131 | (* elements of a set of the form {x \in T : P(x)} unless it has to; and it *) 132 | (* doesn't have to if it only needs to check if an element e is in that *) 133 | (* set. (TLC can do that by evaluating x \in T and P(e).) TLC uses *) 134 | (* heuristics to determine when it should completely evaluate an *) 135 | (* expression. Those heuristics work well most of the time. However, *) 136 | (* sometimes lazy evaluation can result in the expression ultimately being *) 137 | (* evaluated multiple times instead of just once. This can especially be *) 138 | (* a problem when evaluating a recursively defined operator. You can get *) 139 | (* TLC to fully evaluate an expression exp and not use lazy evaluation by *) 140 | (* replacing exp with TLCEval(exp). *) 141 | (* *) 142 | (* If TLC is taking a long time to evaluate something, you can check if *) 143 | (* lazy evaluation is the source of the problem by using the TLCSet and *) 144 | (* TLCGet operators to count how many times expressions are being *) 145 | (* evaluated. *) 146 | (***************************************************************************) 147 | TLCEval(v) == v 148 | 149 | ============================================================================= -------------------------------------------------------------------------------- /tests/regression/test2.exp: -------------------------------------------------------------------------------- 1 | Initial context: [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a1", 1 |-> "a1" ], turn |-> 0 ] 2 | Next state: 0 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a1", 1 |-> "a2" ], turn |-> 0 ] 3 | Next state: 1 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a2", 1 |-> "a2" ], turn |-> 0 ] 4 | Next state: 2 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a2", 1 |-> "a3" ], turn |-> 0 ] 5 | Next state: 3 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a3", 1 |-> "a3" ], turn |-> 0 ] 6 | Next state: 4 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4", 1 |-> "a3" ], turn |-> 1 ] 7 | Next state: 5 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4", 1 |-> "a4" ], turn |-> 0 ] 8 | Next state: 6 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4a", 1 |-> "a4" ], turn |-> 0 ] 9 | Next state: 7 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4b", 1 |-> "a4" ], turn |-> 0 ] 10 | Next state: 8 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4b", 1 |-> "a4a" ], turn |-> 0 ] 11 | Next state: 9 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "cs", 1 |-> "a4a" ], turn |-> 0 ] 12 | Next state: 10 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a5", 1 |-> "a4a" ], turn |-> 0 ] 13 | Next state: 11 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a6", 1 |-> "a4a" ], turn |-> 0 ] 14 | Next state: 12 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a6", 1 |-> "cs" ], turn |-> 0 ] 15 | Next state: 13 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a1", 1 |-> "cs" ], turn |-> 0 ] 16 | Next state: 14 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a1", 1 |-> "a5" ], turn |-> 0 ] 17 | Next state: 15 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a2", 1 |-> "a5" ], turn |-> 0 ] 18 | Next state: 16 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a3", 1 |-> "a5" ], turn |-> 0 ] 19 | Next state: 17 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a3", 1 |-> "a6" ], turn |-> 0 ] 20 | Next state: 18 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a4", 1 |-> "a6" ], turn |-> 1 ] 21 | Next state: 19 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a4", 1 |-> "a1" ], turn |-> 1 ] 22 | Next state: 20 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a4a", 1 |-> "a1" ], turn |-> 1 ] 23 | Next state: 21 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "cs", 1 |-> "a1" ], turn |-> 1 ] 24 | Next state: 22 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a5", 1 |-> "a1" ], turn |-> 1 ] 25 | Next state: 23 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a5", 1 |-> "a2" ], turn |-> 1 ] 26 | Next state: 24 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a5", 1 |-> "a3" ], turn |-> 1 ] 27 | Next state: 25 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a5", 1 |-> "a4" ], turn |-> 0 ] 28 | Next state: 26 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a5", 1 |-> "a4a" ], turn |-> 0 ] 29 | Next state: 27 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a6", 1 |-> "a4a" ], turn |-> 0 ] 30 | Next state: 28 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a6", 1 |-> "cs" ], turn |-> 0 ] 31 | Next state: 29 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a6", 1 |-> "a5" ], turn |-> 0 ] 32 | Next state: 30 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a1", 1 |-> "a5" ], turn |-> 0 ] 33 | Next state: 31 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a2", 1 |-> "a5" ], turn |-> 0 ] 34 | Next state: 32 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a3", 1 |-> "a5" ], turn |-> 0 ] 35 | Next state: 33 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4", 1 |-> "a5" ], turn |-> 1 ] 36 | Next state: 34 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a4", 1 |-> "a6" ], turn |-> 1 ] 37 | Next state: 35 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a4a", 1 |-> "a6" ], turn |-> 1 ] 38 | Next state: 36 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "cs", 1 |-> "a6" ], turn |-> 1 ] 39 | Next state: 37 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a5", 1 |-> "a6" ], turn |-> 1 ] 40 | Next state: 38 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a6", 1 |-> "a6" ], turn |-> 1 ] 41 | Next state: 39 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a6", 1 |-> "a1" ], turn |-> 1 ] 42 | Next state: 40 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a1", 1 |-> "a1" ], turn |-> 0 ] 43 | Next state: 41 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a2", 1 |-> "a1" ], turn |-> 0 ] 44 | Next state: 42 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a2", 1 |-> "a2" ], turn |-> 0 ] 45 | Next state: 43 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a3", 1 |-> "a2" ], turn |-> 0 ] 46 | Next state: 44 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a3", 1 |-> "a3" ], turn |-> 0 ] 47 | Next state: 45 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4", 1 |-> "a3" ], turn |-> 1 ] 48 | Next state: 46 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4", 1 |-> "a4" ], turn |-> 0 ] 49 | Next state: 47 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4a", 1 |-> "a4" ], turn |-> 0 ] 50 | Next state: 48 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4b", 1 |-> "a4" ], turn |-> 0 ] 51 | Next state: 49 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "cs", 1 |-> "a4" ], turn |-> 0 ] 52 | Next state: 50 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a5", 1 |-> "a4" ], turn |-> 0 ] 53 | Next state: 51 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a5", 1 |-> "a4a" ], turn |-> 0 ] 54 | Next state: 52 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a6", 1 |-> "a4a" ], turn |-> 0 ] 55 | Next state: 53 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a1", 1 |-> "a4a" ], turn |-> 0 ] 56 | Next state: 54 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a1", 1 |-> "cs" ], turn |-> 0 ] 57 | Next state: 55 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a1", 1 |-> "a5" ], turn |-> 0 ] 58 | Next state: 56 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a1", 1 |-> "a6" ], turn |-> 0 ] 59 | Next state: 57 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a1", 1 |-> "a1" ], turn |-> 1 ] 60 | Next state: 58 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a2", 1 |-> "a1" ], turn |-> 1 ] 61 | Next state: 59 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a3", 1 |-> "a1" ], turn |-> 1 ] 62 | Next state: 60 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a4", 1 |-> "a1" ], turn |-> 1 ] 63 | Next state: 61 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a4a", 1 |-> "a1" ], turn |-> 1 ] 64 | Next state: 62 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a4a", 1 |-> "a2" ], turn |-> 1 ] 65 | Next state: 63 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4a", 1 |-> "a3" ], turn |-> 1 ] 66 | Next state: 64 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4a", 1 |-> "a4" ], turn |-> 0 ] 67 | Next state: 65 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4a", 1 |-> "a4a" ], turn |-> 0 ] 68 | Next state: 66 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4b", 1 |-> "a4a" ], turn |-> 0 ] 69 | Next state: 67 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4b", 1 |-> "a4b" ], turn |-> 0 ] 70 | Next state: 68 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4b", 1 |-> "a4" ], turn |-> 0 ] 71 | Next state: 69 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "cs", 1 |-> "a4" ], turn |-> 0 ] 72 | Next state: 70 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a5", 1 |-> "a4" ], turn |-> 0 ] 73 | Next state: 71 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a6", 1 |-> "a4" ], turn |-> 0 ] 74 | Next state: 72 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a6", 1 |-> "a4a" ], turn |-> 0 ] 75 | Next state: 73 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a6", 1 |-> "cs" ], turn |-> 0 ] 76 | Next state: 74 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a6", 1 |-> "a5" ], turn |-> 0 ] 77 | Next state: 75 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a1", 1 |-> "a5" ], turn |-> 0 ] 78 | Next state: 76 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a2", 1 |-> "a5" ], turn |-> 0 ] 79 | Next state: 77 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a2", 1 |-> "a6" ], turn |-> 0 ] 80 | Next state: 78 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a2", 1 |-> "a1" ], turn |-> 1 ] 81 | Next state: 79 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a2", 1 |-> "a2" ], turn |-> 1 ] 82 | Next state: 80 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a3", 1 |-> "a2" ], turn |-> 1 ] 83 | Next state: 81 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a3", 1 |-> "a3" ], turn |-> 1 ] 84 | Next state: 82 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a3", 1 |-> "a4" ], turn |-> 0 ] 85 | Next state: 83 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a3", 1 |-> "a4a" ], turn |-> 0 ] 86 | Next state: 84 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4", 1 |-> "a4a" ], turn |-> 1 ] 87 | Next state: 85 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4", 1 |-> "a4b" ], turn |-> 1 ] 88 | Next state: 86 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4", 1 |-> "cs" ], turn |-> 1 ] 89 | Next state: 87 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4", 1 |-> "a5" ], turn |-> 1 ] 90 | Next state: 88 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a4a", 1 |-> "a5" ], turn |-> 1 ] 91 | Next state: 89 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a4a", 1 |-> "a6" ], turn |-> 1 ] 92 | Next state: 90 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "cs", 1 |-> "a6" ], turn |-> 1 ] 93 | Next state: 91 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "cs", 1 |-> "a1" ], turn |-> 1 ] 94 | Next state: 92 [ flag |-> [ 0 |-> TRUE, 1 |-> FALSE ], pc |-> [ 0 |-> "a5", 1 |-> "a1" ], turn |-> 1 ] 95 | Next state: 93 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a6", 1 |-> "a1" ], turn |-> 1 ] 96 | Next state: 94 [ flag |-> [ 0 |-> FALSE, 1 |-> FALSE ], pc |-> [ 0 |-> "a6", 1 |-> "a2" ], turn |-> 1 ] 97 | Next state: 95 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a6", 1 |-> "a3" ], turn |-> 1 ] 98 | Next state: 96 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a1", 1 |-> "a3" ], turn |-> 0 ] 99 | Next state: 97 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a1", 1 |-> "a4" ], turn |-> 0 ] 100 | Next state: 98 [ flag |-> [ 0 |-> FALSE, 1 |-> TRUE ], pc |-> [ 0 |-> "a2", 1 |-> "a4" ], turn |-> 0 ] 101 | Next state: 99 [ flag |-> [ 0 |-> TRUE, 1 |-> TRUE ], pc |-> [ 0 |-> "a3", 1 |-> "a4" ], turn |-> 0 ] 102 | MAIN DONE 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pluspy 2 | 3 | pluspy is a TLA+ interpreter, written in Python. 4 | 5 | Run "./pluspy -h" for basic help. The output should be something like: 6 | 7 | Usage: pluspy [options] [module] 8 | options: 9 | -c cnt: #times that Next should be evaluated 10 | -h: help 11 | -i: Init operator (default Init) 12 | -n: Next operator (default Next) 13 | -P path: module directory search path 14 | -s: silent output 15 | -S seed: random seed for reproducible tests 16 | -v: verbose output 17 | 18 | You can also invoke pluspy with "-i Spec" where Spec is a full TLA+ 19 | specification. Try for example "./pluspy -i Spec Prime", which 20 | should print the prime numbers. 21 | 22 | pluspy is a Bash shell script. If you can't run it, try "python3 pluspy.py" 23 | instead. 24 | 25 | -------- EXAMPLE 1: HourClock -------- 26 | 27 | Run "./pluspy -c2 HourClock" 28 | 29 | The output should be something like: 30 | 31 | Initial context: [ hr: 6 ] 32 | Next state: 0 [ hr: 7 ] 33 | Next state: 1 [ hr: 8 ] 34 | MAIN DONE 35 | 36 | You can find the HourClock module in modules/book/HourClock.tla. 37 | The interpreter shows three "contexts", which are assignments of 38 | constants and variables to values. It first shows the "Initial 39 | context," computed by the "Init" operator in HourClock.tla. (The 40 | initial value of hr is a random number between 1 and 12.) Then it 41 | shows two more contexts computed by the "Next" operator in 42 | HourClock.tla. The number of steps can be controlled with the "-c" 43 | option to pluspy. 44 | 45 | You should be able to run Peterson.tla, Prime.tla, and Qsort.tla in 46 | much the same way, but try larger -c counts for those. 47 | 48 | -------- EXAMPLE 2: Threads -------- 49 | 50 | The Peterson module has multiple processes. PlusPy can run each as 51 | a separate thread. Run: "./pluspy -c100 -n proc%0 -n proc%1 Peterson". 52 | "proc" is an operator in the Peterson module that takes an argument. 53 | The "-n x%y" argument to pluspy starts a thread that repeatedly evaluates 54 | the x operator with argument y instead of the default "Next". You may 55 | also want to try: "./pluspy -c100 -n proc%0 Peterson" and 56 | "./pluspy -c100 -n proc%1 Peterson" which each will run just one of the 57 | processes. 58 | 59 | Using the new JWait/JSignalReturn interfaces in TLCExt, threads can use 60 | condition variables. See modules/other/BoundedQueueSplit.tla for an 61 | example. Run as follows: 62 | 63 | ./pluspy -n producer%p1 -c100 -n producer%p2 -n producer%p3 \ 64 | -n consumer%c1 -n consumer%c2 -n consumer%c3 TestBQ 65 | 66 | (This won't work if you try to run this without threads.) 67 | 68 | -------- EXAMPLE 3: Sending and Receiving Messages -------- 69 | 70 | Open three windows. Run the following commands, one in each of the windows: 71 | 72 | ./pluspy -c100 -n Proc%localhost:5001 TestBinBosco 73 | ./pluspy -c100 -n Proc%localhost:5002 TestBinBosco 74 | ./pluspy -c100 -n Proc%localhost:5003 TestBinBosco 75 | 76 | The Proc action takes one argument, the process identifier, 77 | 78 | The processes will actually send and receive messages, trying to 79 | solve consensus. Although BinBosco has no rule to actually decide, 80 | in all likelihood they will each end up with the same estimate after 81 | about five rounds. Only three of the four processes can do so. You 82 | can inspect the output and see the state of each of the processes 83 | and the set Messages. The "processes" variable of localhost:5001 84 | should contain something like the following in the end: 85 | 86 | [ 87 | "localhost:5001" |-> [ estimate |-> "red", round |-> 5 ], 88 | "localhost:5002" |-> [ estimate |-> "blue", round |-> 0 ], 89 | "localhost:5003" |-> [ estimate |-> "red", round |-> 0 ], 90 | "localhost:5004" |-> [ estimate |-> "blue", round |-> 0 ] 91 | ] 92 | 93 | Similarly, the "processes" variable of localhost:5002 might contain: 94 | 95 | [ 96 | "localhost:5001" |-> [ estimate |-> "red", round |-> 0 ], 97 | "localhost:5002" |-> [ estimate |-> "red", round |-> 5 ], 98 | "localhost:5003" |-> [ estimate |-> "red", round |-> 0 ], 99 | "localhost:5004" |-> [ estimate |-> "blue", round |-> 0 ] 100 | ] 101 | 102 | Note that all processes end up with the same estimate, probably 103 | around round 5. Running BinBosco this way is a little odd, as each 104 | pluspy process only updates part of what is really supposed to be 105 | a global state. You can imagine there being a refinement mapping 106 | to the virtual global state, where the local state of TLA+ process 107 | i in pluspy process i maps to the state of TLA+ process i in the 108 | global state. 109 | 110 | Messaging is specified in the modules/lib/Messaging.tla module. 111 | Besides the message interface variable mi, there are the following 112 | three operators exported: 113 | 114 | Init \* initializes mi 115 | Send(msgs) \* sends the given << destination, payload >> messages 116 | Receive(p, Deliver(_, _)) \* wait for a message for p and call Deliver(p, payload) 117 | 118 | The spec proper is specified after the comment "\*++:SPEC". If you look further 119 | you'll find a second comment "\*++:PlusPy". This is where the implementation of 120 | the messaging module starts. It uses the IOUtils module described below. 121 | 122 | -------- The IOUtils module -------- 123 | 124 | PlusPy exports a module in modules/lib/IOUtils.tla that allows processes to do various 125 | kinds of I/O. There are currently three kinds of interfaces defined: "fd", "tcp", 126 | and "local". For "fd", there are three muxes: "stdin", "stdout", and "stderr". 127 | For example IOPut("fd", "stdout", "hello") prints hello. Note that all I/O is 128 | "deferred": it is only performed if the action in which it occurs evaluates to TRUE. 129 | 130 | The modules/lib/Input.tla module shows how one can read from standard input. 131 | The Input.tla module is "pure TLA+" -- it has no implied variable. It also 132 | provides an example of the "\*++:SPEC" and "\*++:PlusPy" sections. 133 | 134 | To send and receive TCP messages, use the "tcp" interface and use as "mux" a 135 | TCP/IP address of the form "x.x.x.x:port". 136 | 137 | The "local" interface is a little like the IP loopback interface. It allows 138 | sending messages to self. 139 | 140 | -------- TLA+ value representations in Python -------- 141 | 142 | The basic values are booleans, numbers, and strings: 143 | 144 | FALSE: False 145 | TRUE: True 146 | number: number 147 | string: string 148 | 149 | TLA+ sets are represented as Python frozensets, A frozenset is like 150 | a Python set but is hashable because it cannot be modified. 151 | 152 | Essentially, a tuple is represented as a tuple, and a record as a 153 | pluspy.FrozenDict. 154 | 155 | However, to ensure that equal values have the same representation, 156 | records that are tuples (because their keys are in the range 1..len) 157 | are represented as tuples, and tuples that are strings (because all 158 | their elements are characters) are represented as strings. In 159 | particular, empty records and tuples are represented as the empty 160 | string. 161 | 162 | There is also a "Nonce" type for "CHOOSE x: x \notin S" expressions. 163 | 164 | Note that in Python False == 0 and True == 1. This can lead to 165 | weird behaviors. 166 | 167 | For example, { False, 0 } == { False } == { 0 } == { 0, False }. 168 | 169 | -------- PlusPy Module -------- 170 | PlusPy can also be used as a Python module, so you integrate Python and 171 | TLA+ programs quite easily. The interface is as follows: 172 | 173 | pp = pluspy.PlusPy(module, constants={}) 174 | 'module' is a string containing either a file name or the 175 | name of a TLA+ module. Constants is a dictionary that maps 176 | constant names to values (see TLA+ value represenations.) 177 | 178 | pp.init(Init) 179 | 'Init' is a string containing the name of the 'init' operator 180 | in the TLA+ formula: "Spec == Init /\ [][Next]". You can also 181 | pass the "Spec" operator, but it will not give back control 182 | until "Next" evaluates to FALSE. Also, does not implement 183 | environment variables at the moment. 184 | 185 | pp.next(Next, arg=None) 186 | 'Next' is a string containing the name of the 'Next' operator 187 | in the TLA+ formula: "Spec == Init /\ [][Next]". If Next takes 188 | an argument, "arg" contains its value. It returns True if some 189 | action was enabled and False if no action was enabled. Typically 190 | pp.next() is called within a loop. Interface state variables 191 | can be changed in the loop if desired. 192 | 193 | pp.unchanged() 194 | Checks to see if the state has changed after pp.next() 195 | 196 | value = pp.get(variable) 197 | "variable" is a string containing the name of a variable. Its 198 | value is returned. For the representation of TLA+ values, see 199 | below. 200 | 201 | value = pp.getall(): 202 | returns a single record value containing all variables 203 | 204 | pp.set(variable, value) 205 | "variable" is a string containing the name of a variable. Its 206 | value is set to "value". For the representation of TLA+ values, 207 | see below. 208 | 209 | v = pluspy.format(v): 210 | Convert a value to a string formatted in TLA+ format 211 | 212 | v = pluspy.convert(v): 213 | Convert a value to something a little more normal and better for 214 | handling in Python. In particular, it turns records into dictionaries, 215 | and frozensets into lists 216 | 217 | -------- PlusPy Wrappers -------- 218 | 219 | PlusPy allows operators in specified modules to be replaced by Python 220 | code. You can specify this in the pluspy.wrappers variable. For example: 221 | 222 | class LenWrapper(pluspy.Wrapper): 223 | def eval(self, id, args): 224 | assert id == "Len" 225 | assert len(args) == 1 226 | return len(args[0]) 227 | 228 | pluspy.wrappers["Sequences"] = { 229 | "Len": LenWrapper() 230 | } 231 | 232 | The IOUtils module is implemented using a wrapper. 233 | 234 | -------- Discussion of interfacing between Python and TLA+ -------- 235 | 236 | PlusPy allows TLA+ and Python to interface in a variety of ways, as demonstrated 237 | above. It is important to try to avoid ad hoc solutions. The Messaging and Input 238 | modules provide a clean separation between the TLA+ world and the Python world. 239 | They can be used with the TLC model checker or TLAPS to validate your code. The 240 | IOUtils module is outside the TLA+ world, so if you extend it, try to do it through a 241 | module that has clean semantics. 242 | 243 | Similarly, while it is possible to invoke operators other than "Spec" directly from 244 | Python, and while it is possible to write state variables directly from Python, this 245 | circumvents the TLA+ framework. Use caution. 246 | -------------------------------------------------------------------------------- /tests/regression/test10.exp: -------------------------------------------------------------------------------- 1 | Next state: 0 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> <<>> ] 2 | Next state: 1 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> <<>> ] 3 | Next state: 2 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 4 | Next state: 3 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 5 | Next state: 4 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 6 | Next state: 5 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 7 | Next state: 6 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red" >> ] 8 | Next state: 7 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red" >> ] 9 | Next state: 8 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 10 | Next state: 9 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 11 | Next state: 10 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 12 | Next state: 11 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 13 | Next state: 12 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 14 | Next state: 13 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 15 | Next state: 14 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 16 | Next state: 15 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 17 | Next state: 16 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue" >> ] 18 | Next state: 17 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue" >> ] 19 | Next state: 18 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue" >> ] 20 | Next state: 19 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue" >> ] 21 | Next state: 20 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue" >> ] 22 | Next state: 21 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue" >> ] 23 | Next state: 22 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue" >> ] 24 | Next state: 23 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue" >> ] 25 | Next state: 24 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue" >> ] 26 | Next state: 25 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue" >> ] 27 | Next state: 26 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue" >> ] 28 | Next state: 27 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue" >> ] 29 | Next state: 28 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red" >> ] 30 | Next state: 29 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red" >> ] 31 | Next state: 30 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red" >> ] 32 | Next state: 31 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red" >> ] 33 | Next state: 32 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red" >> ] 34 | Next state: 33 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red" >> ] 35 | Next state: 34 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red" >> ] 36 | Next state: 35 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red" >> ] 37 | Next state: 36 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red" >> ] 38 | Next state: 37 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red" >> ] 39 | Next state: 38 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 40 | Next state: 39 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 41 | Next state: 40 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 42 | Next state: 41 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 43 | Next state: 42 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue" >> ] 44 | Next state: 43 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue" >> ] 45 | Next state: 44 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 46 | Next state: 45 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 47 | Next state: 46 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> <<>> ] 48 | Next state: 47 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> <<>> ] 49 | Next state: 48 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue" >> ] 50 | Next state: 49 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "blue" >> ] 51 | Next state: 50 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> <<>> ] 52 | Next state: 51 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> <<>> ] 53 | Next state: 52 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue" >> ] 54 | Next state: 53 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue" >> ] 55 | Next state: 54 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue" >> ] 56 | Next state: 55 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> <<>> ] 57 | Next state: 56 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red" >> ] 58 | Next state: 57 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red" >> ] 59 | Next state: 58 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red" >> ] 60 | Next state: 59 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "blue" >> ] 61 | Next state: 60 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "blue" >> ] 62 | Next state: 61 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 63 | Next state: 62 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red" >> ] 64 | Next state: 63 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red" >> ] 65 | Next state: 64 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red" >> ] 66 | Next state: 65 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red" >> ] 67 | Next state: 66 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red" >> ] 68 | Next state: 67 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red" >> ] 69 | Next state: 68 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "blue" >> ] 70 | Next state: 69 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "blue" >> ] 71 | Next state: 70 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 72 | Next state: 71 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 73 | Next state: 72 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red" >> ] 74 | Next state: 73 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red" >> ] 75 | Next state: 74 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red" >> ] 76 | Next state: 75 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red" >> ] 77 | Next state: 76 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red" >> ] 78 | Next state: 77 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red" >> ] 79 | Next state: 78 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red" >> ] 80 | Next state: 79 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 81 | Next state: 80 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 82 | Next state: 81 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 83 | Next state: 82 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 84 | Next state: 83 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 85 | Next state: 84 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 86 | Next state: 85 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 87 | Next state: 86 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 88 | Next state: 87 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 89 | Next state: 88 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 90 | Next state: 89 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 91 | Next state: 90 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 92 | Next state: 91 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 93 | Next state: 92 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> <<>> ] 94 | Next state: 93 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue" >> ] 95 | Next state: 94 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue" >> ] 96 | Next state: 95 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red" >> ] 97 | Next state: 96 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red" >> ] 98 | Next state: 97 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "red" >> ] 99 | Next state: 98 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "red" >> ] 100 | Next state: 99 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red" >> ] 101 | Next state: 100 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red" >> ] 102 | -------------------------------------------------------------------------------- /tests/regression/test7.exp: -------------------------------------------------------------------------------- 1 | Initial context: [ output |-> "under construction", todo |-> << << 0, 383, 886, 777, 915, 793, 335, 386, 492, 649, 421, 362, 27, 690, 59, 763, 926, 540, 426, 172, 736, 211, 368, 567, 429, 782, 530, 862, 123, 67, 135, 929, 802, 22, 58, 69, 167, 393, 456, 11, 42, 229, 373 >> >> ] 2 | Next state: 0 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 383, 886, 777, 915, 793, 335, 386, 492, 649, 421, 362, 27, 690, 59, 763, 926, 540, 426, 172, 736, 211, 368, 567, 429, 782, 530, 862, 123, 67, 135, 929, 802, 22, 58, 69, 167, 393, 456, 11, 42, 229, 373 >> >> ] 3 | Next state: 1 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 335, 362, 27, 59, 172, 211, 368, 123, 67, 135, 22, 58, 69, 167, 11, 42, 229, 373 >>, << 383 >>, << 886, 777, 915, 793, 386, 492, 649, 421, 690, 763, 926, 540, 426, 736, 567, 429, 782, 530, 862, 929, 802, 393, 456 >> >> ] 4 | Next state: 2 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 27, 59, 172, 211, 123, 67, 135, 22, 58, 69, 167, 11, 42, 229 >>, << 335 >>, << 362, 368, 373 >>, << 383 >>, << 886, 777, 915, 793, 386, 492, 649, 421, 690, 763, 926, 540, 426, 736, 567, 429, 782, 530, 862, 929, 802, 393, 456 >> >> ] 5 | Next state: 3 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 22, 11 >>, << 27 >>, << 59, 172, 211, 123, 67, 135, 58, 69, 167, 42, 229 >>, << 335 >>, << 362, 368, 373 >>, << 383 >>, << 886, 777, 915, 793, 386, 492, 649, 421, 690, 763, 926, 540, 426, 736, 567, 429, 782, 530, 862, 929, 802, 393, 456 >> >> ] 6 | Next state: 4 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 22, 11 >>, << 27 >>, << 59, 172, 211, 123, 67, 135, 58, 69, 167, 42, 229 >>, << 335 >>, << 362, 368, 373 >>, << 383 >>, << 777, 793, 386, 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 782, 530, 862, 802, 393, 456 >>, << 886 >>, << 915, 926, 929 >> >> ] 7 | Next state: 5 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 22, 11 >>, << 27 >>, << 59, 172, 211, 123, 67, 135, 58, 69, 167, 42, 229 >>, << 335 >>, << 362, 368, 373 >>, << 383 >>, << 777, 793, 386, 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 782, 530, 862, 802, 393, 456 >>, << 886 >>, <<>>, << 915 >>, << 926, 929 >> >> ] 8 | Next state: 6 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 22, 11 >>, << 27 >>, << 58, 42 >>, << 59 >>, << 172, 211, 123, 67, 135, 69, 167, 229 >>, << 335 >>, << 362, 368, 373 >>, << 383 >>, << 777, 793, 386, 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 782, 530, 862, 802, 393, 456 >>, << 886 >>, <<>>, << 915 >>, << 926, 929 >> >> ] 9 | Next state: 7 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 22, 11 >>, << 27 >>, << 58, 42 >>, << 59 >>, << 172, 211, 123, 67, 135, 69, 167, 229 >>, << 335 >>, << 362, 368, 373 >>, << 383 >>, << 777, 793, 386, 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 782, 530, 862, 802, 393, 456 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 10 | Next state: 8 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 22, 11 >>, << 27 >>, << 58, 42 >>, << 59 >>, << 123, 67, 135, 69, 167 >>, << 172 >>, << 211, 229 >>, << 335 >>, << 362, 368, 373 >>, << 383 >>, << 777, 793, 386, 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 782, 530, 862, 802, 393, 456 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 11 | Next state: 9 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, << 123, 67, 135, 69, 167 >>, << 172 >>, << 211, 229 >>, << 335 >>, << 362, 368, 373 >>, << 383 >>, << 777, 793, 386, 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 782, 530, 862, 802, 393, 456 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 12 | Next state: 10 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, << 123, 67, 135, 69, 167 >>, << 172 >>, << 211, 229 >>, << 335 >>, <<>>, << 362 >>, << 368, 373 >>, << 383 >>, << 777, 793, 386, 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 782, 530, 862, 802, 393, 456 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 13 | Next state: 11 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, << 67, 69 >>, << 123 >>, << 135, 167 >>, << 172 >>, << 211, 229 >>, << 335 >>, <<>>, << 362 >>, << 368, 373 >>, << 383 >>, << 777, 793, 386, 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 782, 530, 862, 802, 393, 456 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 14 | Next state: 12 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, << 67, 69 >>, << 123 >>, << 135, 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, << 368, 373 >>, << 383 >>, << 777, 793, 386, 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 782, 530, 862, 802, 393, 456 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 15 | Next state: 13 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, << 67, 69 >>, << 123 >>, << 135, 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, << 368, 373 >>, << 383 >>, << 386, 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 530, 393, 456 >>, << 777 >>, << 793, 782, 862, 802 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 16 | Next state: 14 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, << 67, 69 >>, << 123 >>, << 135, 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, << 368, 373 >>, << 383 >>, <<>>, << 386 >>, << 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 530, 393, 456 >>, << 777 >>, << 793, 782, 862, 802 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 17 | Next state: 15 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, << 135, 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, << 368, 373 >>, << 383 >>, <<>>, << 386 >>, << 492, 649, 421, 690, 763, 540, 426, 736, 567, 429, 530, 393, 456 >>, << 777 >>, << 793, 782, 862, 802 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 18 | Next state: 16 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, << 135, 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, << 368, 373 >>, << 383 >>, <<>>, << 386 >>, << 421, 426, 429, 393, 456 >>, << 492 >>, << 649, 690, 763, 540, 736, 567, 530 >>, << 777 >>, << 793, 782, 862, 802 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 19 | Next state: 17 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, << 135, 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 421, 426, 429, 393, 456 >>, << 492 >>, << 649, 690, 763, 540, 736, 567, 530 >>, << 777 >>, << 793, 782, 862, 802 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 20 | Next state: 18 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, << 135, 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, << 426, 429, 456 >>, << 492 >>, << 649, 690, 763, 540, 736, 567, 530 >>, << 777 >>, << 793, 782, 862, 802 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 21 | Next state: 19 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, << 135, 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, << 426, 429, 456 >>, << 492 >>, << 649, 690, 763, 540, 736, 567, 530 >>, << 777 >>, << 782 >>, << 793 >>, << 862, 802 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 22 | Next state: 20 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, <<>>, << 135 >>, << 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, << 426, 429, 456 >>, << 492 >>, << 649, 690, 763, 540, 736, 567, 530 >>, << 777 >>, << 782 >>, << 793 >>, << 862, 802 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 23 | Next state: 21 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 58, 42 >>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, <<>>, << 135 >>, << 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, << 426, 429, 456 >>, << 492 >>, << 540, 567, 530 >>, << 649 >>, << 690, 763, 736 >>, << 777 >>, << 782 >>, << 793 >>, << 862, 802 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 24 | Next state: 22 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 42 >>, << 58 >>, <<>>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, <<>>, << 135 >>, << 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, << 426, 429, 456 >>, << 492 >>, << 540, 567, 530 >>, << 649 >>, << 690, 763, 736 >>, << 777 >>, << 782 >>, << 793 >>, << 862, 802 >>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 25 | Next state: 23 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 42 >>, << 58 >>, <<>>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, <<>>, << 135 >>, << 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, << 426, 429, 456 >>, << 492 >>, << 540, 567, 530 >>, << 649 >>, << 690, 763, 736 >>, << 777 >>, << 782 >>, << 793 >>, << 802 >>, << 862 >>, <<>>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 26 | Next state: 24 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 42 >>, << 58 >>, <<>>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, <<>>, << 135 >>, << 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, << 426, 429, 456 >>, << 492 >>, << 540, 567, 530 >>, << 649 >>, <<>>, << 690 >>, << 763, 736 >>, << 777 >>, << 782 >>, << 793 >>, << 802 >>, << 862 >>, <<>>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 27 | Next state: 25 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 42 >>, << 58 >>, <<>>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, <<>>, << 135 >>, << 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, << 426, 429, 456 >>, << 492 >>, << 530 >>, << 540 >>, << 567 >>, << 649 >>, <<>>, << 690 >>, << 763, 736 >>, << 777 >>, << 782 >>, << 793 >>, << 802 >>, << 862 >>, <<>>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 28 | Next state: 26 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 42 >>, << 58 >>, <<>>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, <<>>, << 135 >>, << 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, <<>>, << 426 >>, << 429, 456 >>, << 492 >>, << 530 >>, << 540 >>, << 567 >>, << 649 >>, <<>>, << 690 >>, << 763, 736 >>, << 777 >>, << 782 >>, << 793 >>, << 802 >>, << 862 >>, <<>>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 29 | Next state: 27 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 42 >>, << 58 >>, <<>>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, <<>>, << 135 >>, << 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, <<>>, << 426 >>, <<>>, << 429 >>, << 456 >>, << 492 >>, << 530 >>, << 540 >>, << 567 >>, << 649 >>, <<>>, << 690 >>, << 763, 736 >>, << 777 >>, << 782 >>, << 793 >>, << 802 >>, << 862 >>, <<>>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 30 | Next state: 28 [ output |-> "under construction", todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 42 >>, << 58 >>, <<>>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, <<>>, << 135 >>, << 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, <<>>, << 426 >>, <<>>, << 429 >>, << 456 >>, << 492 >>, << 530 >>, << 540 >>, << 567 >>, << 649 >>, <<>>, << 690 >>, << 736 >>, << 763 >>, <<>>, << 777 >>, << 782 >>, << 793 >>, << 802 >>, << 862 >>, <<>>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 31 | Next state: 29 [ output |-> << 0, 11, 22, 27, 42, 58, 59, 67, 69, 123, 135, 167, 172, 211, 229, 335, 362, 368, 373, 383, 386, 393, 421, 426, 429, 456, 492, 530, 540, 567, 649, 690, 736, 763, 777, 782, 793, 802, 862, 886, 915, 926, 929 >>, todo |-> << <<>>, << 0 >>, << 11 >>, << 22 >>, <<>>, << 27 >>, << 42 >>, << 58 >>, <<>>, << 59 >>, <<>>, << 67 >>, << 69 >>, << 123 >>, <<>>, << 135 >>, << 167 >>, << 172 >>, <<>>, << 211 >>, << 229 >>, << 335 >>, <<>>, << 362 >>, <<>>, << 368 >>, << 373 >>, << 383 >>, <<>>, << 386 >>, << 393 >>, << 421 >>, <<>>, << 426 >>, <<>>, << 429 >>, << 456 >>, << 492 >>, << 530 >>, << 540 >>, << 567 >>, << 649 >>, <<>>, << 690 >>, << 736 >>, << 763 >>, <<>>, << 777 >>, << 782 >>, << 793 >>, << 802 >>, << 862 >>, <<>>, << 886 >>, <<>>, << 915 >>, <<>>, << 926 >>, << 929 >> >> ] 32 | No state change after successful step 33 | MAIN DONE 34 | -------------------------------------------------------------------------------- /tests/regression/test9.exp: -------------------------------------------------------------------------------- 1 | Next state: 0 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> <<>> ] 2 | Next state: 1 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> <<>> ] 3 | Next state: 2 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 4 | Next state: 3 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 5 | Next state: 4 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 6 | Next state: 5 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 7 | Next state: 6 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red" >> ] 8 | Next state: 7 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red" >> ] 9 | Next state: 8 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 10 | Next state: 9 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 11 | Next state: 10 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 12 | Next state: 11 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 13 | Next state: 12 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 14 | Next state: 13 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 15 | Next state: 14 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 16 | Next state: 15 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 17 | Next state: 16 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue" >> ] 18 | Next state: 17 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue" >> ] 19 | Next state: 18 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue", "blue" >> ] 20 | Next state: 19 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue", "blue" >> ] 21 | Next state: 20 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue" >> ] 22 | Next state: 21 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red" >> ] 23 | Next state: 22 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red" >> ] 24 | Next state: 23 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 25 | Next state: 24 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 26 | Next state: 25 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 27 | Next state: 26 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 28 | Next state: 27 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 29 | Next state: 28 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 30 | Next state: 29 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 31 | Next state: 30 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "blue" >> ] 32 | Next state: 31 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "blue" >> ] 33 | Next state: 32 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue" >> ] 34 | Next state: 33 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue" >> ] 35 | Next state: 34 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue" >> ] 36 | Next state: 35 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue", "red" >> ] 37 | Next state: 36 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue", "red" >> ] 38 | Next state: 37 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red" >> ] 39 | Next state: 38 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red" >> ] 40 | Next state: 39 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red" >> ] 41 | Next state: 40 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red", "red" >> ] 42 | Next state: 41 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red", "red" >> ] 43 | Next state: 42 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "blue", "blue", "blue", "red", "red" >> ] 44 | Next state: 43 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "blue", "blue", "red", "red" >> ] 45 | Next state: 44 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 46 | Next state: 45 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 47 | Next state: 46 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 48 | Next state: 47 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 49 | Next state: 48 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 50 | Next state: 49 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red" >> ] 51 | Next state: 50 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red" >> ] 52 | Next state: 51 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 53 | Next state: 52 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 54 | Next state: 53 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 55 | Next state: 54 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 56 | Next state: 55 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 57 | Next state: 56 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red" >> ] 58 | Next state: 57 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue" >> ] 59 | Next state: 58 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue" >> ] 60 | Next state: 59 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue", "red" >> ] 61 | Next state: 60 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue", "red" >> ] 62 | Next state: 61 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue", "red" >> ] 63 | Next state: 62 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red" >> ] 64 | Next state: 63 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 65 | Next state: 64 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 66 | Next state: 65 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 67 | Next state: 66 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 68 | Next state: 67 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red", "red" >> ] 69 | Next state: 68 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red", "red" >> ] 70 | Next state: 69 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red", "red" >> ] 71 | Next state: 70 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red" >> ] 72 | Next state: 71 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red" >> ] 73 | Next state: 72 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red", "red" >> ] 74 | Next state: 73 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red", "red" >> ] 75 | Next state: 74 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red" >> ] 76 | Next state: 75 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red" >> ] 77 | Next state: 76 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red", "red" >> ] 78 | Next state: 77 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red", "red" >> ] 79 | Next state: 78 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red" >> ] 80 | Next state: 79 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red" >> ] 81 | Next state: 80 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red" >> ] 82 | Next state: 81 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red" >> ] 83 | Next state: 82 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue" >> ] 84 | Next state: 83 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue" >> ] 85 | Next state: 84 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue", "red" >> ] 86 | Next state: 85 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue", "red" >> ] 87 | Next state: 86 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "red", "red", "blue", "red" >> ] 88 | Next state: 87 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "red", "red", "blue", "red" >> ] 89 | Next state: 88 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "red", "red", "blue", "red" >> ] 90 | Next state: 89 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "red", "red", "blue", "red" >> ] 91 | Next state: 90 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "blue", "red" >> ] 92 | Next state: 91 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "blue", "red" >> ] 93 | Next state: 92 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "blue", "red", "red" >> ] 94 | Next state: 93 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "blue", "red", "red" >> ] 95 | Next state: 94 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "blue", "red", "red" >> ] 96 | Next state: 95 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "blue", "red", "red" >> ] 97 | Next state: 96 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red" >> ] 98 | Next state: 97 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red" >> ] 99 | Next state: 98 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue" >> ] 100 | Next state: 99 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue" >> ] 101 | Next state: 100 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue" >> ] 102 | -------------------------------------------------------------------------------- /tests/regression/test5.exp: -------------------------------------------------------------------------------- 1 | Initial context: [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> <<>> ] 2 | Next state: 0 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> <<>> ] 3 | Next state: 1 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 4 | Next state: 2 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 5 | Next state: 3 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 6 | Next state: 4 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 7 | Next state: 5 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red" >> ] 8 | Next state: 6 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red" >> ] 9 | Next state: 7 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 10 | Next state: 8 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 11 | Next state: 9 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 12 | Next state: 10 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 13 | Next state: 11 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 14 | Next state: 12 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 15 | Next state: 13 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 16 | Next state: 14 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 17 | Next state: 15 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue" >> ] 18 | Next state: 16 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue" >> ] 19 | Next state: 17 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue", "blue" >> ] 20 | Next state: 18 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue", "blue" >> ] 21 | Next state: 19 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue" >> ] 22 | Next state: 20 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red" >> ] 23 | Next state: 21 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red" >> ] 24 | Next state: 22 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 25 | Next state: 23 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 26 | Next state: 24 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 27 | Next state: 25 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 28 | Next state: 26 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 29 | Next state: 27 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 30 | Next state: 28 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 31 | Next state: 29 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "blue" >> ] 32 | Next state: 30 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "blue" >> ] 33 | Next state: 31 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue" >> ] 34 | Next state: 32 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue" >> ] 35 | Next state: 33 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue" >> ] 36 | Next state: 34 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue", "red" >> ] 37 | Next state: 35 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue", "red" >> ] 38 | Next state: 36 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red" >> ] 39 | Next state: 37 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red" >> ] 40 | Next state: 38 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red" >> ] 41 | Next state: 39 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red", "red" >> ] 42 | Next state: 40 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red", "red" >> ] 43 | Next state: 41 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "blue", "blue", "blue", "red", "red" >> ] 44 | Next state: 42 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "blue", "blue", "red", "red" >> ] 45 | Next state: 43 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 46 | Next state: 44 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 47 | Next state: 45 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 48 | Next state: 46 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 49 | Next state: 47 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 50 | Next state: 48 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red" >> ] 51 | Next state: 49 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red" >> ] 52 | Next state: 50 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 53 | Next state: 51 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 54 | Next state: 52 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 55 | Next state: 53 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 56 | Next state: 54 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 57 | Next state: 55 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red" >> ] 58 | Next state: 56 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue" >> ] 59 | Next state: 57 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue" >> ] 60 | Next state: 58 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue", "red" >> ] 61 | Next state: 59 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue", "red" >> ] 62 | Next state: 60 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue", "red" >> ] 63 | Next state: 61 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red" >> ] 64 | Next state: 62 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 65 | Next state: 63 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 66 | Next state: 64 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 67 | Next state: 65 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 68 | Next state: 66 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red", "red" >> ] 69 | Next state: 67 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red", "red" >> ] 70 | Next state: 68 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red", "red" >> ] 71 | Next state: 69 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red" >> ] 72 | Next state: 70 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red" >> ] 73 | Next state: 71 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red", "red" >> ] 74 | Next state: 72 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red", "red" >> ] 75 | Next state: 73 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red" >> ] 76 | Next state: 74 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red" >> ] 77 | Next state: 75 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red", "red" >> ] 78 | Next state: 76 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red", "red" >> ] 79 | Next state: 77 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red" >> ] 80 | Next state: 78 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red" >> ] 81 | Next state: 79 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red" >> ] 82 | Next state: 80 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red" >> ] 83 | Next state: 81 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue" >> ] 84 | Next state: 82 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue" >> ] 85 | Next state: 83 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue", "red" >> ] 86 | Next state: 84 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue", "red" >> ] 87 | Next state: 85 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "red", "red", "blue", "red" >> ] 88 | Next state: 86 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "red", "red", "blue", "red" >> ] 89 | Next state: 87 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "red", "red", "blue", "red" >> ] 90 | Next state: 88 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "red", "red", "blue", "red" >> ] 91 | Next state: 89 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "blue", "red" >> ] 92 | Next state: 90 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "blue", "red" >> ] 93 | Next state: 91 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "blue", "red", "red" >> ] 94 | Next state: 92 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "blue", "red", "red" >> ] 95 | Next state: 93 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "blue", "red", "red" >> ] 96 | Next state: 94 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "blue", "red", "red" >> ] 97 | Next state: 95 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red" >> ] 98 | Next state: 96 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red" >> ] 99 | Next state: 97 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue" >> ] 100 | Next state: 98 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue" >> ] 101 | Next state: 99 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue" >> ] 102 | MAIN DONE 103 | -------------------------------------------------------------------------------- /tests/regression/test6.exp: -------------------------------------------------------------------------------- 1 | Initial context: [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> <<>> ] 2 | Next state: 0 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> <<>> ] 3 | Next state: 1 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 4 | Next state: 2 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 5 | Next state: 3 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 6 | Next state: 4 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 7 | Next state: 5 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red" >> ] 8 | Next state: 6 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red" >> ] 9 | Next state: 7 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red" >> ] 10 | Next state: 8 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 11 | Next state: 9 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 12 | Next state: 10 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red" >> ] 13 | Next state: 11 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 14 | Next state: 12 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> <<>> ] 15 | Next state: 13 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 16 | Next state: 14 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue" >> ] 17 | Next state: 15 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue" >> ] 18 | Next state: 16 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue" >> ] 19 | Next state: 17 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue", "blue" >> ] 20 | Next state: 18 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "blue", "blue" >> ] 21 | Next state: 19 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue" >> ] 22 | Next state: 20 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red" >> ] 23 | Next state: 21 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red" >> ] 24 | Next state: 22 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 25 | Next state: 23 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 26 | Next state: 24 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 27 | Next state: 25 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 28 | Next state: 26 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 29 | Next state: 27 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 30 | Next state: 28 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 31 | Next state: 29 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "blue" >> ] 32 | Next state: 30 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "blue" >> ] 33 | Next state: 31 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue" >> ] 34 | Next state: 32 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue" >> ] 35 | Next state: 33 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue" >> ] 36 | Next state: 34 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue", "red" >> ] 37 | Next state: 35 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "blue", "blue", "red" >> ] 38 | Next state: 36 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red" >> ] 39 | Next state: 37 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red" >> ] 40 | Next state: 38 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red" >> ] 41 | Next state: 39 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red", "red" >> ] 42 | Next state: 40 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "blue", "blue", "red", "red" >> ] 43 | Next state: 41 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "blue", "blue", "blue", "red", "red" >> ] 44 | Next state: 42 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "blue", "blue", "red", "red" >> ] 45 | Next state: 43 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 46 | Next state: 44 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red" >> ] 47 | Next state: 45 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 48 | Next state: 46 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "blue", "blue", "red", "red", "blue" >> ] 49 | Next state: 47 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue" >> ] 50 | Next state: 48 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red" >> ] 51 | Next state: 49 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red" >> ] 52 | Next state: 50 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 53 | Next state: 51 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 54 | Next state: 52 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 55 | Next state: 53 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 56 | Next state: 54 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 57 | Next state: 55 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red" >> ] 58 | Next state: 56 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue" >> ] 59 | Next state: 57 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue" >> ] 60 | Next state: 58 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue", "red" >> ] 61 | Next state: 59 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue", "red" >> ] 62 | Next state: 60 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue", "red" >> ] 63 | Next state: 61 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red" >> ] 64 | Next state: 62 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 65 | Next state: 63 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 66 | Next state: 64 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue", "red", "red" >> ] 67 | Next state: 65 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red" >> ] 68 | Next state: 66 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red", "red" >> ] 69 | Next state: 67 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red", "red" >> ] 70 | Next state: 68 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], q |-> << "red", "red", "blue", "red", "red", "red" >> ] 71 | Next state: 69 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red" >> ] 72 | Next state: 70 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red" >> ] 73 | Next state: 71 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red", "red" >> ] 74 | Next state: 72 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "blue", "red", "red", "red", "red" >> ] 75 | Next state: 73 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red" >> ] 76 | Next state: 74 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red" >> ] 77 | Next state: 75 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red", "red" >> ] 78 | Next state: 76 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "blue", "red", "red", "red", "red", "red" >> ] 79 | Next state: 77 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red" >> ] 80 | Next state: 78 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red" >> ] 81 | Next state: 79 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red" >> ] 82 | Next state: 80 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red" >> ] 83 | Next state: 81 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue" >> ] 84 | Next state: 82 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue" >> ] 85 | Next state: 83 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue", "red" >> ] 86 | Next state: 84 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "blue" ], q |-> << "red", "red", "red", "red", "red", "red", "blue", "red" >> ] 87 | Next state: 85 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "red", "red", "blue", "red" >> ] 88 | Next state: 86 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "red", "red", "blue", "red" >> ] 89 | Next state: 87 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "red", "red", "blue", "red" >> ] 90 | Next state: 88 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "red", "red", "blue", "red" >> ] 91 | Next state: 89 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "blue", "red" >> ] 92 | Next state: 90 [ in |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "blue", "red" >> ] 93 | Next state: 91 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "red", "red", "blue", "red", "red" >> ] 94 | Next state: 92 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "blue", "red", "red" >> ] 95 | Next state: 93 [ in |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "blue", "red", "red" >> ] 96 | Next state: 94 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "red", "red", "blue", "red", "red" >> ] 97 | Next state: 95 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red" >> ] 98 | Next state: 96 [ in |-> [ ack |-> 0, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red" >> ] 99 | Next state: 97 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 1, val |-> "red" ], q |-> << "red", "blue", "red", "red", "blue" >> ] 100 | Next state: 98 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 1, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue" >> ] 101 | Next state: 99 [ in |-> [ ack |-> 1, rdy |-> 1, val |-> "blue" ], out |-> [ ack |-> 0, rdy |-> 0, val |-> "red" ], q |-> << "blue", "red", "red", "blue" >> ] 102 | MAIN DONE 103 | --------------------------------------------------------------------------------