1 package edu.berkeley.slipway.demos;
6 import com.atmel.fpslic.*;
7 import edu.berkeley.slipway.*;
8 import edu.berkeley.slipway.gui.*;
9 import static com.atmel.fpslic.FpslicConstants.*;
11 public class FastestMicropipelineFifoDemo extends MicropipelineFifoDemo {
13 public static void main(String[] s) throws Exception {
14 new FastestMicropipelineFifoDemo().mainx(s);
17 //////////////////////////////////////////////////////////////////////////////
19 public FpslicDevice.Cell start;
20 public FastestMicropipelineFifoDemo() throws Exception {
21 start = fpslic.cell(21, 21);
24 protected FpslicDevice.Cell masterCell() { return start.north().north(); }
26 private int dividers = 0;
27 protected int numDivisors() { return dividers; }
29 /** drive this plane high to cause the "master" fifo stage to pause (hold current value) */
30 public static final int PLANE_PAUSE_MASTER_WHEN_HIGH = L0;
32 /** drive this plane high to cause the "slave" fifo stages to pause (hold current value) */
33 public static final int PLANE_PAUSE_SLAVES_WHEN_HIGH = L1;
35 /** drive this plane low to cause the "slave" fifo stages to pause (hold current value) */
36 public static final int PLANE_PAUSE_SLAVES_WHEN_LOW = L2;
38 /** drive this plane low to cause all fifo stages to reset (set current value to 0) */
39 public static final int PLANE_RESET_ALL_WHEN_LOW = L3;
41 /** unpauses the master stage */
42 public void unPauseMaster() {
43 fpslic.cell(0,PLANE_PAUSE_MASTER_WHEN_HIGH).ylut(0x00);
47 /** unpauses the slave stages */
48 public void unPauseSlaves() {
49 fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_HIGH).ylut(0x00);
50 fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_LOW).ylut(0xff);
54 /** pauses the master stage */
55 public void pauseMaster() {
56 fpslic.cell(0,PLANE_PAUSE_MASTER_WHEN_HIGH).ylut(0xff);
60 /** pauses the slave stages */
61 public void pauseSlaves() {
62 fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_HIGH).ylut(0xff);
63 fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_LOW).ylut(0x00);
67 /** reset all stages (should be paused before doing this) */
68 public void resetAll() {
69 fpslic.cell(0,PLANE_RESET_ALL_WHEN_LOW).ylut(0x00);
71 fpslic.cell(0,PLANE_RESET_ALL_WHEN_LOW).ylut(0xff);
75 /** configures the ylut of the cell at (0,plane) to drive plane "plane" across the entire chip */
76 private void drivePlane(int plane) {
77 for(int i=0; i<=23; i++){
78 FpslicDevice.Cell c = fpslic.cell(0, i);
81 if (c.vwire(plane).south() != null)
82 c.vwire(plane).south().drives(c.vwire(plane), true);
83 for(FpslicDevice.SectorWire sw = c.hwire(plane).east();
86 sw.west().drives(sw, true);
88 fpslic.cell(0, plane-L0).c(YLUT);
89 fpslic.cell(0, plane-L0).b(false);
90 fpslic.cell(0, plane-L0).f(false);
91 fpslic.cell(0, plane-L0).out(plane, true);
94 /** causes the master cell's successor output to be set to the given value */
95 protected void forceMasterSuccessor(boolean high) {
96 masterCell().ylut(0xff);
97 masterCell().xo(false);
98 masterCell().yo(false);
99 masterCell().xlut(high ? 0xff : 0x00);
103 /** causes the master cell's successor output to resume normal functionality, leaving it in state "state" */
104 protected void unForceMasterSuccessor(boolean state) {
106 masterCell().xo(true);
107 masterCell().yo(true);
108 masterCell().xlut(LUT_Z);
110 masterCell().ylut(!state ? 0x00 : 0xff);
113 masterCell().ylut((LUT_SELF & ~LUT_OTHER) |
114 (LUT_Z & ~LUT_OTHER) |
122 protected int init(int size) {
123 return init(size, this.start);
125 protected int init(int size, FpslicDevice.Cell start) {
126 for(int x=1; x<24; x++)
127 for(int y=0; y<24; y++) {
128 FpslicDevice.Cell c = fpslic.cell(x, y);
135 ExperimentUtils.setupScanCell(fpslic);
146 // create a column of dividers
147 FpslicDevice.Cell div;
151 pipe(start.west().north(), start.west().north().north(), new int[] { NE, SOUTH, NW, SOUTH });
153 // annoying "bridge cell", because dividers must take input from the north
154 div.north().yo(start.north());
155 div.north().xo(start.north());
157 rsize = size-createPipeline(start, true, size-4, false);
160 pipe(start.west().north(), start.west(), new int[] { NE, EAST, SW, SOUTH });
162 // annoying "bridge cell", because dividers must take input from the north
163 div.north().yo(start.north());
164 div.north().xo(start.north());
169 FpslicDevice.Cell xdiv = ExperimentUtils.divider(div);
171 if (xdiv==null) break;
174 div = div.south().east(); // lower-right hand corner of the last divider placed
178 while(div.north() != null) {
190 while(div != null && dividers < 10) {
191 FpslicDevice.Cell xdiv = ExperimentUtils.divider(div);
193 if (xdiv==null) { div = div.south().east(); break; }
194 if (dividers >= 10) { div = div.south().east(); break; }
198 while(div.south() != null) {
202 while(div.east() != null) {
206 // assumption that we wind up in the lower-right-hand corner
211 //////////////////////////////////////////////////////////////////////////////
213 /** create a pipeline starting at cell "c", with predecessor "prev", and move in the directions
214 * specified by "dirs" */
215 private FpslicDevice.Cell pipe(FpslicDevice.Cell c, FpslicDevice.Cell prev, int[] dirs) {
216 for(int i=0; i<dirs.length; i++) {
217 FpslicDevice.Cell next = c.dir(dirs[i]);
218 micropipelineStage(c, prev, next);
225 /** this is really ugly and I no longer understand it */
226 private int createPipeline(FpslicDevice.Cell c, boolean downward, int length, boolean start) {
227 boolean stop = false;
231 if (length < 8+4) { stop = true; break; }
233 c = pipe(c, c.north(), new int[] { SW, EAST, SW, WEST, NW, NORTH });
235 c = pipe(c, c.north(), new int[] { NE, NORTH });
239 if (length < 8+4) { stop = true; break; }
241 c = micropipelineStage(c, c.north(), c.sw());
242 c = micropipelineStage(c, c.ne(), c.south());
243 c = micropipelineStage(c, c.north(), c.se());
244 c = micropipelineStage(c, c.nw(), c.south());
246 c = micropipelineStage(c, c.south(), c.ne());
247 c = micropipelineStage(c, c.sw(), c.north());
248 c = micropipelineStage(c, c.south(), c.nw());
249 micropipelineStage(c, c.se(), c.north());
250 c = c.south().south().south().south().east();
253 if (c.row > c.fpslic().getHeight()-7) {
254 if (length < 8+4) { stop = true; break; }
256 c = pipe(c, c.south(), new int[] { NW, SOUTH });
258 c = pipe(c, c.south(), new int[] { NE, EAST, SE, WEST, SE, SOUTH });
262 if (length < 8+4) { stop = true; break; }
264 FpslicDevice.Cell ret = c = pipe(c, c.south(), new int[] { NE, NORTH, NW, NORTH });
266 c = pipe(c, c.north(), new int[] { SW, SOUTH, SE, SOUTH });
274 c = micropipelineStage(c, c.north(), c.sw());
275 c = micropipelineStage(c, c.ne(), c.west());
276 c = micropipelineStage(c, c.east(), c.ne());
277 c = micropipelineStage(c, c.sw(), c.north());
279 c = pipe(c, c.south(), new int[] { NW, EAST, SE, SOUTH });
283 return createPipeline(c, downward, length, false);
287 private FpslicDevice.Cell micropipelineStage(FpslicDevice.Cell c,
288 FpslicDevice.Cell prev,
289 FpslicDevice.Cell next) {
290 boolean polarity = false;
291 switch(c.dir(next)) {
292 case NORTH: case SOUTH: case EAST: case WEST:
293 switch (c.dir(prev)) {
294 case NORTH: case SOUTH: case EAST: case WEST: throw new Error("cannot have prev&next both use y");
298 case NW: case SE: case SW: case NE:
299 switch (c.dir(prev)) {
300 case NW: case SE: case SW: case NE: throw new Error("cannot have prev&next both use x");
304 default: throw new Error();
307 c.yi(polarity ? prev : next);
308 c.xi(polarity ? next : prev);
316 c.wi(PLANE_RESET_ALL_WHEN_LOW);
319 for(int i=L0; i<=L3; i++) c.h(i, true);
322 if (c.row==masterCell().row && c.col==masterCell().col) {
323 c.zi(PLANE_PAUSE_MASTER_WHEN_HIGH);
325 c.zi(PLANE_PAUSE_SLAVES_WHEN_HIGH);
327 c.ylut((LUT_SELF & ~LUT_OTHER) |
328 (LUT_Z & ~LUT_OTHER) |
333 // internally asymmetric
334 c.zi(PLANE_PAUSE_SLAVES_WHEN_LOW);
335 c.xlut((LUT_SELF & ~LUT_OTHER) |
336 (LUT_Z & ~LUT_OTHER) |
341 // internally symmetric
342 c.zi(PLANE_PAUSE_SLAVES_WHEN_HIGH);
343 c.ylut((~LUT_SELF & LUT_OTHER) |
344 (LUT_Z & ~LUT_SELF) |
345 (LUT_Z & LUT_OTHER));