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