rename Process to DataFlowGraph, de-static-ify some methods
[fleet.git] / src / edu / berkeley / fleet / dataflow / DataFlowGraph.java
1 package edu.berkeley.fleet.dataflow;
2 import edu.berkeley.fleet.loops.*;
3 import java.util.concurrent.Semaphore;
4 import java.util.*;
5 import java.net.*;
6 import edu.berkeley.fleet.two.*;
7 import edu.berkeley.fleet.api.*;
8 import edu.berkeley.fleet.fpga.*;
9 import edu.berkeley.fleet.api.Instruction.*;
10 import edu.berkeley.fleet.api.Instruction.Set;
11 import edu.berkeley.fleet.api.Instruction.Set.*;
12 import static edu.berkeley.fleet.api.Predicate.*;
13 import static edu.berkeley.fleet.util.BitManipulations.*;
14
15 // does peer.recvWord() have to honor the currently-set predicate?
16
17 // public class ReplaceNode extends Node { }
18 // public class CountMergeNode extends Node { }
19 // public class SortMergeNode extends Node { }
20 // public class FanOutNode extends Node { }
21 // public class MemoryNode extends Node { }
22 // public class DoneNode extends Node { }
23
24 public class DataFlowGraph {
25
26     public final Fleet    fleet;
27     public final ShipPool pool;
28
29     public DataFlowGraph(Fleet fleet) {
30         this(fleet, new ShipPool(fleet));
31     }
32     public DataFlowGraph(Fleet fleet, ShipPool pool) {
33         this.fleet = fleet;
34         this.pool  = pool;
35     }
36
37     public static int reset_count = 0;
38     public static HashSet<Dock> torpedoes = new HashSet<Dock>();
39
40     private HashSet<Node> nodes = new HashSet<Node>();
41
42     public void build(Context ctx) {
43         for(Node mod : nodes)
44             mod.build(ctx);
45     }
46     public void reset(Context ctx, int phase, Destination ackDestination) {
47         reset_count = 0;
48         torpedoes.clear();
49         for(Node mod : nodes)
50             mod.reset(ctx, phase, ackDestination);
51     }
52
53     public class Node {
54
55         void doReset(Context ctx, int phase, Dock dock, Port peer, Destination ackDestination, boolean peerUsed) {
56             if (dock.getShip().getType().equals("Debug")) return;
57
58             switch(phase) {
59
60                 // Phase 0: torpedo every output dock, put it in
61                 // collecting mode.  Cannot combine with phase 1,
62                 // because until output docks are in vacuum mode we
63                 // cannot be sure that the tokens to the input docks
64                 // will eventually succeed.  This may cause the
65                 // instructions sent after the tokens to back up into
66                 // the switch fabric.
67                 case 0: {
68                     if (!dock.isInputDock()) {
69                         torpedoes.add(dock);
70                         LoopFactory lf = new LoopFactory(ctx, dock, 1);
71                         lf.sendToken(ackDestination);
72                         lf = lf.makeNext(0);
73                         lf.abortLoopIfTorpedoPresent();
74                         lf.collectWord();
75                         reset_count++;
76                     }
77                     break;
78                 }
79
80                 // Phase 1: torpedo every input dock, put it in loopback mode
81                 case 1: {
82                     if (dock.isInputDock()) {
83                         torpedoes.add(dock);
84                         LoopFactory lf = new LoopFactory(ctx, dock, 1);
85                         lf.sendToken(ackDestination);
86
87                         // FIXME: this won't work right for ports that
88                         // get "shared" by two senders (for example,
89                         // inAddrRead1/2)
90
91                         if (peerUsed && peer!=null) {
92                             lf = lf.makeNext(0);
93                             lf.abortLoopIfTorpedoPresent();
94                             ((OutPort)peer).recvWord(lf);
95                             ((OutPort)peer).sendToken(lf);
96                         }
97                         reset_count++;
98                     }
99                     break;
100                 }
101
102                 // Phase 2: torpedo every output dock, have it absorb tokens
103                 case 2: {
104                     if (!dock.isInputDock()) {
105                         torpedoes.add(dock);
106                         LoopFactory lf = new LoopFactory(ctx, dock, 1);
107                         if (peer != null)
108                             for(int i=0; i<((InPort)peer).getTokensToAbsorb(); i++)
109                                 lf.recvToken();
110                         lf.sendToken(ackDestination);
111                         reset_count++;
112                     }
113                     break;
114                 }
115
116                 // Phase 3: torpedo every input dock, and we're done
117                 case 3: {
118                     if (dock.isInputDock()) {
119                         if (peerUsed && peer!=null) {
120                             torpedoes.add(dock);
121                         }
122                         LoopFactory lf = new LoopFactory(ctx, dock, 1);
123                         lf.sendToken(ackDestination);
124                         reset_count++;
125                     }
126                     break;
127                 }
128
129
130             }
131         }
132
133         public Node() {
134             DataFlowGraph.this.nodes.add(this);
135         }
136
137         private HashMap<String,Port> ports = new HashMap<String,Port>();
138
139         public InPort  getInPort(String name)  { return (InPort)ports.get(name); }
140         public OutPort getOutPort(String name) { return (OutPort)ports.get(name); }
141         
142         public void build(Context ctx) { for(Port p : ports.values()) p.build(ctx); }
143         public void reset(Context ctx, int phase, Destination ackDestination) {
144             for(Port p : ports.values()) p.reset(ctx, phase, ackDestination);
145         }
146
147         public abstract class Port {
148             public final String name;
149             public Port(String name) {
150                 this.name = name;
151                 if (Node.this.ports.get(name)!=null) throw new RuntimeException();
152                 Node.this.ports.put(name,this);
153             }
154             public abstract void build(Context ctx);
155             public abstract void reset(Context ctx, int phase, Destination ackDestination);
156         }
157
158         public abstract class InPort extends Port {
159             OutPort peer;
160             public InPort(String name) { super(name); }
161             public void connect(OutPort peer) {
162                 this.setPeer(peer);
163                 peer.setPeer(this);
164             }
165             public void setPeer(OutPort peer) {
166                 if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
167                 this.peer = peer;
168             }
169
170             /** this port's peer (an OutPort) invokes this to have "recvToken" or equivalent inserted */
171             public abstract void recvToken(LoopFactory loopfactory_at_output_dock);
172             /** this port's peer (an OutPort) invokes this to have "sendWord" or equivalent inserted */
173             public abstract void sendWord(LoopFactory loopfactory_at_output_dock);
174
175             public int getTokensToAbsorb() { return 0; }
176         }
177
178         public abstract class OutPort extends Port {
179             InPort peer;
180             public OutPort(String name) { super(name); }
181             public void connect(InPort peer) {
182                 this.setPeer(peer);
183                 peer.setPeer(this);
184             }
185             public void setPeer(InPort peer) {
186                 if (this.peer!=null) throw new RuntimeException("cannot call setPeer() twice");
187                 this.peer = peer;
188             }
189
190             /** this port's peer (an InPort) invokes this to have "sendToken" or equivalent inserted */
191             public abstract void sendToken(LoopFactory loopfactory_at_input_dock);
192             /** this port's peer (an InPort) invokes this to have "recvWord" or equivalent inserted */
193             public abstract void recvWord(LoopFactory loopfactory_at_input_dock);
194         }
195
196         public final class DockInPort extends InPort {
197             final Dock dock;
198             int count;
199             BitVector[] pattern;
200             public DockInPort(String name, Dock dock) { this(name, dock, 0); }
201             public DockInPort(String name, Dock dock, int count) { this(name, dock, count, new BitVector[] { null }); }
202             public DockInPort(String name, Dock dock, int count, BitVector[] pattern) {
203                 super(name);
204                 this.dock = dock;
205                 this.count = count;
206                 this.pattern = pattern;
207             }
208             public void recvToken(LoopFactory lf) { lf.recvToken(); }
209             public void sendWord(LoopFactory lf) { lf.sendWord(dock.getDataDestination()); }
210             public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
211             // number-in-flight is considered a property of the input dock in a pair
212             public int getInflight() { return 4; }
213             //public int getInflight() { return 1; }
214             public int getTokensToAbsorb() { return getInflight(); }
215             private boolean peerUsed() {
216                 if (peer==null) return false;
217                 for(int i=0; i<pattern.length; i++) if (pattern[i]==null) return true;
218                 return false;
219             }
220             public void reset(Context ctx, int phase, Destination ackDestination) {
221                 doReset(ctx, phase, dock, peer, ackDestination, peerUsed());
222             }
223             protected void build(Context ctx, LoopFactory lf) {
224                 int inflight = (count != 0 && count < getInflight()) ? count : getInflight();
225
226                 if (peer!=null)
227                     for(int i=0; i<inflight; i++) peer.sendToken(lf);
228
229                 lf = lf.makeNext(count, true);
230                 for(int i=0; i<pattern.length; i++) {
231                     if (pattern[i]==null) {
232                         if (peer!=null) {
233                             lf.abortLoopIfTorpedoPresent();
234                             peer.recvWord(lf);
235                             peer.sendToken(lf);
236                             lf.deliver();
237                         } else {
238                             lf.interruptibleNop();
239                         }
240                     } else {
241                         lf.literal(pattern[i]);
242                         lf.abortLoopIfTorpedoPresent();
243                         lf.deliver();
244                     }
245                 }
246
247                 if (count!=0) {
248                     // "torpedoable nop" to keep the dock in a receptive state
249                     lf.abortLoopIfTorpedoPresent();
250                     lf.recvToken();
251                 }
252             }
253             public BitVector getConstant(String constantName) {
254                 return dock.getConstant(constantName);
255             }
256         }
257
258         public /*final*/ class DockOutPort extends OutPort {
259             public final Dock dock;
260             public final int count;
261             public DockOutPort(String name, Dock dock) { this(name, dock, 0); }
262             public DockOutPort(String name, Dock dock, int count) { super(name); this.dock = dock; this.count = count; }
263             public void sendToken(LoopFactory lf) { lf.sendToken(dock.getDataDestination()); }
264             public void recvWord(LoopFactory lf) { lf.recvWord(); }
265             public void build(Context ctx) { build(ctx, new LoopFactory(ctx, dock, 1)); }
266             protected void build(Context ctx, LoopFactory lf) {
267                 if (peer==null) return;
268                 lf = lf.makeNext(count);
269                 lf.abortLoopIfTorpedoPresent();
270                 peer.recvToken(lf);
271                 lf.collectWord();
272                 peer.sendWord(lf);
273             }
274             public void reset(Context ctx, int phase, Destination ackDestination) {
275                 doReset(ctx, phase, dock, peer, ackDestination, true);
276             }
277         }
278     }
279
280     private BitVector bv(long l) { return new BitVector(/*FIXME fleet.getWordWidth()*/37).set(l); }
281     private BitVector[] bv(long[] l) {
282         BitVector[] ret = new BitVector[l.length];
283         for(int i=0; i<ret.length; i++) ret[i] = bv(l[i]);
284         return ret;
285     }
286
287     /**
288      *  Deliver the constant at out forever.  Flow control in<->out is
289      *  maintained, but out is not flow-controlled, so be sure
290      *  that every datum sent there is consumed synchronously wiht
291      *  data items sent to out.
292      */
293     public class ForeverNode extends Node {
294         private BitVector bv;
295         public final OutPort out = new OutPort("out") {
296                 public void sendToken(LoopFactory lf) { }
297                 public void recvWord(LoopFactory lf) { }
298                 public void build(Context ctx) { }
299                 public void reset(Context ctx, int phase, Destination ackDestination) { }
300                 public void setPeer(InPort peer) {
301                     this.peer = peer;
302                     DockInPort pip = ((DockInPort)peer);
303                     for(int i=0; i<pip.pattern.length; i++) {
304                         if (pip.pattern[i]==null)
305                             pip.pattern[i] = bv;
306                     }
307                 }
308             };
309         public ForeverNode(long l) { this(new BitVector(fleet.getWordWidth()).set(l)); }
310         public ForeverNode(final BitVector bv) { this.bv = bv; }
311     }
312
313     public class OnceNode extends Node {
314         private BitVector bv;
315         public final OutPort out = new OutPort("out") {
316                 public void sendToken(LoopFactory lf) { }
317                 public void recvWord(LoopFactory lf) { }
318                 public void build(Context ctx) { }
319                 public void reset(Context ctx, int phase, Destination ackDestination) { }
320                 public void setPeer(InPort peer) {
321                     this.peer = peer;
322                     DockInPort pip = ((DockInPort)peer);
323                     BitVector[] pip_pattern = pip.pattern;
324                     BitVector[] temp = new BitVector[pip_pattern.length * 2];
325                     int j = 0;
326                     int i = 0;
327                     boolean done = false;
328                     // FIXME: if peer.count is already 1, this gets simpler and different
329                     for(i=0; i<temp.length; i++) {
330                         if (pip_pattern[j] != null) {
331                             temp[i] = pip_pattern[j];
332                         } else {
333                             if (done) break;
334                             done = true;
335                             temp[i] = bv;
336                         }
337                         j++;
338                         if (j >= pip_pattern.length) j = 0;
339                     }
340                     pip.pattern = new BitVector[i];
341                     System.arraycopy(temp, 0, pip.pattern, 0, i);
342                     pip.count = 1;
343                 }
344             };
345         public OnceNode(long l) { this(new BitVector(fleet.getWordWidth()).set(l)); }
346         public OnceNode(final BitVector bv) { this.bv = bv; }
347     }
348
349     public class DebugNode extends Node {
350         public final Ship ship = pool.allocateShip("Debug");
351         public final InPort in = new DockInPort("in", ship.getDock("in"));
352         // NOTE: shutdown needs to treat this specially
353         public DebugNode() { }
354     }
355
356     public class UnPunctuatorNode extends Node {
357         private final Ship    ship  = pool.allocateShip("Counter");
358         public  final OutPort out   = new DockOutPort("out", ship.getDock("out"));
359         public  final InPort  val   = new DockInPort("in1",  ship.getDock("in1"));
360         public  final InPort  count = new DockInPort("in2",  ship.getDock("in2"), 0, new BitVector[] { null, bv(1) });
361         public  final InPort  op    = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
362                 ship.getDock("inOp").getConstant("PASS_C2_V1"),
363                 ship.getDock("inOp").getConstant("DROP_C2_V1") } );
364         public UnPunctuatorNode() { }
365     }
366
367     public class PunctuatorNode extends Node {
368         private final long    punc;
369         private final Ship    ship  = pool.allocateShip("Counter");
370         public  final OutPort out   = new DockOutPort("out", ship.getDock("out"));
371         public  final InPort  val   = new DockInPort("in1",  ship.getDock("in1"));
372         public  final InPort  op    = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
373                 ship.getDock("inOp").getConstant("PASS_C2_V1"),
374                 ship.getDock("inOp").getConstant("PASS_C2_V2") } );
375         public  final InPort  count;
376         public PunctuatorNode(long punc) {
377             this.punc = punc;
378             this.count = new DockInPort("in2",  ship.getDock("in2"), 0, new BitVector[] { null, bv(1), bv(punc) });
379         }
380     }
381
382     public class AluNode extends Node {
383         public final Ship    ship = pool.allocateShip("Alu");
384         public final InPort  in1 = new DockInPort("in1",  ship.getDock("in1"));
385         public final InPort  in2 = new DockInPort("in2",  ship.getDock("in2"));
386         public final InPort  inOp = new DockInPort("inOp", ship.getDock("inOp"));
387         public final OutPort out  = new DockOutPort("out", ship.getDock("out"));
388         public AluNode() { }
389     }
390
391     public class DownCounterNode extends Node {
392         public final Ship    ship  = pool.allocateShip("Counter");
393         public final InPort  start = new DockInPort("in1",  ship.getDock("in1"));
394         public final InPort  incr  = new DockInPort("in2",  ship.getDock("in2"));
395         public final InPort  inOp  = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
396                 ship.getDock("inOp").getConstant("COUNT") });
397         public final OutPort out   = new DockOutPort("out", ship.getDock("out"));
398         public DownCounterNode() { }
399     }
400
401     public class RepeatNode extends Node {
402         public final Ship    ship   = pool.allocateShip("Counter");
403         public final InPort  count  = new DockInPort("in1",  ship.getDock("in1"));
404         public final InPort  val    = new DockInPort("in2",  ship.getDock("in2"));
405         public final InPort  inOP   = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
406                 ship.getDock("inOp").getConstant("REPEAT_C1_V2") });
407         public final OutPort out    = new DockOutPort("out", ship.getDock("out"));
408         public RepeatNode() { }
409     }
410
411     public class SortedMergeNode extends Node {
412         public final Ship    ship = pool.allocateShip("Alu");
413         public final InPort  in1  = new DockInPort("in1",  ship.getDock("in1"));
414         public final InPort  in2  = new DockInPort("in2",  ship.getDock("in2"));
415         public final InPort  inOp = new DockInPort("inOp", ship.getDock("inOp"), 0, new BitVector[] {
416                 ship.getDock("inOp").getConstant("MAXMERGE") });
417         public final OutPort out  = new DockOutPort("out", ship.getDock("out"));
418         public SortedMergeNode() { }
419     }
420
421     public class MemoryNode extends Node {
422         public final Ship    ship;
423         public final InPort  inCBD;
424         public final InPort  inAddrRead1;
425         public final InPort  inAddrRead2;
426         public final InPort  inAddrWrite;
427         public final InPort  inDataWrite;
428         public final OutPort outRead1;
429         public final OutPort outRead2;
430         public final OutPort outWrite;
431         public MemoryNode(Ship memoryShip) {
432             this.ship = memoryShip;
433             this.inCBD        = ship.getType().equals("Memory") ? new DockInPort("inCBD", ship.getDock("inCBD")) : null;
434             this.inAddrWrite  = new DockInPort("inAddrWrite", ship.getDock("inAddrWrite"));
435             this.inDataWrite  = new DockInPort("inDataWrite", ship.getDock("inDataWrite"));
436             this.inAddrRead1  = new InPort("inAddrRead1") {
437                     public void recvToken(LoopFactory lf) { lf.recvToken(); }
438                     public void sendWord(LoopFactory lf) { lf.sendWord(ship.getDock("inAddrRead").getDataDestination(), new BitVector(1).set(0)); }
439                     public void build(Context ctx) { }
440                     public int getTokensToAbsorb() { return outRead1.peer.getTokensToAbsorb(); }
441                     public void reset(Context ctx, int phase, Destination ackDestination) {
442                         doReset(ctx, phase, ship.getDock("inAddrRead"), null, ackDestination, false);
443                     }
444                 };
445             this.inAddrRead2  = new InPort("inAddrRead2") {
446                     public void recvToken(LoopFactory lf) { lf.recvToken(); }
447                     public void sendWord(LoopFactory lf) { lf.sendWord(ship.getDock("inAddrRead").getDataDestination(), new BitVector(1).set(1)); }
448                     public void build(Context ctx) { }
449                     public int getTokensToAbsorb() { return outRead2.peer.getTokensToAbsorb(); }
450                     public void reset(Context ctx, int phase, Destination ackDestination) { }
451                 };
452             this.outRead1 = new OutPort("outRead1") {
453                     public void sendToken(LoopFactory lf) { inAddrRead1.peer.sendToken(lf); }
454                     public void recvWord(LoopFactory lf) { lf.recvWord(); }
455                     public void build(Context ctx) { }
456                     public void reset(Context ctx, int phase, Destination ackDestination) { }
457                 };
458             this.outRead2 = new OutPort("outRead2") {
459                     public void sendToken(LoopFactory lf) { inAddrRead2.peer.sendToken(lf); }
460                     public void recvWord(LoopFactory lf) { lf.recvWord(); }
461                     public void build(Context ctx) { }
462                     public void reset(Context ctx, int phase, Destination ackDestination) { }
463                 };
464             this.outWrite = new DockOutPort("out", ship.getDock("out")) {
465                     protected void build(Context ctx, LoopFactory lf) {
466                         lf = lf.makeNext(0);
467                         lf.abortLoopIfTorpedoPresent();
468                         lf.collectWord();
469                         
470                         lf.setFlags(FlagFunction.ZERO, FlagFunction.ZERO.add(FlagC));
471                         if (this.peer != null) {
472                             lf.setPredicate(Predicate.FlagB);
473                             lf.literal(77);
474                             lf.abortLoopIfTorpedoPresent();
475                             this.peer.recvToken(lf);
476                             this.peer.sendWord(lf);
477                         }
478                         
479                         lf.setPredicate(Predicate.NotFlagB);
480                         lf.abortLoopIfTorpedoPresent();
481                         lf.recvToken();
482                         lf.setFlags(FlagFunction.ZERO.add(NotFlagC).add(FlagB), FlagFunction.ZERO.add(FlagC).add(FlagB));
483                         if (outRead1.peer != null) {
484                             lf.setPredicate(Predicate.NotFlagB);
485                             outRead1.peer.sendWord(lf);
486                         }
487                         if (outRead2.peer != null) {
488                             lf.setPredicate(Predicate.NotFlagA);
489                             outRead2.peer.sendWord(lf);
490                         }
491                         lf.setPredicate(null);
492                     }
493                 };
494         }
495         public void build(Context ctx) {
496             super.build(ctx);
497             LoopFactory lf;
498
499             lf = new LoopFactory(ctx, ship.getDock("inAddrRead"), 0);
500             lf.abortLoopIfTorpedoPresent();
501             lf.recvWord();
502             lf.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
503             lf.setPredicate(Predicate.NotFlagA);
504             lf.sendToken(ship.getDock("out").getDataDestination(), new BitVector(1).set(0));
505             lf.setPredicate(Predicate.FlagA);
506             lf.sendToken(ship.getDock("out").getDataDestination(), new BitVector(1).set(1));
507             lf.setPredicate(null);
508             lf.deliver();
509         }
510     }
511
512     public static void main(String[] s) throws Exception {
513         Fleet fleet = new Fpga();
514         //Fleet fleet = new Interpreter(false);
515
516         Random random = new Random(System.currentTimeMillis());
517         long[] vals = new long[256];
518         for(int i=0; i<vals.length; i++) {
519             vals[i] = Math.abs(random.nextInt());
520         }
521
522         Ship mem1 = fleet.getShip("Memory", 0);
523         Ship mem2 = fleet.getShip("Memory", 1);
524         //Ship mem2 = fleet.getShip("DDR2", 0);
525
526         FleetProcess fp;
527         int stride = 1;
528         fp = null;
529
530         fp = fleet.run(new Instruction[0]);
531         MemoryUtils.writeMem(fp, mem1, 0, vals);
532         int vals_length = vals.length;
533
534         // Disable readback/writeback inside the loop
535         vals = null;
536
537         while(stride < vals_length) {
538             
539             // reset the FleetProcess
540             //fp.terminate(); fp = null;
541
542             System.out.println("stride " + stride);
543
544             // if we reset the FleetProcess, restart it
545             if (fp==null) fp = fleet.run(new Instruction[0]);
546
547             // do the mergeSort
548             vals = mergeSort(fp, fleet, vals, vals_length, stride, mem1, mem2);
549
550             // verify the cleanup
551             //CleanupUtils.verifyClean(fp);
552
553             Ship mem = mem1; mem1=mem2; mem2=mem;
554
555             stride = stride * 2;
556             System.out.println();
557         }
558
559         BitVector[] bvs = new BitVector[vals_length];
560         MemoryUtils.readMem(fp, mem1, 0, bvs);
561         System.out.println("results:");
562         for(int i=0; i<vals_length; i++)
563             System.out.println(bvs[i].toLong());
564     }
565
566
567     public static long[] mergeSort(FleetProcess fp, Fleet fleet,
568                                    long[] vals, int vals_length, int stride_length,
569                                    Ship memoryShip1, Ship memoryShip2) throws Exception {
570
571         if (vals != null) {
572             BitVector[] mem = new BitVector[vals_length];
573             for(int i=0; i<mem.length; i++) mem[i] = new BitVector(fleet.getWordWidth()).set(vals[i]);
574             MemoryUtils.writeMem(fp, memoryShip1, 0, mem);
575         }
576
577         //////////////////////////////////////////////////////////////////////////////
578
579         DataFlowGraph proc = new DataFlowGraph(fleet);
580         DebugNode dm = proc.new DebugNode();
581
582         int end_of_data = vals_length;
583         int num_strides = end_of_data / (stride_length * 2);
584
585         MemoryNode mm  = proc.new MemoryNode(memoryShip1);
586         SortedMergeNode sm = proc.new SortedMergeNode();
587
588         // So far: we have four spare Counter ships; one can be used for resetting
589         for(int i=0; i<2; i++) {
590
591             DownCounterNode c0 = proc.new DownCounterNode();
592             DownCounterNode c1 = proc.new DownCounterNode();
593
594             c0.start.connect(proc.new ForeverNode(stride_length).out);
595             c0.incr.connect(proc.new ForeverNode(1).out);
596
597             c1.start.connect(proc.new OnceNode(end_of_data + i*stride_length).out);
598             c1.incr.connect(proc.new OnceNode(stride_length*2).out);
599
600             RepeatNode r1 = proc.new RepeatNode();
601             r1.val.connect(c1.out);
602             r1.count.connect(proc.new ForeverNode(stride_length).out);
603
604             AluNode alu = proc.new AluNode();
605             alu.in1.connect(r1.out);
606             alu.in2.connect(c0.out);
607             alu.inOp.connect(proc.new ForeverNode(((Node.DockInPort)alu.inOp).getConstant("ADD")).out);
608             alu.out.connect(i==0 ? mm.inAddrRead1 : mm.inAddrRead2);
609
610             PunctuatorNode punc = proc.new PunctuatorNode(-1);
611             punc.count.connect(proc.new ForeverNode(stride_length).out);
612             punc.val.connect(i==0 ? mm.outRead1 : mm.outRead2);
613             punc.out.connect(i==0 ? sm.in1 : sm.in2);
614         }
615
616         UnPunctuatorNode unpunc = proc.new UnPunctuatorNode();
617         unpunc.val.connect(sm.out);
618         unpunc.count.connect(proc.new ForeverNode(2*stride_length).out);
619
620         DownCounterNode cw = proc.new DownCounterNode();
621         cw.start.connect(proc.new OnceNode(end_of_data).out);
622         cw.incr.connect(proc.new OnceNode(1).out);
623
624         MemoryNode mm2 = proc.new MemoryNode(memoryShip2);
625         mm2.inAddrWrite.connect(cw.out);
626         mm2.inDataWrite.connect(unpunc.out);
627         mm2.outWrite.connect(dm.in);
628
629         //////////////////////////////////////////////////////////////////////////////
630
631         Context ctx = new Context(fp.getFleet());
632         ctx.setAutoflush(true);
633
634         ArrayList<Instruction> ai = new ArrayList<Instruction>();
635         proc.build(ctx);
636         ctx.emit(ai);
637         for(Instruction ins : ai) {
638             //System.out.println(ins);
639             fp.sendInstruction(ins);
640         }
641         fp.flush();
642
643         for(int i=0; i<vals_length; i++) {
644             System.out.print("\rreading back... " + i+"/"+vals_length+"  ");
645             BitVector rec = fp.recvWord();
646             System.out.print(" (prev result: " + rec + " = " + rec.toLong() + ")");
647         }
648         System.out.println("\rdone.                                                                    ");
649
650         //if (true) return ret;
651
652         Context ctx2 = new Context(fp.getFleet());
653         Dock debugIn = fleet.getShip("Debug",0).getDock("in");
654         Dock fred = debugIn;
655         fp.sendToken(debugIn.getInstructionDestination());
656         fp.flush();
657
658         LoopFactory lf = new LoopFactory(ctx2, debugIn, 0);
659         lf.literal(0);
660         lf.abortLoopIfTorpedoPresent();
661         lf.recvToken();
662         lf.deliver();
663
664         ctx2.dispatch(fp);
665         fp.flush();
666
667         int count = 0;
668
669         Ship counter = proc.pool.allocateShip("Counter");
670
671         for(int phase=0; phase<=3; phase++) {
672             System.out.println("== phase "+phase+" ==================================================================");
673             ctx2 = new Context(fp.getFleet());
674
675             Destination ackDestination = counter.getDock("in2").getDataDestination();
676             proc.reset(ctx2, phase, ackDestination);
677
678             Context ctx3 = new Context(fp.getFleet());
679             lf = new LoopFactory(ctx3, counter.getDock("inOp"), 1);
680             lf.literal("DROP_C1_V2");
681             lf.deliver();
682             lf.literal(5);
683             lf.deliver();
684             lf = new LoopFactory(ctx3, counter.getDock("in1"), 1);
685             lf.literal(reset_count-1);
686             lf.deliver();
687             lf.literal(1);
688             lf.deliver();
689             lf = new LoopFactory(ctx3, counter.getDock("in2"), 0);
690             lf.abortLoopIfTorpedoPresent();
691             lf.recvWord();
692             lf.deliver();
693             lf = new LoopFactory(ctx3, counter.getDock("out"), 1);
694             lf.collectWord();
695             lf.sendToken(counter.getDock("in2").getInstructionDestination());  // HACK: we don't check to make sure this hits
696             lf.sendToken(debugIn.getDataDestination());
697             ctx3.dispatch(fp);  // HACK: we don't check to make sure that this is "firmly in place"
698
699             for(Dock dock : torpedoes) fp.sendToken(dock.getInstructionDestination());
700             ctx2.dispatch(fp);
701             fp.flush();
702             System.out.println("flushed");
703
704             fp.recvWord();
705             System.out.println("phase done");
706
707             System.out.println();
708         }
709
710         fp.sendToken(debugIn.getInstructionDestination());
711         fp.flush();
712
713         //System.out.println("verifying cleanup:");
714         //CleanupUtils.verifyClean(fp);
715
716         System.out.println("reading back:");
717         long[] ret = null;
718         if (vals != null) {
719             ret = new long[vals_length];
720             BitVector[] mem = new BitVector[vals_length];
721             MemoryUtils.readMem(fp, memoryShip2, 0, mem);
722             for(int i=0; i<ret.length; i++) ret[i] = mem[i].toLong();
723         }
724         return ret;
725     }
726
727     private BitVector[] longsToBitVectors(long[] initialValues) {
728         BitVector[] bv = new BitVector[initialValues.length];
729         for(int i=0; i<initialValues.length; i++)
730             bv[i] = new BitVector(fleet.getWordWidth()).set(initialValues[i]);
731         return bv;
732     }
733 }
734
735