// bubblesort.fleet // Author: Thomas Kho #import edu.berkeley.fleet.ships // 20 elements in memory #memory { 1, 2, 6, 1, 3, 9, 4, 4, 7, 1, 9, 4, 7, 6, 1, 2, 3, 0, 9, 3 } #ship memread : MemoryReadShip // ports: addr, stride, count, data, done #ship memwrite : MemoryWriteShip // ports: addr, stride, count, data, done #ship halt : HaltShip // ports: in #ship fetch : FetchShip // ports: codebag, release, revoke, done #ship tokensource : TokenSourceShip // ports: out #ship bitbucket : BitBucketShip // ports: token, data #ship debug : DebugShip // ports: token, data #ship counter : HomeworkCounter // ports: load, zero, positive, ask #ship itercnt : HomeworkCounter // ports: load, zero, positive, ask #ship max : ArithmeticShip // ports: A, B, cmd, out #ship min : ArithmeticShip // ports: A, B, cmd, out #ship dup1 : DuplicatorShip // ports: in, out1, out2, out3, out4 #ship dup2 : DuplicatorShip // ports: in, out1, out2, out3, out4 #ship tokenfifo : TokenFifo // ports: in, out #ship donecodebag : FifoShip // ports: in, out #ship nextcodebag : FifoShip // ports: in, out #ship exitcodebag : FifoShip // ports: in, out // first, load itercnt counter { fetch.done -> bitbucket.token move+ack itercnt.load -> fetch.release itercnt.load -[*]-> () itercnt.positive -[*]-> nextcodebag.out itercnt.zero -> exitcodebag.out // use tokens from itercnt to trigger delivery of the correct codebag triggered move nextcodebag.out -[*]-> fetch.codebag triggered move exitcodebag.out -[*]-> fetch.codebag CLEANUP -> exitcodebag.in FETCH_NEXT -> fetch.codebag 19 -> itercnt.load } -> fetch.codebag nop+ack itercnt.load -> fetch.release FETCH_NEXT: { // itercnt loaded fetch.done -> bitbucket.token LOOP_BODY -> nextcodebag.in tokensource.out -> itercnt.ask tokensource.out -> fetch.release } LOOP_BODY: { fetch.done -> bitbucket.token // donecodebag.in is called after one iteration of sort FETCH_NEXT -> donecodebag.in tokensource.out -> fetch.release SORT_ONCE -> fetch.codebag } CLEANUP: { fetch.done -> bitbucket.token nop+ack exitcodebag.out -> tokenfifo.in nop+ack nextcodebag.out -> tokenfifo.in nop+ack itercnt.positive -> tokenfifo.in nextcodebag.out -> bitbucket.data tokenfifo.out -[2]-> bitbucket.token tokenfifo.out -> halt.in } SORT_ONCE: { fetch.done -> bitbucket.token 0 -> memread.addr 1 -> memread.stride 20 -> memread.count memread.done -> bitbucket.token // in-place sorting 0 -> memwrite.addr 1 -> memwrite.stride 20 -> memwrite.count memwrite.done -> bitbucket.token // clear standing moves at inboxes that will ack nop+ack dup1.in -> tokenfifo.in nop+ack dup2.in -> tokenfifo.in nop+ack max.A -> tokenfifo.in nop+ack max.B -> tokenfifo.in nop+ack max.cmd -> tokenfifo.in nop+ack min.A -> tokenfifo.in nop+ack min.B -> tokenfifo.in nop+ack min.cmd -> tokenfifo.in nop+ack memwrite.data -> tokenfifo.in nop+ack counter.load -> tokenfifo.in tokenfifo.out -[9]-> bitbucket.token tokenfifo.out -> fetch.release { fetch.done -> bitbucket.token move+ack counter.load -> fetch.release counter.load -[*]-> () // restore standing move 19 -> counter.load // load N - 1 into counter { // on counter load, seed pipeline fetch.done -> bitbucket.token tokensource.out -[3]-> counter.ask } -> fetch.codebag // send first memread.data to dup2.in memread.data -> dup2.in // counting pipeline: min.out -> memwrite.data triggered move min.out -[*]-> memwrite.data accept+ack memwrite.data -[*]-> counter.ask counter.positive -[*]-> min.out // standing commands on min, max ships copy min.cmd -[*]-> () "MIN ZERO ZERO" -> min.cmd copy max.cmd -[*]-> () "MAX ZERO ZERO" -> max.cmd // pipelines: dup1 -> max, dup2 -> max, dup1 -> min, dup2 -> min triggered move dup1.out1 -[*]-> max.A accept+ack max.A -[*]-> dup1.out1 triggered move dup2.out1 -[*]-> max.B accept+ack max.B -[*]-> dup2.out1 triggered move dup1.out2 -[*]-> min.A accept+ack min.A -[*]-> dup1.out2 triggered move dup2.out2 -[*]-> min.B accept+ack min.B -[*]-> dup2.out2 // pipeline: max.out -> dup2.in triggered move max.out -[*]-> dup2.in accept+ack dup2.in -[*]-> max.out // pipeline: memread.data -> dup1.in triggered move memread.data -[*]-> dup1.in accept+ack dup1.in -[*]-> memread.data // seed the above 6 pipelines tokensource.out -[3]-> dup1.out1 tokensource.out -[3]-> dup1.out2 tokensource.out -[3]-> dup2.out1 tokensource.out -[3]-> dup2.out2 tokensource.out -[3]-> memread.data tokensource.out -[2]-> max.out // also seeded with first data // ignore dup[12].out[03] dup1.out3 -[*]-> bitbucket.data dup1.out0 -[*]-> bitbucket.data dup2.out3 -[*]-> bitbucket.data dup2.out0 -[*]-> bitbucket.data // setup exit condition counter.zero -[2]-> bitbucket.token counter.zero -> fetch.release { // after N-1 writes fetch.done -> bitbucket.token // once we're done with N-1 writes, we can flush the last one // by comparing with MAXINT 999 -> dup1.in tokensource.out -> min.out counter.zero -> fetch.release // trigger next codebag } -> fetch.codebag { // cleanup codebag fetch.done -> bitbucket.token // clear outbox standing moves nop+ack dup1.out0 -> tokenfifo.in nop+ack dup1.out3 -> tokenfifo.in nop+ack dup2.out0 -> tokenfifo.in nop+ack dup2.out3 -> tokenfifo.in nop+ack counter.positive -> tokenfifo.in nop+ack min.out -> tokenfifo.in // get rid of tokens triggered nop+ack memread.data -[4]-> tokenfifo.in // 3 + flush triggered nop+ack max.out -[3]-> tokenfifo.in triggered nop+ack dup1.out1 -[3]-> tokenfifo.in triggered nop+ack dup1.out2 -[3]-> tokenfifo.in triggered nop+ack dup2.out1 -[3]-> tokenfifo.in triggered nop+ack dup2.out2 -[3]-> tokenfifo.in // this, paired with MAXINT at port B, will kill standing copy 0 -> max.A 0 -> min.A max.out -> bitbucket.data min.out -> bitbucket.data // restore unacked inbox standing moves nop+ack memwrite.data -> tokenfifo.in memwrite.data -[*]-> () nop+ack dup1.in -> tokenfifo.in dup1.in -[*]-> () nop+ack dup2.in -> tokenfifo.in dup2.in -[*]-> () nop+ack max.A -> tokenfifo.in max.A -[*]-> () nop+ack min.A -> tokenfifo.in min.A -[*]-> () nop+ack max.B -> tokenfifo.in max.B -[*]-> () nop+ack min.B -> tokenfifo.in min.B -[*]-> () nop+ack max.cmd -> tokenfifo.in max.cmd -[*]-> () nop+ack min.cmd -> tokenfifo.in min.cmd -[*]-> () tokenfifo.out -[33]-> bitbucket.token tokenfifo.out -> fetch.release } -> fetch.codebag { fetch.done -> bitbucket.token // standing copy is gone, so get rid of this last cmd 0 -> max.A 0 -> min.A 0 -> max.B 0 -> min.B // probably lax on the sequencing here max.out -> bitbucket.data min.out -> bitbucket.data // "function calls" return with a continuation tokensource.out -> fetch.release donecodebag.out -> fetch.codebag } -> fetch.codebag } -> fetch.codebag }