take both xo/yo from center column when using XLUT (YLUT behavior unchanged)
[slipway.git] / src / edu / berkeley / slipway / AsyncPaperDemo.java
1 package edu.berkeley.slipway;
2
3 import edu.berkeley.slipway.*;
4 import com.atmel.fpslic.*;
5 import static com.atmel.fpslic.FpslicConstants.*;
6 import static com.atmel.fpslic.FpslicUtil.*;
7 import edu.berkeley.slipway.gui.*;
8 import java.awt.*;
9 import java.awt.event.*;
10 import java.awt.color.*;
11 import org.ibex.util.*;
12 import java.io.*;
13 import java.util.*;
14 import gnu.io.*;
15
16 public class AsyncPaperDemo {
17
18     FtdiBoard fpslic;
19
20     public AsyncPaperDemo() throws Exception {
21         fpslic = new FtdiBoard();
22     }
23
24     Fpslic.Cell start;
25     public void main(String[] s) throws Exception {
26
27         //turnOnLeds();
28         setupScanCell();
29
30         //runGui(24, 24);
31
32         for(int i=0; i<255; i++)
33             fpslic.readCount();
34
35         //System.in.read();
36         for(int i=0; i<400; i+=2) {
37             go(i);
38         }
39         //System.out.println("done");
40
41     }
42
43     public void go(int size) throws Exception {
44         start = fpslic.cell(20, 21);
45         int rsize = size-createPipeline(start, true, size-4, false);
46         System.out.println("actual size => " + rsize);
47         pipe(start.west().north(), start.west(), new int[] { NE, EAST, SW, SOUTH });
48
49         Fpslic.Cell div = start.east();
50         while(true) {
51             divider(div);
52             if (div.south()==null || div.south().south()==null) break;
53             div = div.south().south();
54         }
55         div = div.south().east();
56         div.east().yo(div);
57         //fpslic.cell(23,0).yo(fpslic.cell(22,0));
58         fpslic.cell(21,22).yo(fpslic.cell(20,22));
59         fpslic.cell(21,22).xo(fpslic.cell(20,22));
60
61         reconfigTopLeft();
62         reconfigTopRight();
63         fpslic.flush();
64
65         String sizes = rsize+"";
66         while(sizes.length()<3) sizes = "0"+sizes;
67         String fname = "data/size"+sizes+".csv";
68         if (!new File(fname).exists()) {
69             PrintWriter outfile = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fname)));
70             for(int i=rsize/2; i>=0; i--) test(i, rsize, outfile);
71             outfile.flush();
72             outfile.close();
73         }
74         System.out.println("done.");
75     }
76
77     public void test(int count, int size, PrintWriter outfile) throws Exception {
78         fpslic.flush();
79         drain(count);
80         fpslic.flush();
81         fill(count, size);
82
83         fpslic.flush();
84
85         fpslic.readCount();
86         long now = System.currentTimeMillis();
87         Thread.sleep(2000);
88         topLeft().ylut(0xff);
89         topLeft().xlut(0xff);
90         fpslic.flush();
91         long then = System.currentTimeMillis();
92
93         int tokens = fpslic.readCount();
94
95         int clockrate = 24; // (in mhz)
96         double elapsed = (double)((((FtdiBoard)fpslic).timer)/clockrate);
97         
98         double occupancy = ((double)(2*count))/((double)size);
99
100         // eleven dividers... ...and the interrupt pin counts *pairs* of transitions
101         int multiplier = 2*2*2*2*2*2*2*2*2*2*2*2;
102
103         int clockdivisor = 64;
104         multiplier /= clockdivisor;
105
106         double result = (tokens*multiplier)/elapsed; // in millions
107
108
109         // result is transitions/sec => 633mcell/sec velocity! =)
110         outfile.println(occupancy + ", " + result);
111         System.out.println((2*count)+"/"+size+"  "+occupancy + ", " + result/* + " @ " + elapsed*/);
112         outfile.flush();
113     }
114
115     private void drain(int size) {
116         while(true){
117             topLeft().xlut(0x00);
118             for(int i=0; i<size*4; i++) {
119                 topLeft().ylut(0xff);
120                 topLeft().ylut(0x00);
121             }
122             
123             fpslic.flush();
124             fpslic.readCount();
125             try { Thread.sleep(100); } catch (Exception e) { }
126             int rc = fpslic.readCount();
127             if (rc!=0) { System.err.println("flush() failed REALLY BADLY => " + rc); continue; }
128             
129             reconfigTopLeft();
130             for(int x=0; x<24; x++)
131                 for(int y=0; y<24; y++)
132                     fpslic.cell(x,y).wi(L0);
133             fpslic.flush();
134             for(int x=0; x<24; x++)
135                 for(int y=0; y<24; y++)
136                     fpslic.cell(x,y).wi(NONE);
137             fpslic.flush();
138             
139             fpslic.readCount();
140             try { Thread.sleep(100); } catch (Exception e) { }
141             rc = fpslic.readCount();
142             if (rc!=0) { System.err.println("flush() failed => " + rc); continue; }
143             break;
144         }
145     }
146
147     private void fill(int count, int size) {
148         //topLeft().ylut((count>0 && count<size/2-1) ? 0xff : 0x00);
149         if (count>0)
150             topLeft().ylut(0x00);
151         boolean yes = true;
152         if (count==1) {
153             topLeft().xlut(0x00);
154             yes = true;
155         } else {
156             for(int i=0; i<count-1; i++) {
157                 if (yes) {
158                     topLeft().xlut(0xff);
159                 } else {
160                     topLeft().xlut(0x00);
161                 }
162                 fpslic.flush();
163                 yes = !yes;
164             //System.out.println("fill => " + yes);
165             //try { Thread.sleep(500); } catch (Exception _) { }
166             }
167         }
168         //System.out.println("done filling.");
169         //try { Thread.sleep(2000); } catch (Exception _) { }
170
171         //System.out.println("reconfigured.");
172         //try { System.in.read(); }  catch (Exception _) { }
173
174
175         if (count>0 && count!=size/2-1) {
176             reconfigTopLeftPreserve(yes);
177         } else if (count>0) {
178             topLeft().xlut(0xff);
179             fpslic.flush();
180             topLeft().ylut(0xff);
181             reconfigTopLeftPreserve(false);
182         } 
183
184         //System.out.println("running.");
185         //try { System.in.read(); }  catch (Exception _) { }
186
187         //try { Thread.sleep(2000); } catch (Exception _) { }
188     }
189
190     private Fpslic.Cell topLeft() { return start.north().north(); }
191     private Fpslic.Cell topRight() { return start.north().ne(); }
192     private void reconfigTopLeft() {
193         Fpslic.Cell c = topLeft();
194                 c.c(YLUT);
195                 c.ylut(0x00);
196                 c.xlut(0x00);
197                 c.wi(L0);
198                 c.t(TMUX_W_AND_FB);
199                 c.ylut((LUT_SELF & ~LUT_OTHER) |
200                        (LUT_Z & ~LUT_OTHER) |
201                        (LUT_Z & LUT_SELF));
202             fpslic.flush();
203                 c.xlut(LUT_Z);
204             fpslic.flush();
205                 c.wi(NONE);
206             fpslic.flush();
207     }
208     private void reconfigTopLeftNice() {
209         Fpslic.Cell c = topLeft();
210         c.c(YLUT);
211         c.xlut(LUT_Z);
212         fpslic.flush();
213         c.ylut((LUT_SELF & ~LUT_OTHER) |
214                (LUT_Z & ~LUT_OTHER) |
215                (LUT_Z & LUT_SELF));
216         fpslic.flush();
217     }
218     private void reconfigTopLeftPreserve(boolean on) {
219         Fpslic.Cell c = topLeft();
220         fpslic.flush();
221         if (on) c.ylut(0x00);
222         //else    c.ylut(0xff);
223         //fpslic.flush();
224         c.xlut(LUT_Z);
225         fpslic.flush();
226         c.ylut((LUT_SELF & ~LUT_OTHER) |
227                (LUT_Z & ~LUT_OTHER) |
228                (LUT_Z & LUT_SELF));
229         fpslic.flush();
230     }
231     private void reconfigTopRight() { micropipelineStage(topRight(), topRight().west(), topRight().sw()); }
232
233     private Fpslic.Cell pipe(Fpslic.Cell c, Fpslic.Cell prev, int[] dirs) {
234         for(int i=0; i<dirs.length; i++) {
235             Fpslic.Cell next = c.dir(dirs[i]);
236             micropipelineStage(c, prev, next);
237             prev = c;
238             c = next;
239         }
240         return c;
241     }
242
243     private int createPipeline(Fpslic.Cell c, boolean downward, int length, boolean start) {
244         boolean stop = false;
245         do {
246         if (downward) {
247             if (c.row < 6) {
248                 if (length < 8+4) { stop = true; break; }
249                 length -= 8;
250                 c = pipe(c, c.north(), new int[] { SW, EAST, SW, WEST, NW, NORTH });
251                 c = c.se();
252                 c = pipe(c, c.north(), new int[] { NE, NORTH });
253                 c = c.sw().west();
254                 downward = false;
255             } else {
256                 if (length < 8+4) { stop = true; break; }
257                 length -= 8;
258                 c = micropipelineStage(c, c.north(), c.sw());
259                 c = micropipelineStage(c, c.ne(),    c.south());
260                 c = micropipelineStage(c, c.north(), c.se());
261                 c = micropipelineStage(c, c.nw(),    c.south());
262                 c = c.nw();
263                 c = micropipelineStage(c, c.south(), c.ne());
264                 c = micropipelineStage(c, c.sw(),    c.north());
265                 c = micropipelineStage(c, c.south(), c.nw());
266                 micropipelineStage(c, c.se(),    c.north());
267                 c = c.south().south().south().south().east();
268             }
269         } else {
270             if (c.row > c.fpslic().getHeight()-7) {
271                 if (length < 8+4) { stop = true; break; }
272                 length -= 8;
273                 c = pipe(c, c.south(), new int[] { NW, SOUTH });
274                 c = c.nw();
275                 c = pipe(c, c.south(), new int[] { NE, EAST, SE, WEST, SE, SOUTH });
276                 c = c.nw().west();
277                 downward = true;
278             } else {
279                 if (length < 8+4) { stop = true; break; }
280                 length -= 8;
281                 Fpslic.Cell ret = c = pipe(c, c.south(), new int[] { NE, NORTH, NW, NORTH });
282                 c = c.se();
283                 c = pipe(c, c.north(), new int[] { SW, SOUTH, SE, SOUTH });
284                 c = ret;
285             }
286         }
287         } while(false);
288         if (stop) {
289             length -= 4;
290             if (downward) {
291                 c = micropipelineStage(c, c.north(), c.sw());
292                 c = micropipelineStage(c, c.ne(), c.west());
293                 c = micropipelineStage(c, c.east(), c.ne());
294                 c = micropipelineStage(c, c.sw(), c.north());
295             } else {
296                 c = pipe(c, c.south(), new int[] { NW, EAST, SE, SOUTH });
297             }
298             return length;
299         } else {
300             return createPipeline(c, downward, length, false);
301         }
302     }
303
304     /*
305     private void createPipeline(Fpslic.Cell c, boolean downward, int length) {
306         length -= 2;
307         if (downward) {
308             if (c.row == 0) {
309                 c = micropipelineStage(c, c.ne(),   c.west());
310                 c = micropipelineStage(c, c.east(), c.nw());
311                 if (length > 0) createPipeline(c, false, length);
312             } else {
313                 c = micropipelineStage(c, c.ne(),   c.east());
314                 c = micropipelineStage(c, c.west(), c.sw());
315                 if (length > 0) createPipeline(c, true, length);
316             }
317         } else {
318             if (c.row == c.fpslic().getHeight()-1) {
319                 c = micropipelineStage(c, c.se(),   c.west());
320                 c = micropipelineStage(c, c.east(), c.sw());
321                 if (length > 0) createPipeline(c, true, length);
322             } else {
323                 c = micropipelineStage(c, c.se(),   c.east());
324                 c = micropipelineStage(c, c.west(), c.nw());
325                 if (length > 0) createPipeline(c, false, length);
326             }
327         }
328     }
329     */
330
331     private Fpslic.Cell micropipelineStage(Fpslic.Cell c, Fpslic.Cell prev, Fpslic.Cell next) {
332         return micropipelineStage(c, prev, next, true);
333     }
334     private Fpslic.Cell micropipelineStage(Fpslic.Cell c, Fpslic.Cell prev, Fpslic.Cell next, boolean configDir) {
335         c.b(false);
336         c.f(false);
337         switch(c.dir(next)) {
338             case NORTH: case SOUTH: case EAST: case WEST:
339                 switch (c.dir(prev)) {
340                     case NORTH: case SOUTH: case EAST: case WEST: throw new Error("cannot have prev&next both use y");
341                 }
342                 if (configDir) {
343                     c.yi(next);
344                     c.xi(prev);
345                 }
346
347         c.yo(false);
348         c.xo(true);
349
350                 c.c(YLUT);
351                 c.ylut(0x00);
352                 c.xlut(0x00);
353                 c.wi(L0);
354                 c.t(TMUX_W_AND_FB);
355                 c.ylut((LUT_SELF & ~LUT_OTHER) |
356                        (LUT_Z & ~LUT_OTHER) |
357                        (LUT_Z & LUT_SELF));
358                 c.xlut(LUT_Z);
359             fpslic.flush();
360                 c.wi(NONE);
361             fpslic.flush();
362                 break;
363             case NW: case SE: case SW: case NE:
364                 switch (c.dir(prev)) {
365                     case NW: case SE: case SW: case NE: throw new Error("cannot have prev&next both use x");
366                 }
367                 if (configDir) {
368                     c.xi(next);
369                     c.yi(prev);
370                 }
371
372         c.yo(true);
373         c.xo(true);
374         c.c(ZMUX);
375         c.zi(NONE);
376
377         //c.c(XLUT);
378                 c.xlut(0x00);
379                 c.ylut(0x00);
380                 c.wi(L0);
381                 c.t(TMUX_W_AND_FB);
382                 c.xlut((LUT_SELF & ~LUT_OTHER) |
383                        (LUT_Z & ~LUT_OTHER) |
384                        (LUT_Z & LUT_SELF));
385                 c.ylut(LUT_Z);
386             fpslic.flush();
387                 c.wi(NONE);
388             fpslic.flush();
389                 break;
390             default: throw new Error();
391         }
392         //c.t(TMUX_FB);
393         return next;
394     }
395
396     /*
397     private void turnOnLeds() {
398         for(int i=0; i<24; i++) {
399             //fpslic.iob_bot(i, true).enableOutput(NORTH);
400             //fpslic.iob_bot(i, false).enableOutput(NW);
401             fpslic.cell(i, 0).xlut(0xff);
402             fpslic.cell(i, 0).ylut(0xff);
403         }
404     }
405     */
406     private void setupScanCell() {
407         fpslic.cell(23,15).h(3, true);
408         fpslic.cell(23,15).yi(L3);
409         fpslic.cell(23,15).ylut(0xAA);
410         fpslic.iob_right(15, true).enableOutput(WEST);
411
412         fpslic.cell(23,0).ylut(0x00);
413         fpslic.iob_right(0, true).enableOutput(WEST);
414         fpslic.flush();
415     }
416
417     private void divider(Fpslic.Cell c) {
418         Fpslic.Cell detect1 = c;
419         Fpslic.Cell detect2 = c.east();
420
421         detect1.yi(NORTH);
422         detect1.ylut(LUT_SELF);
423         detect1.xlut(LUT_OTHER & (~LUT_Z));
424         detect1.c(YLUT);
425         detect1.t(TMUX_FB);
426         detect1.f(false);
427         detect1.b(false);
428
429         detect2.xi(NW);
430         detect2.ylut(LUT_OTHER);
431         detect2.xlut((~LUT_SELF) & LUT_Z);
432         detect2.c(YLUT);
433         detect2.t(TMUX_FB);
434         detect2.f(false);
435         detect2.b(false);
436
437         detect1.south().yi(EAST);
438         detect1.south().xi(NE);
439         detect1.south().c(YLUT);
440         detect1.south().t(TMUX_FB);
441         detect1.south().f(false);
442         detect1.south().b(false);
443         detect1.south().ylut( (LUT_OTHER    & (~LUT_SELF)) |
444                               ((~LUT_OTHER) &   LUT_Z)
445                               );
446         detect1.south().xlut( (LUT_SELF    & (~LUT_OTHER)) |
447                               ((~LUT_SELF) &   LUT_Z)
448                               );
449
450         detect2.south().yi(WEST);
451         detect2.south().xi(NW);
452         detect2.south().c(YLUT);
453         detect2.south().t(TMUX_FB);
454         detect2.south().f(false);
455         detect2.south().b(false);
456         detect2.south().ylut( (LUT_OTHER    & (LUT_SELF)) |
457                               ((~LUT_OTHER) &   LUT_Z)
458                               );
459         detect2.south().xlut( (LUT_SELF    & (~LUT_OTHER)) |
460                               ((~LUT_SELF) &   LUT_Z)
461                               );
462
463     }
464
465     private void runGui(int width, int height) throws Exception {
466         Gui vis = new Gui(fpslic, fpslic, width, height);
467         Frame fr = new Frame();
468         fr.addKeyListener(vis);
469         fr.setLayout(new BorderLayout());
470         fr.add(vis, BorderLayout.CENTER);
471         fr.pack();
472         fr.setSize(900, 900);
473         vis.repaint();
474         fr.repaint();
475         fr.show();
476     }
477 }
478
479