1 package edu.berkeley.slipway.demos;
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.*;
12 public class FastestMicropipelineFifoDemo extends MicropipelineFifoDemo {
14 public static void main(String[] s) throws Exception {
15 new FastestMicropipelineFifoDemo().mainx(s);
18 //////////////////////////////////////////////////////////////////////////////
20 public FpslicDevice.Cell start;
21 public FastestMicropipelineFifoDemo() throws Exception {
22 start = fpslic.cell(21, 21);
25 protected FpslicDevice.Cell masterCell() { return start.north().north(); }
27 private int dividers = 0;
28 protected int numDivisors() { return dividers; }
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;
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;
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;
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;
42 /** unpauses the master stage */
43 public void unPauseMaster() {
44 fpslic.cell(0,PLANE_PAUSE_MASTER_WHEN_HIGH).ylut(0x00);
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);
55 /** pauses the master stage */
56 public void pauseMaster() {
57 fpslic.cell(0,PLANE_PAUSE_MASTER_WHEN_HIGH).ylut(0xff);
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);
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);
72 fpslic.cell(0,PLANE_RESET_ALL_WHEN_LOW).ylut(0xff);
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);
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();
87 sw.west().drives(sw, true);
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);
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);
104 /** causes the master cell's successor output to resume normal functionality, leaving it in state "state" */
105 protected void unForceMasterSuccessor(boolean state) {
107 masterCell().xo(true);
108 masterCell().yo(true);
109 masterCell().xlut(LUT_Z);
111 masterCell().ylut(!state ? 0x00 : 0xff);
114 masterCell().ylut((LUT_SELF & ~LUT_OTHER) |
115 (LUT_Z & ~LUT_OTHER) |
123 protected int init(int size) {
124 return init(size, this.start);
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);
136 ExperimentUtils.setupScanCell(fpslic);
147 // create a column of dividers
148 FpslicDevice.Cell div;
152 pipe(start.west().north(), start.west().north().north(), new int[] { NE, SOUTH, NW, SOUTH });
154 // annoying "bridge cell", because dividers must take input from the north
155 div.north().yo(start.north());
156 div.north().xo(start.north());
158 rsize = size-createPipeline(start, true, size-4, false);
161 pipe(start.west().north(), start.west(), new int[] { NE, EAST, SW, SOUTH });
163 // annoying "bridge cell", because dividers must take input from the north
164 div.north().yo(start.north());
165 div.north().xo(start.north());
170 FpslicDevice.Cell xdiv = ExperimentUtils.divider(div);
172 if (xdiv==null) break;
175 div = div.south().east(); // lower-right hand corner of the last divider placed
179 while(div.north() != null) {
191 while(div != null && dividers < 10) {
192 FpslicDevice.Cell xdiv = ExperimentUtils.divider(div);
194 if (xdiv==null) { div = div.south().east(); break; }
195 if (dividers >= 10) { div = div.south().east(); break; }
199 while(div.south() != null) {
203 while(div.east() != null) {
207 // assumption that we wind up in the lower-right-hand corner
212 //////////////////////////////////////////////////////////////////////////////
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);
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;
232 if (length < 8+4) { stop = true; break; }
234 c = pipe(c, c.north(), new int[] { SW, EAST, SW, WEST, NW, NORTH });
236 c = pipe(c, c.north(), new int[] { NE, NORTH });
240 if (length < 8+4) { stop = true; break; }
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());
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();
254 if (c.row > c.fpslic().getHeight()-7) {
255 if (length < 8+4) { stop = true; break; }
257 c = pipe(c, c.south(), new int[] { NW, SOUTH });
259 c = pipe(c, c.south(), new int[] { NE, EAST, SE, WEST, SE, SOUTH });
263 if (length < 8+4) { stop = true; break; }
265 FpslicDevice.Cell ret = c = pipe(c, c.south(), new int[] { NE, NORTH, NW, NORTH });
267 c = pipe(c, c.north(), new int[] { SW, SOUTH, SE, SOUTH });
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());
280 c = pipe(c, c.south(), new int[] { NW, EAST, SE, SOUTH });
284 return createPipeline(c, downward, length, false);
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");
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");
305 default: throw new Error();
308 c.yi(polarity ? prev : next);
309 c.xi(polarity ? next : prev);
317 c.wi(PLANE_RESET_ALL_WHEN_LOW);
320 for(int i=L0; i<=L3; i++) c.h(i, true);
323 if (c.row==masterCell().row && c.col==masterCell().col) {
324 c.zi(PLANE_PAUSE_MASTER_WHEN_HIGH);
326 c.zi(PLANE_PAUSE_SLAVES_WHEN_HIGH);
328 c.ylut((LUT_SELF & ~LUT_OTHER) |
329 (LUT_Z & ~LUT_OTHER) |
334 // internally asymmetric
335 c.zi(PLANE_PAUSE_SLAVES_WHEN_LOW);
336 c.xlut((LUT_SELF & ~LUT_OTHER) |
337 (LUT_Z & ~LUT_OTHER) |
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));