updates that were lying around but never got checked in; includes reorg of gui
[slipway.git] / src / edu / berkeley / slipway / demos / FastestMicropipelineFifoDemo.java
1 package edu.berkeley.slipway.demos;
2
3 import java.io.*;
4 import java.util.*;
5 import java.awt.*;
6 import com.atmel.fpslic.*;
7 import edu.berkeley.slipway.*;
8 import edu.berkeley.slipway.gui.*;
9 import edu.berkeley.slipway.util.*;
10 import static com.atmel.fpslic.FpslicConstants.*;
11
12 public class FastestMicropipelineFifoDemo extends MicropipelineFifoDemo {
13
14     public static void main(String[] s) throws Exception {
15         new FastestMicropipelineFifoDemo().mainx(s);
16     }
17
18     //////////////////////////////////////////////////////////////////////////////
19
20     public FpslicDevice.Cell start;
21     public FastestMicropipelineFifoDemo() throws Exception {
22         start = fpslic.cell(21, 21);
23     }
24
25     protected FpslicDevice.Cell masterCell() { return start.north().north(); }
26
27     private int dividers = 0;
28     protected int numDivisors() { return dividers; }
29
30     /** drive this plane high to cause the "master" fifo stage to pause (hold current value) */
31     public static final int PLANE_PAUSE_MASTER_WHEN_HIGH  = L0;
32
33     /** drive this plane high to cause the "slave" fifo stages to pause (hold current value) */
34     public static final int PLANE_PAUSE_SLAVES_WHEN_HIGH  = L1;
35
36     /** drive this plane low to cause the "slave" fifo stages to pause (hold current value) */
37     public static final int PLANE_PAUSE_SLAVES_WHEN_LOW   = L2;
38
39     /** drive this plane low to cause all fifo stages to reset (set current value to 0) */
40     public static final int PLANE_RESET_ALL_WHEN_LOW      = L3;
41
42     /** unpauses the master stage */
43     public void unPauseMaster() {
44         fpslic.cell(0,PLANE_PAUSE_MASTER_WHEN_HIGH).ylut(0x00);
45         fpslic.flush();
46     }
47
48     /** unpauses the slave stages */
49     public void unPauseSlaves() {
50         fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_HIGH).ylut(0x00);
51         fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_LOW).ylut(0xff);
52         fpslic.flush();
53     }
54
55     /** pauses the master stage */
56     public void pauseMaster() {
57         fpslic.cell(0,PLANE_PAUSE_MASTER_WHEN_HIGH).ylut(0xff);
58         fpslic.flush();
59     }
60
61     /** pauses the slave stages */
62     public void pauseSlaves() {
63         fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_HIGH).ylut(0xff);
64         fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_LOW).ylut(0x00);
65         fpslic.flush();
66     }
67
68     /** reset all stages (should be paused before doing this) */
69     public void resetAll() {
70         fpslic.cell(0,PLANE_RESET_ALL_WHEN_LOW).ylut(0x00);
71         fpslic.flush();
72         fpslic.cell(0,PLANE_RESET_ALL_WHEN_LOW).ylut(0xff);
73         fpslic.flush();
74     }
75
76     /** configures the ylut of the cell at (0,plane) to drive plane "plane" across the entire chip */
77     private void drivePlane(int plane) {
78         for(int i=0; i<=23; i++){
79             FpslicDevice.Cell c = fpslic.cell(0, i);
80             c.h(plane, true);
81             c.v(plane, true);
82             if (c.vwire(plane).south() != null)
83                 c.vwire(plane).south().drives(c.vwire(plane), true);
84             for(FpslicDevice.SectorWire sw = c.hwire(plane).east();
85                 sw!=null;
86                 sw=sw.east())
87                 sw.west().drives(sw, true);
88         }
89         fpslic.cell(0, plane-L0).c(YLUT);
90         fpslic.cell(0, plane-L0).b(false);
91         fpslic.cell(0, plane-L0).f(false);
92         fpslic.cell(0, plane-L0).out(plane, true);
93     }
94
95     /** causes the master cell's successor output to be set to the given value */
96     protected void forceMasterSuccessor(boolean high) {
97         masterCell().ylut(0xff);
98         masterCell().xo(false);
99         masterCell().yo(false);
100         masterCell().xlut(high ? 0xff : 0x00);
101         fpslic.flush();
102     }
103
104     /** causes the master cell's successor output to resume normal functionality, leaving it in state "state" */
105     protected void unForceMasterSuccessor(boolean state) {
106         pauseSlaves();
107         masterCell().xo(true);
108         masterCell().yo(true);
109         masterCell().xlut(LUT_Z);
110         fpslic.flush();
111         masterCell().ylut(!state ? 0x00 : 0xff);
112         fpslic.flush();
113         pauseMaster();
114         masterCell().ylut((LUT_SELF & ~LUT_OTHER) |
115                        (LUT_Z & ~LUT_OTHER) |
116                        (LUT_Z & LUT_SELF));
117         fpslic.flush();
118         unPauseMaster();
119         unPauseSlaves();
120     }
121
122
123     protected int init(int size) {
124         return init(size, this.start);
125     }
126     protected int init(int size, FpslicDevice.Cell start) {
127         for(int x=1; x<24; x++)
128             for(int y=0; y<24; y++) {
129                 FpslicDevice.Cell c = fpslic.cell(x, y);
130                 c.xlut(0x00);
131                 c.ylut(0x00);
132                 c.b(false);
133                 c.f(false);
134                 c.c(YLUT);
135             }
136         ExperimentUtils.setupScanCell(fpslic);
137         fpslic.flush();
138
139         this.start = start;
140         drivePlane(L0);
141         drivePlane(L1);
142         drivePlane(L2);
143         drivePlane(L3);
144
145         int rsize = 0;
146
147         // create a column of dividers
148         FpslicDevice.Cell div;
149
150         if (size == 4) {
151             rsize = 4;
152             pipe(start.west().north(), start.west().north().north(), new int[] { NE, SOUTH, NW, SOUTH });
153             div = start.east();
154             // annoying "bridge cell", because dividers must take input from the north
155             div.north().yo(start.north());
156             div.north().xo(start.north());
157         } else {
158             rsize = size-createPipeline(start, true, size-4, false);
159             unPauseMaster();
160             unPauseSlaves();
161             pipe(start.west().north(), start.west(), new int[] { NE, EAST, SW, SOUTH });
162             div = start.east();
163             // annoying "bridge cell", because dividers must take input from the north
164             div.north().yo(start.north());
165             div.north().xo(start.north());
166         }
167
168         dividers = 0;
169         while(div != null) {
170             FpslicDevice.Cell xdiv = ExperimentUtils.divider(div);
171             dividers++;
172             if (xdiv==null) break;
173             div = xdiv;
174         }
175         div = div.south().east();  // lower-right hand corner of the last divider placed
176         if (dividers < 10) {
177         div.east().yo(div);
178         div = div.east();
179         while(div.north() != null) {
180             div.north().yo(div);
181             div = div.north();
182         }
183         div.xo(div.south());
184         div.east().yo(div);
185         div.east().xo(div);
186         div = div.east();
187         div.east().xo(div);
188         div.east().yo(div);
189         div.south().yo(div);
190         div = div.south();
191         while(div != null && dividers < 10) {
192             FpslicDevice.Cell xdiv = ExperimentUtils.divider(div);
193             dividers++;
194             if (xdiv==null) { div = div.south().east(); break; }
195             if (dividers >= 10)  { div = div.south().east(); break; }
196             div = xdiv;
197         }
198         }
199         while(div.south() != null) {
200             div.south().yo(div);
201             div = div.south();
202         }
203         while(div.east() != null) {
204             div.east().yo(div);
205             div = div.east();
206         }
207         // assumption that we wind up in the lower-right-hand corner
208
209         return rsize;
210     }
211
212     //////////////////////////////////////////////////////////////////////////////
213
214     /** create a pipeline starting at cell "c", with predecessor "prev", and move in the directions
215      *  specified by "dirs" */
216     private FpslicDevice.Cell pipe(FpslicDevice.Cell c, FpslicDevice.Cell prev, int[] dirs) {
217         for(int i=0; i<dirs.length; i++) {
218             FpslicDevice.Cell next = c.dir(dirs[i]);
219             micropipelineStage(c, prev, next);
220             prev = c;
221             c = next;
222         }
223         return c;
224     }
225
226     /** this is really ugly and I no longer understand it */
227     private int createPipeline(FpslicDevice.Cell c, boolean downward, int length, boolean start) {
228         boolean stop = false;
229         do {
230             if (downward) {
231                 if (c.row < 6) {
232                     if (length < 8+4) { stop = true; break; }
233                     length -= 8;
234                     c = pipe(c, c.north(), new int[] { SW, EAST, SW, WEST, NW, NORTH });
235                     c = c.se();
236                     c = pipe(c, c.north(), new int[] { NE, NORTH });
237                     c = c.sw().west();
238                     downward = false;
239                 } else {
240                     if (length < 8+4) { stop = true; break; }
241                     length -= 8;
242                     c = micropipelineStage(c, c.north(), c.sw());
243                     c = micropipelineStage(c, c.ne(),    c.south());
244                     c = micropipelineStage(c, c.north(), c.se());
245                     c = micropipelineStage(c, c.nw(),    c.south());
246                     c = c.nw();
247                     c = micropipelineStage(c, c.south(), c.ne());
248                     c = micropipelineStage(c, c.sw(),    c.north());
249                     c = micropipelineStage(c, c.south(), c.nw());
250                     micropipelineStage(c, c.se(),    c.north());
251                     c = c.south().south().south().south().east();
252                 }
253             } else {
254                 if (c.row > c.fpslic().getHeight()-7) {
255                     if (length < 8+4) { stop = true; break; }
256                     length -= 8;
257                     c = pipe(c, c.south(), new int[] { NW, SOUTH });
258                     c = c.nw();
259                     c = pipe(c, c.south(), new int[] { NE, EAST, SE, WEST, SE, SOUTH });
260                     c = c.nw().west();
261                     downward = true;
262                 } else {
263                     if (length < 8+4) { stop = true; break; }
264                     length -= 8;
265                     FpslicDevice.Cell ret = c = pipe(c, c.south(), new int[] { NE, NORTH, NW, NORTH });
266                     c = c.se();
267                     c = pipe(c, c.north(), new int[] { SW, SOUTH, SE, SOUTH });
268                     c = ret;
269                 }
270             }
271         } while(false);
272         if (stop) {
273             length -= 4;
274             if (downward) {
275                 c = micropipelineStage(c, c.north(), c.sw());
276                 c = micropipelineStage(c, c.ne(), c.west());
277                 c = micropipelineStage(c, c.east(), c.ne());
278                 c = micropipelineStage(c, c.sw(), c.north());
279             } else {
280                 c = pipe(c, c.south(), new int[] { NW, EAST, SE, SOUTH });
281             }
282             return length;
283         } else {
284             return createPipeline(c, downward, length, false);
285         }
286     }
287
288     private FpslicDevice.Cell micropipelineStage(FpslicDevice.Cell c,
289                                                  FpslicDevice.Cell prev,
290                                                  FpslicDevice.Cell next) {
291         boolean polarity = false;
292         switch(c.dir(next)) {
293             case NORTH: case SOUTH: case EAST: case WEST:
294                 switch (c.dir(prev)) {
295                     case NORTH: case SOUTH: case EAST: case WEST: throw new Error("cannot have prev&next both use y");
296                 }
297                 polarity = false;
298                 break;
299             case NW: case SE: case SW: case NE:
300                 switch (c.dir(prev)) {
301                     case NW: case SE: case SW: case NE: throw new Error("cannot have prev&next both use x");
302                 }
303                 polarity = true;
304                 break;
305             default: throw new Error();
306         }
307
308         c.yi(polarity ? prev : next);
309         c.xi(polarity ? next : prev);
310
311         c.b(false);
312         c.f(false);
313         c.yo(true);
314         c.xo(true);
315         c.c(ZMUX);
316
317         c.wi(PLANE_RESET_ALL_WHEN_LOW);
318         c.t(TMUX_W_AND_FB);
319
320         for(int i=L0; i<=L3; i++) c.h(i, true);
321
322         if (!polarity) {
323             if (c.row==masterCell().row && c.col==masterCell().col) {
324                 c.zi(PLANE_PAUSE_MASTER_WHEN_HIGH);
325             } else {
326                 c.zi(PLANE_PAUSE_SLAVES_WHEN_HIGH);
327             }
328             c.ylut((LUT_SELF & ~LUT_OTHER) |
329                    (LUT_Z & ~LUT_OTHER) |
330                    (LUT_Z & LUT_SELF));
331             c.xlut(LUT_Z);
332         } else {
333             /*
334             // internally asymmetric
335             c.zi(PLANE_PAUSE_SLAVES_WHEN_LOW);
336             c.xlut((LUT_SELF & ~LUT_OTHER) |
337                    (LUT_Z & ~LUT_OTHER) |
338                    (LUT_Z & LUT_SELF));
339             c.ylut(LUT_Z);
340             */
341
342             // internally symmetric
343             c.zi(PLANE_PAUSE_SLAVES_WHEN_HIGH);
344             c.ylut((~LUT_SELF & LUT_OTHER) |
345                    (LUT_Z & ~LUT_SELF) |
346                    (LUT_Z & LUT_OTHER));
347             c.xlut(LUT_Z);
348         }
349         return next;
350     }
351
352
353
354 }