jnilib = libFtdiUartNative.so
endif
-## slipway ############################################################################
-
-run: slipway.jar
- java -cp slipway.jar edu.berkeley.slipway.Demo 30
+## demos ############################################################################
demo: slipway.jar
- java -cp slipway.jar edu.berkeley.slipway.Demo2 30
+ java -cp slipway.jar edu.berkeley.slipway.demos.Demo 30
+
+demo2: slipway.jar
+ java -cp slipway.jar edu.berkeley.slipway.demos.Demo2 30
+
+asyncdemo: slipway.jar
+ java -cp slipway.jar edu.berkeley.slipway.demos.FastestMicropipelineFifoDemo misc/data/async/
+
+mpardemo: upstream/jhdl-edifparser.jar slipway.jar
+ iverilog -t fpga -s main -o out.edf misc/mpardemo.v
+ java -cp slipway.jar:upstream/jhdl-edifparser.jar edu.berkeley.slipway.mpar.MPARDemo out.edf
+
+
+## slipway ############################################################################
build/src/com/ftdi/usb/FtdiUart.c: src/com/ftdi/usb/FtdiUart.i
mkdir -p `dirname $@`
## for rebuilding usbdrone.hex ###########################################################
-build/slipway_drone.hex: src/edu/berkeley/slipway/FtdiBoardSlave.c upstream/avr-libc/.built
+build/slipway_drone.hex: src/edu/berkeley/slipway/SlipwaySlave.c upstream/avr-libc/.built
upstream/prefix/bin/avr-gcc -O3 -mmcu=at94k $< -o $@.o
upstream/prefix/bin/avr-objcopy -O ihex $@.o $@
PATH=$$PATH:$(shell pwd)/upstream/prefix/bin make install
touch $@
-mpardemo: upstream/jhdl-edifparser.jar slipway.jar
- iverilog -t fpga -s main -o out.edf misc/mpardemo.v
- java -cp slipway.jar:upstream/jhdl-edifparser.jar edu.berkeley.slipway.mpar.MPARDemo out.edf
-
## edif parser ##########################################################################
--- /dev/null
+package com.atmel.fpslic;
+
+import edu.berkeley.abits.*;
+import java.io.*;
+
+/**
+ * Implementation of <tt>Board</tt> for Fpslic devices; subclass must
+ * implement methods to wiggle pins on the chip.
+ */
+public abstract class FpslicBoard implements Board {
+
+ public FpslicBoard() throws IOException { }
+
+ public void reset() throws IOException {
+ avrrstPin(false);
+ configDataPin(false);
+ resetPin(false);
+ cclkPin(false);
+
+ conPin(false);
+ flush();
+
+ resetPin(false);
+ try { Thread.sleep(500); } catch (Exception e) { }
+ if (initPin()) throw new IOException("INIT was still high after pulling RESET low");
+
+ resetPin(true);
+ try { Thread.sleep(500); } catch (Exception e) { }
+ if (!initPin()) throw new IOException("INIT was still low after releasing RESET");
+
+ sendConfigBits(0,2);
+ flush();
+ }
+
+ public OutputStream getConfigStream() throws IOException {
+ reset();
+ return new OutputStream() {
+ int bytes = 0;
+ int bits = 0;
+ public void write(int in) throws IOException {
+ for(int i=7; i>=0; i--) {
+ bits++;
+ sendConfigBits((((in & 0xff) & (1<<i))!=0)?1:0, 1);
+ }
+ }
+ public void write(byte[] b, int off, int len) throws IOException {
+ for(int i=off; i<off+len; i++)
+ write(b[i]);
+ }
+ public void flush() throws IOException {
+ FpslicBoard.this.flush();
+ }
+ public void close() throws IOException {
+ flush();
+ releaseConPin();
+ if (!initPin())
+ throw new IOException("initialization failed at " + bytes);
+ for(int i=0; i<100; i++) {
+ flush();
+ if (!initPin())
+ throw new IOException("initialization failed at " + bytes);
+ try { Thread.sleep(20); } catch (Exception e) { }
+ sendConfigBits(0,1);
+ }
+ FpslicBoard.this.close();
+ }
+ };
+ }
+
+ public void selfTest(SelfTestResultListener resultListener) throws IOException {
+ boolean pin;
+
+ // correct preamble
+ getConfigStream();
+ sendConfigBits(Integer.parseInt("00000000", 2), 8);
+ sendConfigBits(Integer.parseInt("10110111", 2), 8);
+ sendConfigBits(0,1);
+ flush();
+ try { Thread.sleep(100); } catch (Exception e) { }
+ pin = initPin();
+ resultListener.reportTestResult(0, 4, pin);
+
+ // preamble shifted one bit earlier than it should be
+ getConfigStream();
+ sendConfigBits(Integer.parseInt("0000000", 2), 7);
+ sendConfigBits(Integer.parseInt("10110111", 2), 8);
+ sendConfigBits(0, 2);
+ flush();
+ try { Thread.sleep(100); } catch (Exception e) { }
+ pin = initPin();
+ resultListener.reportTestResult(1, 4, !pin);
+
+ // preamble shifted one bit later than it should be
+ getConfigStream();
+ sendConfigBits(Integer.parseInt("000000000", 2), 9);
+ sendConfigBits(Integer.parseInt("10110111", 2), 8);
+ //sendConfigBits(0, 1);
+ flush();
+ try { Thread.sleep(100); } catch (Exception e) { }
+ pin = initPin();
+ resultListener.reportTestResult(2, 4, !pin);
+
+ // plain 'ol bogus preamble
+ getConfigStream();
+ sendConfigBits(Integer.parseInt("00000000", 2), 8);
+ sendConfigBits(Integer.parseInt("11110111", 2), 8);
+ sendConfigBits(0, 1);
+ flush();
+ try { Thread.sleep(100); } catch (Exception e) { }
+ pin = initPin();
+ resultListener.reportTestResult(3, 4, !pin);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ private void sendConfigBits(int bits, int numbits) throws IOException {
+ for(int i=(numbits-1); i>=0; i--) {
+ boolean bit = (bits & (1<<i)) != 0;
+ configDataPin(bit);
+ cclkPin(true);
+ cclkPin(false);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ protected abstract void avrrstPin(boolean on) throws IOException;
+ protected abstract void cclkPin(boolean on) throws IOException;
+ protected abstract void configDataPin(boolean on) throws IOException;
+ protected abstract void resetPin(boolean on) throws IOException;
+ protected abstract boolean initPin() throws IOException;
+ protected abstract void releaseConPin() throws IOException;
+ protected abstract void conPin(boolean on) throws IOException;
+
+ protected abstract void purge() throws IOException;
+ protected abstract void flush() throws IOException;
+ protected abstract void close() throws IOException;
+
+}
--- /dev/null
+package com.atmel.fpslic;
+
+import java.util.*;
+import java.io.*;
+import org.ibex.util.Log;
+import edu.berkeley.abits.*;
+import static com.atmel.fpslic.FpslicConstants.*;
+
+public abstract class FpslicDevice implements Device {
+
+ private final int width;
+ private final int height;
+
+ public FpslicDevice(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+
+ public int getWidth() { return width; }
+ public int getHeight() { return height; }
+
+ public abstract void flush();
+ public abstract void mode4(int z, int y, int x, int d);
+ public abstract byte mode4(int z, int y, int x);
+
+ public byte mode4zyx(int zyx) { return mode4(zyx>>24, (zyx>>16)&0xff, (zyx>>8)&0xff); }
+ public void mode4zyx(int zyx, int d, int invmask) { mode4(zyx>>24, (zyx>>16)&0xff, (zyx>>8)&0xff, d, invmask); }
+ public void mode4(int z, int y, int x, int d, int invmask) {
+ int old = mode4(z, y, x);
+ old &= ~invmask;
+ old |= d;
+ mode4(z, y, x, old);
+ }
+ public void mode4zyx(int zyx, int bit, boolean set) { mode4(zyx>>24, (zyx>>16)&0xff, (zyx>>8)&0xff, bit, set); }
+ public void mode4(int z, int y, int x, int bit, boolean set) {
+ int old = mode4(z, y, x);
+ old &= ~(1 << bit);
+ old |= set ? (1 << bit) : 0;
+ mode4(z, y, x, old);
+ }
+
+ // Inner Classes ///////////////////////////////////////////////////////////////////////////////
+
+ public final class Sector {
+ public final int col;
+ public final int row;
+ public Sector(Cell c) { this((c.col/4)*4, (c.row/4)*4); }
+ private Sector(int col, int row) {
+ if (row % 4 != 0) throw new Error("Sector must be created with a multiple-of-4 row");
+ if (col % 4 != 0) throw new Error("Sector must be created with a multiple-of-4 col");
+ this.row = row;
+ this.col = col;
+ }
+ public Sector north() { return row+4>=getHeight() ? null : new Sector(col, row+4); }
+ public Sector south() { return row==0 ? null : new Sector(col, row-4); }
+ public Sector east() { return col+4>=getWidth() ? null : new Sector(col+4, row); }
+ public Sector west() { return col==0 ? null : new Sector(col-4, row); }
+ public Cell cell() { return FpslicDevice.this.cell(col, row); }
+ }
+
+ public final class SectorWire {
+ public final boolean global;
+ public final boolean horizontal;
+ public final int plane;
+ public final int row;
+ public final int col;
+ public SectorWire(boolean horizontal, int plane, int col, int row) {
+ this(horizontal, plane, col, row, false);
+ }
+
+ public void useColumnClock() {
+ // this is very poorly understood
+ if (horizontal) throw new RuntimeException();
+ mode4(0x25, (row>>2)+1, col, 0x80);
+ mode4(0x29, (row>>2), col, 0x40);
+ }
+
+ public SectorWire(boolean horizontal, int plane, int col, int row, boolean global) {
+ this.horizontal=horizontal;
+ this.global=global;
+ this.plane=plane;
+ this.col= horizontal ? (col & ~0x3) : col;
+ this.row=!horizontal ? (row & ~0x3) : row;
+ }
+ public SectorWire global() {
+ return new SectorWire(horizontal, plane, col, row, true);
+ }
+ public boolean isDriven() {
+ // FIXME: bridging connections (horiz-to-vert)
+ for(int i=0; i<4; i++)
+ if (cell(horizontal ? col+i : col,
+ horizontal ? row : row+i).out(plane)) return true;
+ // FIXME: sector switchbox drivers
+ return false;
+ }
+ private int z(int z) { return (horizontal ? 0x30 : 0x20) | z; }
+ public int code(boolean topleft) {
+ switch(plane) {
+ case 0: return z(8)+(topleft?0:1);
+ case 1: return z(6)+(topleft?0:1);
+ case 2: return z(2*(4-plane))+(topleft?0:1);
+ case 3: return z(2*(4-plane))+(topleft?0:1);
+ case 4: return z(2*(4-plane))+(topleft?0:1);
+ }
+ throw new Error();
+ }
+
+ private final int fine() { return horizontal ? row : col; }
+ public final int coarse() { return horizontal ? col : row; }
+ private int _row() { return horizontal ? row : ((row)>>2); }
+ private int _col() { return horizontal ? ((col)>>2) : col; }
+
+ public SectorWire west() { return !horizontal ? null : col-4<0 ? null : new SectorWire(horizontal, plane, col-4, row); }
+ public SectorWire east() { return !horizontal ? null : col+4>=getWidth() ? null : new SectorWire(horizontal, plane, col+4, row); }
+ public SectorWire north() { return horizontal ? null : row+4>=getHeight() ? null : new SectorWire(horizontal, plane, col, row+4); }
+ public SectorWire south() { return horizontal ? null : row-4<0 ? null : new SectorWire(horizontal, plane, col, row-4); }
+
+ public String toString() {
+ return
+ (horizontal?(col+":"+(col+3)):(""+col))+","+
+ (horizontal?(row+"") :(row+":"+(row+3)))+
+ "x"+plane;
+ }
+
+ /** returns the ZYX0 coordinate of the byte controlling the switchbox that allows <tt>w</tt> to drive this wire */
+ public int switchbox(SectorWire w) {
+ if (w.horizontal==horizontal) {
+ if (w.plane!=plane) throw new Error();
+ if (Math.abs(w.coarse()-coarse())!=4) throw new Error(w.coarse() + " -- " + coarse());
+ boolean topleft = horizontal ? (w.coarse() < coarse()) : (w.coarse() > coarse());
+ int col = _col() + (( horizontal && !topleft) ? 1 : 0);
+ int row = _row() + ((!horizontal && topleft) ? 1 : 0);
+ return (code(topleft) << 24) | (row<<16) | (col<<8);
+ }
+ throw new Error("not implemented");
+ }
+
+ public void dork() {
+ mode4zyx(switchbox(north()), (1<<6), (1<<6));
+ }
+
+ public void drives(SectorWire w, boolean enable) {
+ // FIXME: better error checks?
+ int val = 0;
+ if (enable) {
+ if (!global) val = 0x02;
+ else val = 0x04;
+ }
+ int mask = 0x07;
+ if (w.global) { mask = mask << 3; val = val << 3; }
+ mode4zyx(switchbox(w), val, mask);
+ }
+
+ public boolean drives(SectorWire w) {
+ // FIXME: better error checks?
+ int connect = (mode4zyx(switchbox(w)) >> (global?3:0)) & 0x7;
+ return (connect & 0x2)!=0;
+ }
+ public SectorWire driverRight() {
+ //System.out.println("checking " + Integer.toString(code(true), 16) + " " +
+ //Integer.toString(_row(), 16) + " " + Integer.toString(_col(), 16));
+ int ret = mode4(z(code(true)), _row(), _col());
+ ret = (ret >> (global?3:0)) & 0x7;
+ switch(ret) {
+ case 0: return null;
+ case 1: return null; /* global wire on same side */
+ case 2: return new SectorWire(horizontal, plane, horizontal?(col+4):col, horizontal?row:(row+4));
+ case 4: return null; /* global wire on other side */
+ default: throw new Error("multiple drivers on " + this + "!");
+ }
+ }
+
+ public boolean touches(Cell c) {
+ return
+ horizontal
+ ? (c.row==_row() && (_col()/4 == c.col/4))
+ : (c.col==_col() && (_row()/4 == c.row/4));
+ }
+ }
+ /*
+ public final class SwitchBox {
+ public final boolean h;
+ public final int col;
+ public final int row;
+ public final int plane;
+ public SwitchBox(boolean h, int col, int row, int plane) { this.h = h; this.col = col; this.row = row; this.plane = plane; }
+ public SectorWire west(boolean global) { return !h ? null : global ? null : new SectorWire(h, col-4, row, plane); }
+ public SectorWire east(boolean global) { return !h ? null : global ? null : new SectorWire(h, col+4, row, plane); }
+ public SectorWire north(boolean global) { return !h ? null : global ? null : new SectorWire(h, col, row-4, plane); }
+ public SectorWire south(boolean global) { return !h ? null : global ? null : new SectorWire(h, col, row+4, plane); }
+ }
+ */
+
+ public Cell cell(int col, int row) {
+ if (col<0) return null;
+ if (row<0) return null;
+ if (col>=getWidth()) return null;
+ if (row>=getHeight()) return null;
+ return new Cell(col, row);
+ }
+
+ public final class Cell {
+ public final int col;
+ public final int row;
+
+ public void setColumnClock(int where) {
+ mode4(0x50, 0x00, col, where);
+ }
+
+ public String toString() { return "cell@("+col+","+row+")"; }
+
+ public Cell(int col, int row) {
+ this.row = row;
+ this.col = col;
+ }
+
+ public FpslicDevice fpslic() { return FpslicDevice.this; }
+ public int hashCode() { return col ^ row ^ FpslicDevice.this.hashCode(); }
+ public boolean equals(Object o) {
+ if (o==null || (!(o instanceof Cell))) return false;
+ Cell c = (Cell)o;
+ return c.col == col && c.row == row && c.fpslic()==fpslic();
+ }
+
+ // Accessors for Neighbors //////////////////////////////////////////////////////////////////////////////
+
+ public SectorWire hwire(int plane) { return new SectorWire(true, plane, col, row); }
+ public SectorWire vwire(int plane) { return new SectorWire(false, plane, col, row); }
+ public Cell east() { return cell(col+1, row); }
+ public Cell west() { return cell(col-1, row); }
+ public Cell north() { return cell(col, row+1); }
+ public Cell south() { return cell(col, row-1); }
+ public Cell ne() { return cell(col+1, row+1); }
+ public Cell nw() { return cell(col-1, row+1); }
+ public Cell se() { return cell(col+1, row-1); }
+ public Cell sw() { return cell(col-1, row-1); }
+ public Sector sector() { return new Sector(this); }
+
+ /* bit positions mean: [MSB] zxy z_y zx_ z__ _xy __y _x_ ___ [LSB] */
+ public void lut(int xlut, int ylut) { xlut(xlut); ylut(ylut); }
+ public void xlut(int table) { mode4(7, row, col, (byte)(table & 0xff)); }
+ public byte xlut() { return (byte)(mode4(7, row, col) & 0xff); }
+
+ public String str(int x, String def) {
+ switch(x) {
+ case NORTH: return "n";
+ case SOUTH: return "s";
+ case EAST: return "e";
+ case WEST: return "w";
+ case NW: return "nw";
+ case SE: return "se";
+ case NE: return "ne";
+ case SW: return "sw";
+ case FB: return "fb";
+ case L0: return (hx(0)&&vx(0))?"HV0":hx(0)?"H0":vx(0)?"V0":"L0";
+ case L1: return (hx(1)&&vx(1))?"HV1":hx(1)?"H1":vx(1)?"V1":"L1";
+ case L2: return (hx(2)&&vx(2))?"HV2":hx(2)?"H2":vx(2)?"V2":"L2";
+ case L3: return (hx(3)&&vx(3))?"HV3":hx(3)?"H3":vx(3)?"V3":"L3";
+ case L4: return (hx(4)&&vx(4))?"HV4":hx(4)?"H4":vx(4)?"V4":"L4";
+ default: return def;
+ }
+ }
+
+ /* bit positions mean: [MSB] zxy zx_ z_y z__ _xy _x_ __y ___ [LSB] */
+ public void ylut(int table) { mode4(6, row, col, (byte)(table & 0xff)); }
+ public byte ylut() { return (byte)(mode4(6, row, col) & 0xff); }
+
+ public void ff_reset_value(boolean value) {
+ //mode4( /* FIXME WRONG!!! */, row, col, 3, !value); return;
+ }
+ /** FIXME!!! */
+ public boolean ff_reset_value() { return false; }
+ public boolean columnClocked() {
+ return false;
+ }
+
+ public void out(int plane, boolean enable) {
+ switch(plane) {
+ case L0: mode4(0x00, row, col, 2, enable); return;
+ case L1: mode4(0x00, row, col, 3, enable); return;
+ case L2: mode4(0x00, row, col, 5, enable); return;
+ case L3: mode4(0x00, row, col, 4, enable); return;
+ case L4: mode4(0x00, row, col, 1, enable); return;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+
+ public boolean out(int plane) {
+ switch(plane) {
+ case L0: return (mode4(0x00, row, col) & (1<<2)) != 0;
+ case L1: return (mode4(0x00, row, col) & (1<<3)) != 0;
+ case L2: return (mode4(0x00, row, col) & (1<<5)) != 0;
+ case L3: return (mode4(0x00, row, col) & (1<<4)) != 0;
+ case L4: return (mode4(0x00, row, col) & (1<<1)) != 0;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+
+ public void h(int plane, boolean enable) {
+ switch(plane) {
+ case 0: mode4(0x08, row, col, 0, enable); return;
+ case 1: mode4(0x08, row, col, 2, enable); return;
+ case 2: mode4(0x08, row, col, 5, enable); return;
+ case 3: mode4(0x08, row, col, 6, enable); return;
+ case 4: mode4(0x00, row, col, 6, enable); return;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+
+ public boolean hx(int plane) {
+ switch(plane) {
+ case 0: return (mode4(0x08, row, col) & (1<<0)) != 0;
+ case 1: return (mode4(0x08, row, col) & (1<<2)) != 0;
+ case 2: return (mode4(0x08, row, col) & (1<<5)) != 0;
+ case 3: return (mode4(0x08, row, col) & (1<<6)) != 0;
+ case 4: return (mode4(0x00, row, col) & (1<<6)) != 0;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+
+ public void v(int plane, boolean enable) {
+ switch(plane) {
+ case 0: mode4(0x08, row, col, 1, enable); return;
+ case 1: mode4(0x08, row, col, 3, enable); return;
+ case 2: mode4(0x08, row, col, 4, enable); return;
+ case 3: mode4(0x08, row, col, 7, enable); return;
+ case 4: mode4(0x00, row, col, 7, enable); return;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+
+ public boolean vx(int plane) {
+ switch(plane) {
+ case 0: return (mode4(0x08, row, col) & (1<<1)) != 0;
+ case 1: return (mode4(0x08, row, col) & (1<<3)) != 0;
+ case 2: return (mode4(0x08, row, col) & (1<<4)) != 0;
+ case 3: return (mode4(0x08, row, col) & (1<<7)) != 0;
+ case 4: return (mode4(0x00, row, col) & (1<<7)) != 0;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+
+
+ public int ti_source() {
+ switch(mode4(1, row, col) & 0x30) {
+ case 0x20: return zi();
+ case 0x10: return FB;
+ case 0x00: return wi();
+ default: throw new Error("ack!");
+ }
+ }
+
+ public int t() {
+ switch(mode4(1, row, col) & 0x30) {
+ case 0x00: return TMUX_W;
+ case 0x10: return wi()==NONE ? TMUX_FB : TMUX_W_AND_FB;
+ case 0x20: return wi()==NONE ? TMUX_Z : TMUX_W_AND_Z;
+ case 0x30: throw new RuntimeException("illegal!");
+ default: return TMUX_W;
+ }
+ }
+
+ public void t(int code) {
+ int result = 0;
+ switch(code) {
+ case TMUX_W: result = 0x00; break;
+ case TMUX_Z: result = 0x20; break;
+ case TMUX_W_AND_Z: result = 0x20; break;
+ case TMUX_FB: result = 0x10; break;
+ case TMUX_W_AND_FB: result = 0x10; break;
+ default: result = 0x00; break;
+ }
+ mode4(1, row, col, result, 0x30);
+ }
+ /*
+ private void fmux(int source) {
+ switch(source) {
+ case ZMUX:
+ case FB:
+ case ALWAYS_ON:
+ default: throw new Error("unknown argument to fmux()");
+ }
+ }
+
+ public boolean win_easable() {
+ }
+ */
+
+ public int ti() {
+ return mode4(1, row, col) & 0x34;
+ }
+
+ public void t(boolean ignore_z_and_fb, boolean zm_drives_fb, boolean fb_drives_wm) {
+ // still not totally satisfied...
+ // need to find the bit that sets the w-mux off
+ // what does it mean for both bits (0x30) to be set to 1?
+ //if (fb && z) throw new RuntimeException("invalid combination");
+ int result = 0;
+ // ZM->FB = 0x04
+ // FB->WM = 0x10
+ // WZ->WM = 0x20
+
+ // tff => w&z [0x20]
+ // fff => w [0x00]
+ // ttt => fb&w [0x34]
+ // ftt => fb&w [0x14]
+ // fft => fb&w [0x10]
+
+ // ttf => w&z [0x24]
+ // ftf => w [0x04]
+ // tft => fb&w [0x30]
+ if (ignore_z_and_fb) result |= 0x20;
+ if (zm_drives_fb) result |= 0x04;
+ if (fb_drives_wm) result |= 0x10;
+ mode4(1, row, col, result, 0x34);
+ }
+
+
+ public void c(int source) {
+ switch(source) {
+ case XLUT: mode4(1, row, col, 0x00, 0xc0); break;
+ case YLUT: mode4(1, row, col, 0x40, 0xc0); break;
+ case ZMUX: mode4(1, row, col, 0x80, 0xc0); break;
+ default: throw new RuntimeException("Invalid Argument");
+ }
+ }
+ public int c() {
+ int cval = mode4(1, row, col) & 0xc0;
+ switch (cval) {
+ case 0x00: return XLUT;
+ case 0x40: return YLUT;
+ case 0x80: return ZMUX;
+ }
+ throw new Error("c() => " + cval);
+ }
+ public void b(boolean registered) { mode4(1, row, col, 3, !registered); }
+ public void f(boolean registered) { mode4(1, row, col, 2, !registered); }
+ public boolean xo() { return (mode4(1, row, col) & 0x01) != 0; }
+ public boolean yo() { return (mode4(1, row, col) & 0x02) != 0; }
+ public void xo(boolean center) { mode4(1, row, col, 0, center); }
+ public void yo(boolean center) { mode4(1, row, col, 1, center); }
+
+ public void xo(Cell c) {
+ if (c.row==row || c.col==col) { // use the y-input
+ xlut(LUT_OTHER);
+ yi(c);
+ } else {
+ xlut(LUT_SELF);
+ xi(c);
+ }
+ xo(false);
+ }
+
+ public void yo(Cell c) {
+ if (!(c.row==row || c.col==col)) { // use the x-input
+ ylut(LUT_OTHER);
+ xi(c);
+ } else {
+ ylut(LUT_SELF);
+ yi(c);
+ }
+ yo(false);
+ }
+
+ public boolean b() { return (mode4(1, row, col) & (1 << 3)) == 0; }
+ public boolean f() { return (mode4(1, row, col) & (1 << 2)) == 0; }
+ public boolean x() { return (mode4(1, row, col) & (1 << 1)) != 0; }
+ public boolean y() { return (mode4(1, row, col) & (1 << 0)) != 0; }
+
+ public int oe() {
+ switch (mode4(0x02, row, col) & 0x3) {
+ case 0: return NONE;
+ case 1: return H4;
+ case 2: return V4;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+ public void oe(int source) {
+ switch(source) {
+ case NONE: mode4(0x02, row, col, 0, 0x3); break;
+ case H4: mode4(0x02, row, col, 1, 0x3); break;
+ case V4: mode4(0x02, row, col, 2, 0x3); break;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+
+ public int xi() {
+ // FIXME: can be multiple
+ if ((mode4(0x03, row, col) & (1<<4))!=0) return L4;
+ switch(mode4(0x05, row, col) & 0xff) {
+ case 0x80: return SW;
+ case (1<<6): return NE;
+ case (1<<5): return SE;
+ case (1<<4): return NW;
+ case (1<<3): return L0;
+ case (1<<2): return L1;
+ case (1<<1): return L2;
+ case (1<<0): return L3;
+ case 0: return NONE;
+ default: throw new Error();
+ }
+ }
+
+ public void xi(int source) {
+ switch(source) {
+ case SW: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 1<<7); break;
+ case NE: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 1<<6); break;
+ case SE: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 1<<5); break;
+ case NW: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 1<<4); break;
+
+ case L0: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 1<<3); break;
+ case L1: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 1<<2); break;
+ case L2: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 1<<1); break;
+ case L3: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 1<<0); break;
+ case L4: mode4(0x03, row, col, 4, true); mode4(0x05, row, col, 0); break;
+
+ case NONE: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 0); break;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+
+ public void xi(SectorWire sw) {
+ if (!sw.touches(this)) throw new RuntimeException("invalid argument");
+ xi(sw.plane);
+ }
+
+ public void xi(Cell c) {
+ if (c.row==row-1 && c.col==col-1) xi(SW);
+ else if (c.row==row+1 && c.col==col-1) xi(NW);
+ else if (c.row==row-1 && c.col==col+1) xi(SE);
+ else if (c.row==row+1 && c.col==col+1) xi(NE);
+ else throw new RuntimeException("invalid argument");
+ }
+
+ public int yi() {
+ if ((mode4(0x02, row, col) & (1<<6))!=0) return L4;
+ switch(mode4(0x04, row, col) & 0xff) {
+ case (1<<7): return NORTH;
+ case (1<<5): return SOUTH;
+ case (1<<6): return WEST;
+ case (1<<4): return EAST;
+ case (1<<3): return L0;
+ case (1<<2): return L1;
+ case (1<<1): return L2;
+ case (1<<0): return L3;
+ case 0: return NONE;
+ default: throw new Error();
+ }
+ }
+
+ public void yi(int source) {
+ switch(source) {
+ case NORTH: mode4(0x02, row, col, 6, false); mode4(0x04, row, col, 1<<7); break;
+ case SOUTH: mode4(0x02, row, col, 6, false); mode4(0x04, row, col, 1<<5); break;
+ case WEST: mode4(0x02, row, col, 6, false); mode4(0x04, row, col, 1<<6); break;
+ case EAST: mode4(0x02, row, col, 6, false); mode4(0x04, row, col, 1<<4); break;
+ case L4: mode4(0x02, row, col, 6, true); mode4(0x04, row, col, 0); break;
+ case L3: mode4(0x02, row, col, 6, false); mode4(0x04, row, col, 1<<0); break;
+ case L2: mode4(0x02, row, col, 6, false); mode4(0x04, row, col, 1<<1); break;
+ case L1: mode4(0x02, row, col, 6, false); mode4(0x04, row, col, 1<<2); break;
+ case L0: mode4(0x02, row, col, 6, false); mode4(0x04, row, col, 1<<3); break;
+ case NONE: mode4(0x02, row, col, 6, false); mode4(0x04, row, col, 0); break;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+
+ public void yi(SectorWire sw) {
+ if (!sw.touches(this)) throw new RuntimeException("invalid argument");
+ yi(sw.plane);
+ }
+
+ public void yi(Cell c) {
+ if (c.row==row-1 && c.col==col) yi(SOUTH);
+ else if (c.row==row+1 && c.col==col) yi(NORTH);
+ else if (c.row==row && c.col==col-1) yi(WEST);
+ else if (c.row==row && c.col==col+1) yi(EAST);
+ else throw new RuntimeException("invalid argument");
+ }
+
+ public void wi(SectorWire sw) {
+ if (!sw.touches(this)) throw new RuntimeException("invalid argument");
+ wi(sw.plane);
+ }
+
+ public void wi(int source) {
+ switch(source) {
+ case L4: mode4(0x03, row, col, 1<<5, 0xEC); break;
+ case L3: mode4(0x03, row, col, 1<<6, 0xEC); break;
+ case L2: mode4(0x03, row, col, 1<<7, 0xEC); break;
+ case L1: mode4(0x03, row, col, 1<<3, 0xEC); break;
+ case L0: mode4(0x03, row, col, 1<<2, 0xEC); break;
+ case NONE: mode4(0x03, row, col, 0, 0xEC); break;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+
+ public int wi() {
+ int who = mode4(0x03, row, col) & 0xEC;
+ switch(who) {
+ case (1<<5): return L4;
+ case (1<<6): return L3;
+ case (1<<7): return L2;
+ case (1<<3): return L1;
+ case (1<<2): return L0;
+ case (1<<0): return NONE; /* huh? */
+ case (0): return NONE;
+ default: throw new RuntimeException("invalid argument: " + who);
+ }
+ }
+
+
+ public void zi(SectorWire sw) {
+ if (!sw.touches(this)) throw new RuntimeException("invalid argument");
+ zi(sw.plane);
+ }
+
+ public void zi(int source) {
+ switch(source) {
+ case L4: mode4(0x02, row, col, 1<<7, 0xDB); break;
+ case L3: mode4(0x02, row, col, 1<<5, 0xDB); break;
+ case L2: mode4(0x02, row, col, 1<<4, 0xDB); break;
+ case L1: mode4(0x02, row, col, 1<<3, 0xDB); break;
+ case L0: mode4(0x02, row, col, 1<<2, 0xDB); break;
+ case NONE: mode4(0x02, row, col, 0, 0xDB); break;
+ default: throw new RuntimeException("invalid argument");
+ }
+ }
+
+ public int zi() {
+ switch(mode4(0x02, row, col) & 0x9B) {
+ case (1<<7): return L4;
+ case (1<<5): return L3;
+ case (1<<4): return L2;
+ case (1<<3): return L1;
+ case (1<<2): return L0;
+ case (1<<1): return NONE; /* huh? */
+ case (1<<0): return NONE; /* huh? */
+ case 0: return NONE;
+ default: throw new RuntimeException("invalid argument: zi=="+(mode4(0x02, row, col) & 0x9B));
+ }
+ }
+
+ public Cell dir(int i) {
+ switch(i) {
+ case NORTH: return north();
+ case SOUTH: return south();
+ case EAST: return east();
+ case WEST: return west();
+ case NW: return nw();
+ case SW: return sw();
+ case SE: return se();
+ case NE: return ne();
+ }
+ return null;
+ }
+ public int dir(Cell c) {
+ if (c.row==row-1 && c.col==col-1) return SW;
+ else if (c.row==row+1 && c.col==col-1) return NW;
+ else if (c.row==row-1 && c.col==col+1) return SE;
+ else if (c.row==row+1 && c.col==col+1) return NE;
+ else if (c.row==row-1 && c.col==col) return SOUTH;
+ else if (c.row==row+1 && c.col==col) return NORTH;
+ else if (c.row==row && c.col==col-1) return WEST;
+ else if (c.row==row && c.col==col+1) return EAST;
+ return -1;
+ }
+
+ public void generalized_c_element() {
+
+ /*
+ ylut(LUT_SELF & (~LUT_OTHER));
+ xlut((~LUT_SELF) | LUT_OTHER);
+ c(ZMUX);
+ zi(L2);
+ //h(L2, true);
+ out(L2, true);
+ xo(true);
+ yo(true);
+ */
+
+ //ylut(0xB2);
+ ylut((LUT_SELF & ~LUT_OTHER) | (LUT_Z & ~LUT_OTHER) | (LUT_Z & LUT_SELF & LUT_OTHER));
+ xlut(LUT_Z);
+ c(YLUT);
+ f(false);
+ b(false);
+ t(false, false, true);
+ yo(false);
+ xo(false);
+ }
+
+
+ // Relevance //////////////////////////////////////////////////////////////////////////////
+ public boolean relevant() {
+ return xo_relevant() || yo_relevant() || out_relevant();
+ }
+
+ public boolean xo_relevant() { return xo_relevant(NE) || xo_relevant(SE) || xo_relevant(NW) || xo_relevant(SW); }
+ public boolean xo_relevant(int direction) {
+ switch(direction) {
+ case NE: return ne() != null && ne().xi()==SW;
+ case NW: return nw() != null && nw().xi()==SE;
+ case SE: return se() != null && se().xi()==NW;
+ case SW: return sw() != null && sw().xi()==NE;
+ default: return false;
+ }
+ }
+ public boolean yo_relevant() { return yo_relevant(NORTH) || yo_relevant(SOUTH) || yo_relevant(EAST) || yo_relevant(WEST); }
+ public boolean yo_relevant(int direction) {
+ switch(direction) {
+ case NORTH: return north() != null && north().yi()==SOUTH /*&& north().yi_relevant()*/;
+ case EAST: return east() != null && east().yi()==WEST /*&& east().yi_relevant()*/;
+ case SOUTH: return south() != null && south().yi()==NORTH /*&& south().yi_relevant()*/;
+ case WEST: return west() != null && west().yi()==EAST /*&& west().yi_relevant()*/;
+ default: return false;
+ }
+ }
+ public boolean xi_relevant() { return xi_to_xlut_relevant() || xi_to_ylut_relevant(); }
+ public boolean yi_relevant() { return yi_to_xlut_relevant() || yi_to_ylut_relevant(); }
+ public boolean xi_to_ylut_relevant() { return (((ylut() & 0xcc) >> 2) != (ylut() & 0x33)); }
+ public boolean yi_to_xlut_relevant() { return (((xlut() & 0xcc) >> 2) != (xlut() & 0x33)); }
+ public boolean zi_to_xlut_relevant() { return (((xlut() & LUT_Z) >> 4) != (xlut() & LUT_Z)); }
+ public boolean zi_to_ylut_relevant() { return (((ylut() & LUT_Z) >> 4) != (ylut() & LUT_Z)); }
+ public boolean xi_to_xlut_relevant() { return (((xlut() & LUT_SELF) >> 1) != (xlut() & (LUT_SELF >> 1))); }
+ public boolean yi_to_ylut_relevant() { return (((ylut() & LUT_SELF) >> 1) != (ylut() & (LUT_SELF >> 1))); }
+ public boolean xlut_relevant() {
+ if ((c()==XLUT || c()==ZMUX) && c_relevant()) return true;
+ if (xo()) return false;
+ return xo_relevant();
+ }
+ public boolean ylut_relevant() {
+ if ((c()==YLUT || c()==ZMUX) && c_relevant()) return true;
+ if (yo()) return false;
+ return yo_relevant();
+ }
+ public boolean c_relevant() {
+ switch(ti()) {
+ case 0x34: return true;
+ case 0x14: return true;
+ case 0x10: return true;
+ case 0x30: return true;
+ }
+ for(int i=0; i<5; i++)
+ if (out(i))
+ return true;
+ if (xo() || yo()) return true;
+ return false;
+ }
+
+ public boolean register_relevant() {
+ if (!c_relevant()) return false;
+ if (f() && out_relevant()) return true;
+ if (f() && fb_relevant()) return true;
+ if (b() && xo()) return true;
+ if (b() && yo()) return true;
+ return false;
+ }
+ public boolean out_relevant() {
+ boolean out = false;
+ boolean connect = false;
+ for(int i=0; i<4; i++) {
+
+ // FIXME FIXME FIXME
+ if (i==3) continue;
+
+ if (out(L0+i)) out = true;
+ if (hx(L0+i)) connect = true;
+ if (vx(L0+i)) connect = true;
+ }
+ return out && connect;
+ }
+
+ public boolean fb_relevant() {
+ /*
+ if (!(zi_to_xlut_relevant()) ||
+ !(zi_to_ylut_relevant())) return false;
+ switch(ti()) {
+ case 0x34: return true;
+ case 0x14: return true;
+ case 0x10: return true;
+ case 0x30: return true;
+ }
+ return false;
+ */
+ return true;
+ }
+
+
+ }
+
+ public IOB iob_bot(int col, boolean primary) { return new IOB(col, 0, primary, true); }
+ public IOB iob_top(int col, boolean primary) { return new IOB(col, 1, primary, true); }
+ public IOB iob_left(int row, boolean primary) { return new IOB(0, row, primary, false); }
+ public IOB iob_right(int row, boolean primary) { return new IOB(1, row, primary, false); }
+ /*
+ public IOB fromPin(int pin) {
+ if (pin >= 4 && pin <= 11) return io(pin-3);
+ if (pin >= 15 && pin <= 18) return io(pin-2);
+ if (pin >= 19 && pin <= 24) return io(pin);
+ if (pin >= 27 && pin <= 30) return io(pin-2);
+ if (pin >= 33 && pin <= 36) return io(pin);
+ if (pin >= 38 && pin <= 47) return io(pin+1);
+
+
+ if (pin >= 33 && pin <= 36) return io(pin+36);
+ if (pin >= 38 && pin <= 41) return io(pin+43);
+ if (pin >= 42 && pin <= 43) return io(pin+47);
+ if (pin >= 44 && pin <= 47) return io(pin+49);
+ if (pin >= 57 && pin <= 62) return io(pin+40);
+ if (pin >= 63 && pin <= 66) return io(pin+46);
+ if (pin >= 68 && pin <= 71) return io(pin+53);
+ if (pin >= 72 && pin <= 73) return io(pin+53);
+ if (pin >= 74 && pin <= 75) return io(pin+63);
+ if (pin >= 76 && pin <= 77) return io(143+(pin-76));
+ if (pin >= 80 && pin <= 81) return io(145+(pin-80));
+ if (pin >= 82 && pin <= 85) return io(151+(pin-82));
+ if (pin >= 86 && pin <= 89) return io(165+(pin-86));
+ if (pin >= 91 && pin <= 94) return io(177+(pin-91));
+ if (pin >= 95 && pin <= 96) return io(183+(pin-95));
+ if (pin >= 97 && pin <= 100) return io(189+(pin-97));
+ if (pin >= 161 && pin <= 164) return io(289+(pin-161));
+ if (pin >= 165 && pin <= 166) return io(297+(pin-165));
+ if (pin >= 167 && pin <= 168) return io(303+(pin-167));
+ if (pin >= 169 && pin <= 170) return io(309+(pin-169));
+ if (pin >= 172 && pin <= 173) return io(313+(pin-172));
+ if (pin >= 174 && pin <= 175) return io(325+(pin-174));
+ if (pin >= 176 && pin <= 179) return io(327+(pin-176));
+ if (pin >= 180 && pin <= 181) return io(335+(pin-180));
+ if (pin >= 184 && pin <= 185) return io(337+(pin-184));
+ if (pin >= 186 && pin <= 191) return io(343+(pin-186));
+ if (pin >= 192 && pin <= 193) return io(359+(pin-192));
+ if (pin >= 195 && pin <= 196) return io(363+(pin-195));
+ if (pin >= 197 && pin <= 200) return io(369+(pin-197));
+ if (pin >= 201 && pin <= 204) return io(381+(pin-201));
+ }
+ public io(int ionum) {
+ if (ionum <= 94) {
+ int cell = (94 - pin) / 2;
+ boolean primary = cell * 2 == (94-pin);
+ }
+ }
+ */
+ public final class IOB {
+ public final int col;
+ public final int row;
+ public final boolean primary;
+ public final boolean northsouth;
+ public IOB(int col, int row, boolean primary, boolean northsouth) {
+ this.col = col;
+ this.row = row;
+ this.northsouth = northsouth;
+ this.primary = primary;
+ }
+ /*
+ public String dump() {
+ System.out.println("[ "+
+ (schmitt()?"schmitt ":"")+
+ (slew()==3?"fast ":slew()==2?"med ":slew()==1?"slow ":"slew-unknown ")+
+ (cr()?"cr ":"")+
+ (reg()?"reg ":"")+
+
+ }
+ */
+ public void enableOutput(int direction) {
+ useoem(true);
+ output(direction);
+ pullnone();
+ useoem(true);
+ oem(ALWAYS_ON);
+ oe(true);
+ // note: east-side IOBs should have slew=med, others slew=fast
+ slew((!northsouth && col==1) ? MEDIUM : FAST);
+ }
+ public void enableInput() {
+ schmitt(true);
+ pullnone();
+ }
+
+ public void useoem(boolean use) { mode4(z(3), row, col, 6, use); }
+ public boolean useoem() { return (mode4(z(3), row, col) & (1<<6))!=0; }
+ public void schmitt(boolean use) { mode4(z(0), row, col, 7, use); }
+ public boolean schmitt() { return (mode4(z(0), row, col) & (1<<7))!=0; }
+
+ public void slew(int slew) {
+ switch(slew) {
+ case FAST: mode4(z(0), row, col, 3<<5, 0x60); return;
+ case MEDIUM: mode4(z(0), row, col, 2<<5, 0x60); return;
+ case SLOW: mode4(z(0), row, col, 1<<5, 0x60); return;
+ default: throw new Error();
+ }
+ }
+
+ public void oem(int source) {
+ switch(source) {
+ case ALWAYS_ON: mode4(z(3), row, col, 1<<5, 0x3f); return;
+ case ALWAYS_OFF: mode4(z(3), row, col, 0, 0x3f); return;
+ default: throw new Error();
+ }
+ }
+
+ private int z(int code) { return (northsouth ? 0x70 : 0x60) | (primary ? 0x00 : 0x04) | (code & 0x7); }
+ public void pullup() { mode4(z(0), row, col, 0x00<<1, 0x06); }
+ public void pulldown() { mode4(z(0), row, col, 0x03<<1, 0x06); }
+ public void pullnone() { mode4(z(0), row, col, 0x01<<1, 0x06); }
+ public void oe(boolean oe) {
+ int old = mode4(z(1), row, col) & (~(1<<5));
+ old |= oe ? 0 : (1<<5);
+ mode4(z(1), row, col, old & 0xff);
+ }
+
+ public void output(int which) {
+ switch(which) {
+ case NONE:
+ mode4(z(1), row, col, 0, 0x1f); return;
+ case WEST: case EAST: case NORTH: case SOUTH:
+ mode4(z(1), row, col, 1<<0, 0x1f); return;
+ case NW: case SW: case NE: case SE:
+ mode4(z(1), row, col, 1<<1, 0x1f); return;
+ default: throw new Error();
+ }
+ }
+
+ }
+
+ public void readMode4(Reader r) throws IOException {
+ int count = 0;
+ BufferedReader br = new BufferedReader(r);
+ for(String str = br.readLine(); str != null; str = br.readLine()) {
+ long foo = Long.parseLong(str, 16);
+ mode4((int)(foo >> 24), (int)(foo >> 16), (int)(foo >> 8), (int)(foo >> 0));
+ count++;
+ }
+ flush();
+ r.close();
+ }
+
+ public void writeMode4(Writer w) throws IOException {
+ // FIXME: there are resources "above" the top of the device
+ for(int x=0; x<getWidth(); x++)
+ for(int y=0; y<getWidth(); y++)
+ for(int z=0; z<255; z++) {
+ if ((z > 0x09 && z < 0x10) ||
+ (z > 0x11 && z < 0x20) ||
+ (z > 0x29 && z < 0x30) ||
+ (z > 0x39 && z < 0x40) ||
+ (z > 0x41 && z < 0x60) ||
+ (z > 0x67 && z < 0x70) ||
+ (z > 0x77 && z < 0xD0) ||
+ (z > 0xD3))
+ continue;
+ w.write(hex2(z));
+ w.write(hex2(y));
+ w.write(hex2(x));
+ w.write(hex2(mode4(z, y, x) & 0xff));
+ w.write('\n');
+ }
+ w.flush();
+ }
+
+ private static String hex2(int i) {
+ String ret = Integer.toString(i, 16);
+ while(ret.length() < 2) ret = "0"+ret;
+ return ret.toUpperCase();
+ }
+
+}
--- /dev/null
+package edu.berkeley.abits;
+
+import edu.berkeley.abits.*;
+import java.io.*;
+
+/** interface for controlling an FPGA on a development board */
+public interface Board {
+
+ /** "deepest" possible reset of the FPGA */
+ public void reset() throws IOException;
+
+ /** return an OutputStream to which a configuration bitstream may be written */
+ public OutputStream getConfigStream() throws IOException;
+
+ /** InputStream for communicating with the device after configuration */
+ public InputStream getInputStream() throws IOException;
+
+ /** OutputStream for communicating with the device after configuration */
+ public OutputStream getOutputStream() throws IOException;
+
+ /** causes the device to perform a self-test */
+ public void selfTest(SelfTestResultListener resultListener) throws Exception;
+
+ /** returns the actual device on the board */
+ public Device getDevice();
+
+ public static interface SelfTestResultListener {
+ public void reportTestResult(int testNumber, int totalNumberOfTests, boolean didPass);
+ }
+}
--- /dev/null
+package edu.berkeley.abits;
+
+public interface Device {
+
+ public int getWidth();
+ public int getHeight();
+
+}
--- /dev/null
+package edu.berkeley.slipway;
+
+import java.io.*;
+import java.util.*;
+import com.ftdi.usb.*;
+import com.atmel.fpslic.*;
+import edu.berkeley.abits.*;
+import org.ibex.util.*;
+
+// FEATURE: more state checking (ie must have reset high before uart-mode, etc)
+
+/**
+ * Slipway board (Fpslic via FTDI USB-UART, running <tt>SlipwaySlave.c</tt>)
+ */
+public class SlipwayBoard extends FpslicBoard {
+
+ // Private Variables //////////////////////////////////////////////////////////////////////////////
+
+ private final DataInputStream in;
+ private final DataOutputStream out;
+ private final FpslicDevice device;
+ private final FtdiUart ftdiuart;
+ private boolean initialized = false;
+
+
+ // Accessors //////////////////////////////////////////////////////////////////////////////////////
+
+ public InputStream getInputStream() { return in; }
+ public OutputStream getOutputStream() { return out; }
+
+ /** just a different return type for <tt>getDevice()</tt> */
+ public FpslicDevice getFpslicDevice() { return (FpslicDevice)getDevice(); }
+ public Device getDevice() { return device; }
+
+
+ // Methods //////////////////////////////////////////////////////////////////////////////////////
+
+ /** initialize assuming default USB settings and only one board connected to the system, perform self-test */
+ public SlipwayBoard() throws Exception { this(true); }
+
+ /** initialize assuming default USB settings and only one board connected to the system */
+ public SlipwayBoard(boolean selfTest) throws Exception {
+ this(new FtdiUart(0x6666, 0x3133, 1500 * 1000/2), selfTest);
+ }
+
+ /** initialize with a custom USB interface */
+ public SlipwayBoard(FtdiUart ftdiuart, boolean selfTest) throws Exception {
+ this.ftdiuart = ftdiuart;
+ device = new SlipwayFpslicDevice(24, 24);
+ String bstFile = this.getClass().getName();
+ bstFile = bstFile.substring(0, bstFile.lastIndexOf('.'));
+ bstFile = bstFile.replace('.', '/')+"/slipway_drone.bst";
+ if (selfTest) selfTest();
+ boot(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream(bstFile)));
+ in = new DataInputStream(ftdiuart.getInputStream());
+ out = new DataOutputStream(ftdiuart.getOutputStream());
+ for(int i=0; i<255; i++) out.write(0);
+ out.flush();
+ init(selfTest);
+ }
+
+ private void selfTest() throws IOException {
+ System.err.print("smoke check: ");
+ selfTest(new edu.berkeley.abits.Board.SelfTestResultListener() {
+ public void reportTestResult(int testNumber, int totalNumberOfTests, boolean didPass) {
+ System.err.print(didPass ? " \033[32m[pass]\033[0m " : " \033[31m[FAIL]\033[0m ");
+ }
+ });
+ System.err.println();
+ }
+
+ private void boot(Reader r) throws IOException {
+ int total = 75090/9;
+ OutputStream os = new ProgressOutputStream("bootstrap bitstream:", getConfigStream(), total);
+ BufferedReader br = new BufferedReader(r);
+ int bytes = 0;
+ while(true) {
+ String s = br.readLine();
+ if (s==null) break;
+ bytes++;
+ os.write((byte)Integer.parseInt(s, 2));
+ if ((bytes % 1000)==0) os.flush();
+ }
+ os.close();
+ }
+
+ private void init(boolean verbose) throws IOException {
+ if (initialized) throw new Error("cannot initialize twice");
+ initialized = true;
+ byte[] bytes = new byte[6];
+ int i=0;
+
+ out.write(0);
+ out.flush();
+
+ // read any garbage that might be left in the buffer
+ while(true) {
+ System.arraycopy(bytes, 1, bytes, 0, 5);
+ bytes[5] = in.readByte();
+ i++;
+ if (verbose) System.err.print("\rsignature: read \"" + new String(bytes) + "\" ");
+ if (bytes[0] == (byte)'O' &&
+ bytes[1] == (byte)'B' &&
+ bytes[2] == (byte)'I' &&
+ bytes[3] == (byte)'T' &&
+ bytes[4] == (byte)'S') {
+ if (verbose) System.err.println("\rsignature: got proper signature ");
+ purge();
+ break;
+ }
+ }
+
+ new Thread() {
+ public void run() {
+ while(true) {
+ try {
+ while(callbacks.size() == 0) Thread.sleep(50);
+ byte b = in.readByte();
+ ByteCallback bc = (ByteCallback)callbacks.remove(0);
+ bc.call(b);
+ synchronized(lock) {
+ lock.notifyAll();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }.start();
+ }
+
+
+ // Device //////////////////////////////////////////////////////////////////////////////
+
+ public class SlipwayFpslicDevice extends FpslicDevice {
+ private final byte[][][] cache = new byte[24][][];
+
+ // FEATURE: autodetect width/height by querying device id from the chip
+ public SlipwayFpslicDevice(int width, int height) {
+ super(width, height);
+ }
+
+ public synchronized byte mode4(int z, int y, int x) {
+ if (cache[x]==null) return 0;
+ if (cache[x][y]==null) return 0;
+ return cache[x][y][z];
+ }
+ public synchronized void mode4(int z, int y, int x, int d) {
+ try {
+ if (cache[x & 0xff]==null) cache[x & 0xff] = new byte[24][];
+ if (cache[x & 0xff][y & 0xff]==null) cache[x & 0xff][y & 0xff] = new byte[256];
+ cache[x & 0xff][y & 0xff][z & 0xff] = (byte)(d & 0xff);
+
+ out.writeByte(1);
+ out.writeByte(z);
+ out.writeByte(y);
+ out.writeByte(x);
+ out.writeByte(d);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ public synchronized void flush() {
+ try {
+ SlipwayBoard.this.flush();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+
+ // Callbacks //////////////////////////////////////////////////////////////////////////////
+
+ private static final int CALLBACK_LIMIT = 40;
+ private Vector callbacks = new Vector();
+ private Object lock = new Object();
+ private int timer = 0;
+
+ private void enqueue(ByteCallback bcb) {
+ synchronized(lock) {
+ try {
+ while (callbacks.size() >= CALLBACK_LIMIT) {
+ lock.wait(100);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ callbacks.add(bcb);
+ }
+
+ public static abstract class ByteCallback {
+ public int result;
+ public abstract void call(byte b) throws Exception;
+ }
+
+ /** synchronously returns the number of interrupts triggered since the last call to <tt>readInterruptCount()</tt> */
+ public synchronized int readInterruptCount() {
+ try {
+ ByteCallback bc = new ByteCallback() {
+ public synchronized void call(byte b) throws Exception {
+ result =
+ ((b & 0xff) << 24) |
+ ((in.read() & 0xff) << 16) |
+ ((in.read() & 0xff) << 8) |
+ ((in.read() & 0xff) << 0);
+ timer =
+ ((in.read() & 0xff) << 24) |
+ ((in.read() & 0xff) << 16) |
+ ((in.read() & 0xff) << 8) |
+ ((in.read() & 0xff) << 0);
+ this.notify();
+ }
+ };
+ synchronized(bc) {
+ enqueue(bc);
+ out.writeByte(3);
+ out.flush();
+ bc.wait();
+ }
+ return bc.result;
+ } catch (Exception e) { throw new RuntimeException(e); }
+ }
+
+ /** returns the number of milliseconds elapsed between the previous call to readInterruptCount() and the one before it */
+ public synchronized int readInterruptCountTime() {
+ return timer;
+ }
+
+ /** reads the values on the 8-bit bus connecting the fpga to the AVR */
+ public synchronized void readFpgaData(ByteCallback bc) throws IOException {
+ enqueue(bc);
+ out.writeByte(2);
+ out.flush();
+ }
+
+
+ // Pin Implementations //////////////////////////////////////////////////////////////////////////////
+
+ private int dbits = 0;
+ private int dmask =
+ (1<<0) |
+ (1<<1) |
+ (1<<2) |
+ //(1<<3) |
+ //(1<<4) |
+ (1<<5) |
+ (1<<6) |
+ (1<<7);
+
+ protected void flush() {
+ try {
+ if (out!=null) out.flush();
+ ftdiuart.getOutputStream().flush();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected void avrrstPin(boolean on) throws IOException { setDBusLine(7, on); }
+ protected void cclkPin(boolean on) throws IOException { setDBusLine(6, on); }
+ protected void configDataPin(boolean on) throws IOException { setDBusLine(5, on); }
+ protected boolean initPin() throws IOException { flush(); return (ftdiuart.readPins() & (1<<4))!=0; }
+
+ // tricky: RESET has a weak pull-up, and is wired to a CBUS line. So,
+ // we can pull it down (assert reset) from uart-mode, or we can
+ // let it float upward from either mode.
+ protected void resetPin(boolean on) throws IOException {
+ ftdiuart.uart_and_cbus_mode(1<<1, on ? (1<<1) : 0);
+ flush();
+ if (on) {
+ ftdiuart.dbus_mode(dmask);
+ flush();
+ }
+ }
+
+ protected void setDBusLine() throws IOException {
+ OutputStream os = ftdiuart.getOutputStream();
+ os.write((byte)dbits);
+ }
+ protected void clearDBusLines() throws IOException {
+ dbits = 0;
+ setDBusLine();
+ }
+ protected void setDBusLine(int bit, boolean val) throws IOException {
+ dbits = val ? (dbits | (1 << bit)) : (dbits & (~(1 << bit)));
+ setDBusLine();
+ }
+ protected void releaseConPin() throws IOException {
+ dmask &= ~(1<<0);
+ ftdiuart.dbus_mode(dmask);
+ flush();
+ }
+ protected void conPin(boolean on) throws IOException {
+ dmask |= (1<<0);
+ ftdiuart.dbus_mode(dmask);
+ setDBusLine(0, on);
+ flush();
+ }
+ public void close() throws IOException {
+ // switching to uart mode will implicitly release AVRRST
+ avrrstPin(false);
+ ftdiuart.purge();
+ ftdiuart.uart_and_cbus_mode(1<<1, 1<<1);
+ ftdiuart.purge();
+ }
+ protected void purge() throws IOException {
+ ftdiuart.purge();
+ }
+
+
+ // Util //////////////////////////////////////////////////////////////////////////////
+
+ private static String pad(int i, String s) {
+ if (s.length()>i) return s;
+ return "0"+pad((i-1),s);
+ }
+ private static String pad(String s, int i) {
+ if (s.length() >= i) return s;
+ return "0"+pad(s, i-1);
+ }
+}
+
--- /dev/null
+//
+// YOU MUST COMPILE THIS WITH -O3 OR THE AVR WILL NOT BE ABLE TO KEEP UP!!!!
+//
+
+#define F_CPU 12000000
+
+#if !defined(__AVR_AT94K__)
+#error you forgot to put -mmcu=at94k on the command line
+#endif
+
+#include <avr/wdt.h>
+#include <util/delay.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+volatile int32_t upper = 0;
+
+int err = 0;
+
+void initUART0(unsigned int baudRate, unsigned int doubleRate) {
+ UBRRHI = (((baudRate) >> 8) & 0x000F);
+ UBRR0 = ((baudRate) & 0x00FF);
+ UCSR0B |= ((1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0));
+
+ if (doubleRate)
+ UCSR0A |= (1 << U2X0);
+ else
+ UCSR0A &= ~(1 << U2X0);
+}
+
+#define BUFSIZE (1024)
+
+long int numread = 0;
+inline void cts(int c) {
+ numread++;
+ if (c) {
+ PORTE &= ~(1 << 7);
+ } else {
+ PORTE |= (1 << 7);
+ }
+}
+
+
+static volatile int sending = 0;
+static volatile int32_t interrupt_count = 0;
+
+// RECV //////////////////////////////////////////////////////////////////////////////
+
+char read_buf[BUFSIZE];
+volatile int read_buf_head;
+volatile int read_buf_tail;
+char write_buf[BUFSIZE];
+volatile int write_buf_head;
+volatile int write_buf_tail;
+
+inline int inc(int x) { x++; if (x>=BUFSIZE) x=0; return x; }
+inline int read_full() { return inc(read_buf_tail)==read_buf_head; }
+inline int abs(int x) { return x<0 ? -x : x; }
+inline int read_size() { return read_buf_tail<read_buf_head ? (read_buf_head-read_buf_tail) : (read_buf_tail-read_buf_head); }
+inline int read_empty() { return read_buf_head==read_buf_tail; }
+inline int read_nearlyFull() {
+ if (read_buf_tail==read_buf_head) return 0;
+ if (read_buf_tail < read_buf_head) return (read_buf_head-read_buf_tail) < (BUFSIZE/2);
+ return (read_buf_tail-read_buf_head) > (BUFSIZE/2);
+}
+
+inline int write_full() { return inc(write_buf_tail)==write_buf_head; }
+inline int write_empty() { return write_buf_head==write_buf_tail; }
+inline int write_nearlyFull() {
+ if (write_buf_tail==write_buf_head) return 0;
+ if (write_buf_tail < write_buf_head) return (write_buf_head-write_buf_tail) < (BUFSIZE/2);
+ return (write_buf_tail-write_buf_head) > (BUFSIZE/2);
+}
+
+int32_t timer = 0;
+
+inline char recv() {
+ int q;
+ char ret;
+
+ PORTE |= (1<<3);
+ while(read_empty()) cts(1);
+ PORTE &= ~(1<<3);
+
+ ret = read_buf[read_buf_head];
+ read_buf_head = inc(read_buf_head);
+ if (!read_nearlyFull()) cts(1);
+ return ret;
+}
+
+// Interrupt Handlers //////////////////////////////////////////////////////////////////////////////
+
+ISR(SIG_UART0_DATA) {
+ if (write_empty()) {
+ UCSR0B &= ~(1 << UDRIE0);
+ return;
+ }
+ char ret = write_buf[write_buf_head];
+ write_buf_head = inc(write_buf_head);
+ UDR0 = (int)ret;
+ sei();
+}
+
+void send(char c) {
+ PORTE |= (1<<2);
+ while (write_full());
+ PORTE &= ~(1<<2);
+ write_buf[write_buf_tail] = c;
+ write_buf_tail = inc(write_buf_tail);
+ UCSR0B |= (1 << UDRIE0);
+}
+
+
+void fpga_interrupts(int on) {
+ if (on) {
+ //FISUA = 0x1;
+ FISCR = 0x80;
+ FISUA = 0x01;
+ } else {
+ FISUA = 0;
+ FISCR = 0;
+ }
+}
+
+inline void conf(int z, int y, int x, int d) {
+ FPGAX = x;
+ FPGAY = y;
+ FPGAZ = z;
+ FPGAD = d;
+}
+
+#define TIMERVAL 100
+
+ISR(SIG_FPGA_INTERRUPT0) {
+ interrupt_count++;
+ sei();
+}
+
+volatile int dead = 0;
+
+ISR(SIG_OVERFLOW1) {
+ upper = upper + 1;
+
+ if (!dead) {
+ if (PORTE & (1<<5)) PORTE &= ~(1<<5);
+ else PORTE |= (1<<5);
+ }
+
+ TCNT1 = 0;
+ sei();
+}
+
+//void die() { dead = 1; cli(); PORTE|=(1<<5); _delay_ms(2000); while(1) { } }
+
+void die(int two, int three, int five) {
+ dead = 1;
+ PORTE &~ ((1<<2) | (1<<3) | (1<<5));
+ if (two) PORTE |= (1<<2);
+ if (three) PORTE |= (1<<3);
+ if (five) PORTE |= (1<<5);
+ while(1) { }
+}
+
+ISR(SIG_UART0_RECV) {
+ if (UCSR0A & (1 << FE0)) die(0, 0, 1);
+ if ((UCSR0A & (1 << OR0))) die(1, 1, 1);
+ if (read_full()) die(1, 0, 1);
+
+ read_buf[read_buf_tail] = UDR0;
+ read_buf_tail = inc(read_buf_tail);
+ if (read_nearlyFull()) cts(0);
+ SREG |= 0x80;
+ sei();
+}
+
+inline int hex(char c) {
+ if (c >= '0' && c <= '9') return (c - '0');
+ if (c >= 'a' && c <= 'f') return ((c - 'a') + 0xa);
+ if (c >= 'A' && c <= 'F') return ((c - 'A') + 0xa);
+ return -1;
+}
+
+int readFPGA() {
+ fpga_interrupts(0);
+ int ret = FISUA;
+ fpga_interrupts(1);
+ return ret;
+}
+
+int main() {
+ DDRE = (1<<7) | (1<<5) | (1<<3) | (1<<2);
+ PORTE = 0;
+
+ PORTE |= (1<<5);
+
+ read_buf_head = 0;
+ read_buf_tail = 0;
+ write_buf_head = 0;
+ write_buf_tail = 0;
+ initUART0(1, 0); //for slow board
+
+ EIMF = 0xFF;
+ SREG = INT0;
+ sei();
+
+ TCNT1 = 0;
+ TIFR&=~(1<<TOV1);
+ TIMSK|=(1<<TOIE1);
+ TCCR1B = 3;
+
+ cts(0);
+ cts(1);
+
+ int x=0, y=0, z=0;
+ int flag=0;
+ for(;;) {
+ int i, d=0;
+ int r = recv();
+ switch(r) {
+ case 0:
+ send('O');
+ send('B');
+ send('I');
+ send('T');
+ send('S');
+ fpga_interrupts(1);
+ if (flag) die(0, 1, 1);
+ break;
+
+ case 1:
+ z = recv();
+ y = recv();
+ x = recv();
+ d = recv();
+ conf(z, y, x, d);
+ break;
+
+ case 2:
+ flag=1;
+ send(readFPGA());
+ break;
+
+ case 3: {
+ int32_t local_interrupt_count = interrupt_count;
+ interrupt_count = 0;
+ send((local_interrupt_count >> 24) & 0xff);
+ send((local_interrupt_count >> 16) & 0xff);
+ send((local_interrupt_count >> 8) & 0xff);
+ send((local_interrupt_count >> 0) & 0xff);
+
+ int32_t local_timer = TCNT1;
+ int32_t local_upper = upper;
+ TCCR1B = 0;
+ TIFR&=~(1<<TOV1);
+ TIMSK|=(1<<TOIE1);
+ upper = 0;
+ TCNT1 = 0;
+ TCCR1B = 3;
+ send((local_upper >> 8) & 0xff);
+ send((local_upper >> 0) & 0xff);
+ send((local_timer >> 8) & 0xff);
+ send((local_timer >> 0) & 0xff);
+ break;
+ }
+
+ /*
+ case 3:
+ //init_timer();
+ break;
+ case 4:
+ sending = 1;
+ break;
+ case 5:
+ sending = 0;
+ break;
+ */
+ }
+ }
+ return 0;
+
+}
+
--- /dev/null
+package edu.berkeley.slipway.demos;
+
+import edu.berkeley.slipway.*;
+import com.atmel.fpslic.*;
+import static com.atmel.fpslic.FpslicConstants.*;
+import edu.berkeley.slipway.gui.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.color.*;
+import org.ibex.util.*;
+import java.io.*;
+import java.util.*;
+import gnu.io.*;
+
+public class Demo {
+
+ public static boolean mullers = true;
+ public static int masterx = 1;
+
+ public static int PIPELEN=20;
+
+ public static void main(String[] s) throws Exception {
+ SlipwayBoard slipway = new SlipwayBoard();
+ FpslicDevice device = slipway.getFpslicDevice();
+ FpslicDevice at40k = device;
+ try {
+ Log.info(Demo.class, "issuing command");
+
+ //at40k.iob_top(2, true).oe(false);
+ //at40k.iob_top(2, false).oe(false);
+ //at40k.iob_top(1, true).oe(false);
+
+ // this command confirmed to turn *on* led0
+ //at40k.iob_top(1, false).output(0);
+ /*
+ for(int i=0; i<20; i++) {
+ at40k.iob_bot(i, false).output(0);
+ at40k.iob_bot(i, true).output(0);
+ }
+ */
+
+ //System.out.println("tick");
+ //Thread.sleep(3000);
+ //System.out.println("tick");
+ //at40k.cell(0x01, 0x17).xlut((byte)0x);
+
+ /*
+ System.out.println(Integer.toString(0xff & at40k.cell(0x01, 0x17).xlut(), 16));
+ System.out.println(Integer.toString(0xff & at40k.cell(0x01, 0x17).ylut(), 16));
+ at40k.cell(0x01, 0x17).ylut((byte)0xff);
+ */
+
+ //at40k.cell(0x01, 0x17).wi(L1);
+ /*
+ System.out.println("a: " + at40k.new SectorWire(true, 0, 4, 0x17).driverRight());
+ System.out.println("b: " + at40k.new SectorWire(true, 1, 4, 0x17).driverRight());
+ FpslicDevice.SectorWire h0p0 = at40k.new SectorWire(true, 0, 0, 0x17);
+ FpslicDevice.SectorWire h0p1 = at40k.new SectorWire(true, 1, 0, 0x17);
+ FpslicDevice.SectorWire h0p2 = at40k.new SectorWire(true, 2, 0, 0x17);
+ FpslicDevice.SectorWire h4p0 = at40k.new SectorWire(true, 0, 4, 0x17);
+ FpslicDevice.SectorWire h4p1 = at40k.new SectorWire(true, 1, 4, 0x17);
+ FpslicDevice.SectorWire h4p2 = at40k.new SectorWire(true, 2, 4, 0x17);
+
+ //h4p1.drives(h0p1, false);
+ //at40k.cell(0x04, 0x17).out(L1, false);
+ //at40k.cell(0x04, 0x17).h(L0, false);
+
+ for(int plane=0; plane<5; plane++) {
+ at40k.new SectorWire(true, plane, 4, 0x17).drives(at40k.new SectorWire(true, plane, 0, 0x17), false);
+ at40k.cell(0x04, 0x17).out(plane, false);
+ at40k.cell(0x04, 0x17).h(plane, false);
+ at40k.cell(0x01, 0x17).h(plane, false);
+ }
+ try { Thread.sleep(2000); } catch (Exception e) { }
+
+ int plane=0;
+ at40k.new SectorWire(true, plane, 4, 0x17).drives(at40k.new SectorWire(true, plane, 0, 0x17), true);
+ at40k.cell(0x04, 0x17).out(plane, true);
+ at40k.cell(0x04, 0x17).h(plane, true);
+ at40k.cell(0x01, 0x17).h(plane, true);
+ at40k.cell(0x01, 0x17).wi(plane);
+
+ */
+
+ /*
+ System.out.println("xlut is " + hex(at40k.cell(0x04, 0x17).xlut()));
+ System.out.println("ylut is " + hex(at40k.cell(0x04, 0x17).ylut()));
+ FpslicDevice.Cell cell = at40k.cell(0x04, 0x17);
+ //cell.xlut(0xff);
+ //cell.f(false);
+ System.out.println(cell.c());
+ cell.c(YLUT);
+ cell.ylut(0x4D);
+ cell.xlut(0x00);
+
+ cell.b(false);
+ cell.f(false);
+ //cell.t(false, false, true);
+ cell.t(false, true, false);
+ cell.out(L3, true);
+ cell.wi(L3);
+
+ cell.yo(false);
+ cell.h(L0, false);
+ cell.h(L1, false);
+ cell.h(L2, false);
+ cell.h(L3, false);
+ cell.h(L4, false);
+
+ for(int i=3; i>=1; i--) {
+ at40k.cell(i, 0x17).yi(EAST);
+ at40k.cell(i, 0x17).ylut(0x55);
+ at40k.cell(i, 0x17).yo(false);
+ }
+ */
+
+ //System.out.println("reading port status: " + Integer.toString(device.readFpgaData() & 0xff, 16));
+
+
+ // blank these out
+ /*
+ at40k.cell(23, 8).ylut(0xff);
+ at40k.cell(23, 11).ylut(0xff);
+ at40k.iob_right(8, true).enableOutput();
+ at40k.iob_right(11, true).enableOutput();
+ */
+ //for(int x=4; x<=22; x++) swap(at40k.cell(x, 22), NW, NORTH);
+
+
+ // entry cell: just copy X->X Y->Y
+ //at40k.cell(4,23).b(false);
+ //at40k.cell(4,23).yo(false);
+ //at40k.cell(4,23).ylut(at40k.cell(4,23).xlut());
+ //at40k.cell(4,23).xo(false);
+ /*
+ at40k.cell(4,23).xlut(0x55);
+ at40k.cell(4,23).ylut(0x55);
+ */
+ /*
+ at40k.cell(4,23).xlut(0x71);
+ at40k.cell(4,23).ylut(0x44);
+ at40k.cell(4,23).c(YLUT);
+ at40k.cell(4,23).f(false);
+ at40k.cell(4,23).t(false, false, true);
+ */
+
+ //for(int x=6; x<=23; x++) copy(at40k.cell(x, 23), NW, WEST); // top row copies to the right
+ /*
+ copy(at40k.cell(5, 22), NW, NORTH);
+ for(int x=6; x<=22; x++) copy(at40k.cell(x, 22), NW, WEST); // second top row copies to the right
+ //for(int y=22; y>=10; y--) copy(at40k.cell(23, y), NW, NORTH); // right edge copies down
+ for(int y=21; y>=9; y--) copy(at40k.cell(22, y), NW, NORTH); // second right edge copies down
+ copy(at40k.cell(23, 9), NW, WEST); // second output
+ */
+ /*
+ handshaker(at40k.cell(4,23));
+ at40k.cell(4,23).xi(NW);
+ at40k.cell(4,23).yi(SOUTH);
+
+ //handshaker(at40k.cell(5,23));
+ //at40k.cell(5,23).yi(NORTH);
+
+ at40k.cell(5,23).yi(NORTH);
+ at40k.cell(5,23).xlut(0x55);
+ at40k.cell(5,23).xi(SW);
+ at40k.cell(5,23).ylut(0x55);
+ at40k.cell(5,22).yi(NORTH);
+ at40k.cell(5,22).xlut(0x55);
+
+ bounce(at40k.cell(4,22));
+
+ // cell southeast of entry cell
+ at40k.cell(3,22).xi(NE); // NW->xin
+ at40k.cell(3,22).ylut(0x33); // xin->y
+ at40k.cell(3,22).yo(false); // y->yout
+ copy(at40k.cell(3, 21), NW, NORTH); // second top row copies to the right
+ copy(at40k.cell(4, 21), NW, EAST); // second top row copies to the right
+ copy(at40k.cell(5, 21), NW, EAST); // second top row copies to the right
+ copy(at40k.cell(6, 21), NW, EAST); // second top row copies to the right
+ copy(at40k.cell(6, 22), NW, SOUTH); // second top row copies to the right
+ */
+ /*
+ at40k.cell(05,22).xlut(0xff);
+ at40k.cell(05,22).ylut(0xff);
+ at40k.cell(05,22).c(XLUT);
+ at40k.cell(05,22).f(false);
+ at40k.cell(05,22).b(false);
+ at40k.cell(05,22).oe(NONE);
+ at40k.cell(05,22).v(L3, true);
+ at40k.cell(05,22).out(L3, true);
+ */
+ /*
+ at40k.cell(4,23).ylut(~0xCC);
+ at40k.cell(4,23).xlut(~0xAA);
+ at40k.cell(5,23).ylut(~0xAA);
+ at40k.cell(5,23).xlut(~0xAA);
+ for(int i=6; i<PIPELEN+2; i++) {
+ at40k.cell(i, 23).ylut(0xAA);
+ at40k.cell(i, 23).xlut(0xCC);
+ at40k.cell(i, 23).yi(WEST);
+ }
+ */
+
+ doitx(at40k, slipway);
+ Gui vis = new Gui(device, slipway);
+ Frame fr = new Frame();
+ fr.addKeyListener(vis);
+ fr.setLayout(new BorderLayout());
+ fr.add(vis, BorderLayout.CENTER);
+ fr.pack();
+ fr.setSize(900, 900);
+ vis.repaint();
+ fr.repaint();
+ fr.show();
+ synchronized(Demo.class) { Demo.class.wait(); }
+ /* LAST
+ System.out.println("doit");
+ if (mullers) doitx(at40k, device);
+ //System.out.println("counter");
+ //counter(at40k, device);
+
+ at40k.cell(21,15).yi(WEST);
+ at40k.cell(21,15).ylut(0xAA);
+
+ at40k.cell(22,15).yi(WEST);
+ at40k.cell(22,15).ylut(0xAA);
+ */
+
+ FpslicDevice.Cell root = at40k.cell(10,20);
+
+ root.yo(root.north());
+ root.ylut(~LUT_SELF);
+ root.c(YLUT);
+ root = root.north();
+
+ root.yo(root.east());
+ root.ylut(~LUT_SELF);
+ root.c(YLUT);
+ root = root.east();
+
+ root.yo(root.south());
+ root.ylut(~LUT_SELF);
+ root.c(YLUT);
+ root = root.south();
+
+ root.yo(root.west());
+ root.c(YLUT);
+ root = root.west();
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ at40k.cell(23,15).h(3, true);
+ at40k.cell(23,15).yi(L3);
+ at40k.cell(23,15).ylut(0xAA);
+ at40k.iob_right(15, true).enableOutput(WEST);
+
+
+ FpslicDevice.Cell c = at40k.cell(10,10);
+ c.ylut(~LUT_SELF);
+ c.xlut(LUT_Z);
+ c.yi(WEST);
+ c.c(YLUT);
+ c.f(false);
+ c.t(TMUX_FB);
+ copy(c.west(), EAST, NW);
+ copy(c.west().north().west(), SE, SE);
+
+ c = c.east();
+ c.ylut(~LUT_SELF);
+ c.xlut(LUT_Z);
+ c.yi(EAST);
+ c.c(YLUT);
+ c.f(false);
+ c.t(TMUX_FB);
+ copy(c.east(), WEST, SE);
+ copy(c.east().south().east(), NW, NW);
+
+ c = c.north();
+ copy(c.north(), SOUTH, SOUTH);
+ c.xlut((LUT_SELF & ~LUT_OTHER) | LUT_Z);
+ c.ylut(LUT_Z);
+ c.yi(SOUTH);
+ c.c(XLUT);
+ c.xi(SW);
+ c.wi(L4);
+ c.f(false);
+ c.t(TMUX_W_AND_FB);
+ c.v(L4, false);
+ c.h(L4, true);
+ c.v(L2, false);
+ c.h(L2, true);
+
+ c = c.west();
+ copy(c.north(), SOUTH, SOUTH);
+ c.xlut((LUT_SELF & ~LUT_OTHER) | LUT_Z);
+ c.ylut(~LUT_Z);
+ c.yi(SOUTH);
+ c.xi(SE);
+ c.c(XLUT);
+ c.wi(L4);
+ c.f(false);
+ c.t(TMUX_W_AND_FB);
+ c.v(L4, false);
+ c.h(L4, true);
+ c.v(L2, false);
+ c.h(L2, true);
+
+ c = c.west();
+ c.v(L4, false);
+ c.h(L4, true);
+ c.out(L4, true);
+ c.f(false);
+ c.b(false);
+ c.oe(NONE);
+ c.c(YLUT);
+ c.hwire(L4).west().drives(c.hwire(L4), false);
+ c.hwire(L4).east().drives(c.hwire(L4), false);
+
+ c = c.south();
+ c = c.south();
+ c.v(L4, false);
+ c.h(L4, true);
+ c.out(L4, true);
+ c.f(false);
+ c.b(false);
+ c.oe(NONE);
+ c.c(YLUT);
+ c.hwire(L4).west().drives(c.hwire(L4), false);
+ c.hwire(L4).east().drives(c.hwire(L4), false);
+
+ c = c.east();
+ c = c.east();
+ copy(c.south(), NORTH, NORTH);
+ c.xlut(((~LUT_SELF) & (~LUT_OTHER)) | LUT_Z);
+ c.ylut(LUT_Z);
+ c.yi(NORTH);
+ c.c(XLUT);
+ c.xi(NW);
+ c.wi(L4);
+ c.f(false);
+ c.t(TMUX_W_AND_FB);
+ c.v(L4, false);
+ c.h(L4, true);
+ c.v(L2, false);
+ c.h(L2, true);
+
+ c = c.west();
+ copy(c.south(), NORTH, NORTH);
+ c.xlut((LUT_SELF & LUT_OTHER) | LUT_Z);
+ c.ylut(LUT_Z);
+ c.yi(NORTH);
+ c.xi(NE);
+ c.c(XLUT);
+ c.wi(L4);
+ c.f(false);
+ c.t(TMUX_W_AND_FB);
+ c.v(L4, false);
+ c.h(L4, true);
+ c.v(L2, false);
+ c.h(L2, true);
+
+
+ // catch a rising transition
+ /*
+ c = c.west();
+ c.v(L2, false);
+ c.h(L2, true);
+ c.out(L2, true);
+ c.f(false);
+ c.b(false);
+ c.oe(NONE);
+ c.c(YLUT);
+ */
+ c.hwire(L2).west().drives(c.hwire(L2), false);
+ c.hwire(L2).east().drives(c.hwire(L2), false);
+
+
+
+ //////
+
+ c = at40k.cell(20,20);
+ c.yi(WEST);
+ c.ylut(LUT_SELF);
+ c.c(YLUT);
+ c.oe(H4);
+ c.h(L4, true);
+ c.b(false);
+ c.f(false);
+ c.out(L4);
+
+ c = at40k.cell(21,20);
+ c.c(YLUT);
+ c.oe(NONE);
+ c.h(L4, true);
+ c.b(false);
+ c.f(false);
+
+
+ c = at40k.cell(8,8);
+ c.f(true);
+ c.b(true);
+ c.xo(true);
+ c.xi(NE);
+ c.zi(L3);
+ c.wi(L0);
+ c.yi(NORTH);
+ c.oe(H4);
+ c.h(L0, true);
+ c.h(L2, true);
+ c.h(L4, true);
+ c.v(L1, true);
+ c.v(L3, true);
+ c.out(L0, true);
+ c.out(L1, true);
+ c.out(L2, true);
+ c.out(L3, true);
+ c.out(L4, true);
+ c.xo(true);
+ c.yo(true);
+ c.c(ZMUX);
+
+ at40k.cell(9,10).xo(true);
+ at40k.cell(9,10).yo(true);
+ at40k.cell(9,10).c(YLUT);
+ at40k.cell(9,10).b(false);
+
+ //for(int x=5; x<PIPELEN; x++) {
+ //at40k.cell(x,23).hwire(L0).drives(at40k.cell(x,23).hwire(L0).east());
+ //}
+
+ /*
+ at40k.cell(22,11).ylut(0xff);
+ at40k.cell(23,11).yi(L3);
+ //at40k.cell(23,11).yi(WEST);
+ //at40k.cell(23,11).xi(L1);
+ at40k.cell(23,11).ylut(0xAA);
+ at40k.iob_right(11, true).enableOutput(WEST);
+ at40k.cell(23,11).v(L3, true);
+ at40k.cell(23,11).yo(false);
+ //at40k.flush();
+ */
+ int vx=04;
+ int vv=23;
+ /*
+ System.out.println("correct: " + at40k.cell(19,15).hwire(L3) + " drives " + at40k.cell(20,15).hwire(L3));
+ System.out.println("correct: " + at40k.cell(15,15).hwire(L3) + " drives " + at40k.cell(19,15).hwire(L3));
+ System.out.println("correct: " + at40k.cell(11,15).hwire(L3) + " drives " + at40k.cell(15,15).hwire(L3));
+ System.out.println("correct: " + at40k.cell(07,15).hwire(L3) + " drives " + at40k.cell(11,15).hwire(L3));
+
+ at40k.cell(19,15).hwire(L3).drives(at40k.cell(20,15).hwire(L3), true);
+ at40k.cell(15,15).hwire(L3).drives(at40k.cell(19,15).hwire(L3), true);
+ at40k.cell(11,15).hwire(L3).drives(at40k.cell(15,15).hwire(L3), true);
+ at40k.cell(07,15).hwire(L3).drives(at40k.cell(11,15).hwire(L3), true);
+ */
+ //at40k.cell(05,vv).xlut(0xff);
+ //at40k.cell(05,vv).ylut(0xff);
+ /*
+ at40k.cell(vx,vv).c(YLUT);
+ at40k.cell(vx,vv).f(false);
+ at40k.cell(vx,vv).b(false);
+ at40k.cell(vx,vv).oe(NONE);
+ at40k.cell(vx,vv).v(L3, true);
+ at40k.cell(vx,vv).out(L3, true);
+ */
+ /*
+ at40k.cell(vx,15).v(L3, true);
+ at40k.cell(vx,15).h(L3, true);
+ at40k.cell(vx,19).vwire(L3).drives(at40k.cell(vx,15).vwire(L3), true);
+ at40k.cell(vx,23).vwire(L3).drives(at40k.cell(vx,19).vwire(L3), true);
+ */
+
+ //at40k.cell(5,23).ylut(0x00);
+ //at40k.cell(6,22).ylut(0xff);
+ //at40k.cell(22,11).ylut(0xff);
+ /*
+ FpslicDevice.Cell cell = at40k.cell(4, 16);
+ cell.xlut(0xff);
+ cell.ylut(0xff);
+ cell.b(false);
+ cell.f(false);
+ cell.c(XLUT);
+ cell.h(L3, true);
+ cell.v(L3, true);
+ cell.out(L3, true);
+ cell.oe(NONE);
+ */
+ //scan(at40k, cell, YLUT, true);
+ //scan(at40k, cell, YLUT, false);
+
+ //device.scanFPGA(true);
+
+ at40k.cell(10,10).f(true);
+ at40k.cell(10,10).c(ZMUX);
+
+ at40k.cell(8,7).xlut(LUT_SELF);
+ at40k.cell(8,7).xi(NW);
+
+ at40k.cell(7,8).xlut(LUT_SELF & LUT_Z);
+ at40k.cell(7,8).xi(SE);
+ at40k.cell(7,8).c(XLUT);
+ at40k.cell(7,8).f(false);
+ at40k.cell(7,8).b(false);
+ at40k.cell(7,8).t(TMUX_FB);
+ at40k.cell(7,8).xo(false);
+ System.out.println(at40k.cell(7,8).fb_relevant());
+
+ at40k.cell(6,13).xi(SE);
+ at40k.cell(6,13).c(ZMUX);
+ at40k.cell(6,13).xlut(LUT_SELF);
+ at40k.cell(6,13).ylut(LUT_OTHER);
+ at40k.cell(6,13).xo(false);
+ at40k.cell(6,13).yo(false);
+ at40k.cell(7,12).xi(SE);
+
+ for(int i=0; i<24; i++) {
+ at40k.iob_bot(i, true).enableOutput(NORTH);
+ at40k.iob_bot(i, false).enableOutput(NW);
+ at40k.cell(i, 0).xlut(0xff);
+ at40k.cell(i, 0).ylut(0xff);
+ }
+
+ device.flush();
+
+ fr.addKeyListener(vis);
+ fr.setLayout(new BorderLayout());
+ fr.add(vis, BorderLayout.CENTER);
+ fr.pack();
+ fr.setSize(900, 900);
+ vis.repaint();
+ fr.repaint();
+ fr.show();
+ synchronized(Demo.class) { Demo.class.wait(); }
+
+
+
+ /*
+ Visualizer v = new Visualizer(at40k, device);
+ v.show();
+ v.setSize(1380, 1080);
+ FpslicDevice.Cell cell = at40k.cell(4, 23);
+ */
+ //Image img = v.createImage(v.getWidth(), v.getHeight());
+ /*
+ int x = 1;
+ int y = 14;
+ cell = at40k.cell(x,y);
+ scan(at40k, cell, YLUT, true);
+ cell.c(YLUT);
+ cell.b(false);
+ cell.f(false);
+ cell.oe(NONE);
+ cell.ylut(0xff);
+ */
+ //int x = 5;
+ //int y = 11;
+
+ //selfTest(device, at40k, v);
+ //System.out.println("save: " + SlipwayBoard.save + " of " + (SlipwayBoard.saveof*5));
+
+ at40k.iob_top(0, true).enableInput();
+ copy(at40k.cell(0, 23), NORTH, NORTH);
+ at40k.iob_bot(0, true).enableOutput(NORTH);
+
+ for(int i=0; i<10000; i++) {
+ //v.refresh();
+ try { Thread.sleep(100); } catch (Exception e) { }
+ }
+ //cell.ylut(0x09);
+
+ //at40k.cell(0x01, 0x17).h(0, false);
+ //at40k.cell(0x01, 0x17).xi(NE);
+ //at40k.cell(0x01, 0x17).ylut((byte)0x55);
+
+ //at40k.cell(0x04, 0x17).xlut((byte)0x10);
+ //at40k.cell(0x04, 0x17).ylut((byte)0x10);
+ //at40k.cell(0x04, 0x17).yo(false);
+ //at40k.cell(0x04, 0x17).xo();
+
+ /*
+ at40k.cell(0x01, 0x17).xi(L0);
+ at40k.cell(0x01, 0x17).h(L0, true);
+ */
+ /*
+ at40k.cell(0x03, 0x17).xlut((byte)0x55);
+ at40k.cell(0x03, 0x17).ylut((byte)0x55);
+ at40k.cell(0x03, 0x17).yi(EAST);
+ at40k.cell(0x03, 0x17).ylut((byte)0x55);
+ at40k.cell(0x03, 0x17).yo(true);
+
+ at40k.cell(0x03, 0x17).f(false);
+ at40k.cell(0x03, 0x17).c(XLUT);
+ at40k.cell(0x03, 0x17).oe(NONE);
+ at40k.cell(0x03, 0x17).out(L0, true);
+
+ at40k.cell(0x02, 0x17).yi(EAST);
+ at40k.cell(0x02, 0x17).ylut((byte)0x55);
+ at40k.cell(0x02, 0x17).yo(false);
+
+ at40k.cell(0x01, 0x17).yi(EAST);
+ at40k.cell(0x01, 0x17).ylut((byte)0x55);
+ at40k.cell(0x01, 0x17).yo(false);
+
+ at40k.cell(0x01, 0x17).h(L0, true);
+ at40k.cell(0x01, 0x17).v(L0, false);
+ */
+ //at40k.cell(0x01, 0x17).yi(L0);
+ //at40k.cell(0x01, 0x17).xi(L0);
+ //at40k.cell(0x01, 0x17).ylut((byte)0x33);
+
+ /*
+ at40k.cell(0x03, 0x17).h(L0, true);
+ at40k.cell(0x03, 0x17).out(L0, true);
+ at40k.cell(0x03, 0x17).c(XLUT);
+ at40k.cell(0x03, 0x17).f(false);
+ */
+ /*
+ at40k.cell(0x01, 0x17).xin(4);
+ at40k.cell(0x01, 0x17).yin(4);
+ at40k.cell(0x01, 0x16).ylut((byte)0x00);
+ device.mode4(2, 0x17, 0x01, 0);
+
+ for(int i=0; i<10; i++) {
+ Thread.sleep(3000);
+ System.out.println("tick");
+ //at40k.cell(0x01, 0x17).xlut((byte)0xFF);
+ at40k.cell(0x00, 0x17).ylut((byte)0x00);
+ device.getFpslicDevice().flush();
+ Thread.sleep(3000);
+ System.out.println("tick");
+ //at40k.cell(0x01, 0x17).xlut((byte)0x00);
+ at40k.cell(0x00, 0x17).ylut((byte)0xFF);
+ device.getFpslicDevice().flush();
+ }
+ */
+
+
+ /*
+ at40k.iob_top(0, true).output(0);
+ at40k.iob_top(0, true).oe(false);
+ at40k.iob_top(0, true).pullup();
+ device.getFpslicDevice().flush();
+ Thread.sleep(3000);
+
+ Log.info(Demo.class, "issuing command");
+ at40k.iob_top(1, true).pulldown();
+ device.getFpslicDevice().flush();
+ */
+ Log.info(Demo.class, "done");
+ System.exit(0);
+ } catch (Exception e) { e.printStackTrace(); }
+ }
+
+
+ public static void copy(FpslicDevice.Cell c, int xdir, int ydir) {
+ switch(xdir) {
+ case NW: case NE: case SW: case SE: {
+ c.xi(xdir);
+ c.xlut(LUT_SELF);
+ break;
+ }
+ case NORTH: case SOUTH: case EAST: case WEST: {
+ c.yi(xdir);
+ c.xlut(LUT_OTHER);
+ break;
+ }
+ case NONE: break;
+ default: throw new Error();
+ }
+ switch(ydir) {
+ case NW: case NE: case SW: case SE: {
+ c.xi(ydir);
+ c.ylut(LUT_OTHER);
+ break;
+ }
+ case NORTH: case SOUTH: case EAST: case WEST: {
+ c.yi(ydir);
+ c.ylut(LUT_SELF);
+ break;
+ }
+ case NONE: break;
+ default: throw new Error();
+ }
+ c.xo(false);
+ c.yo(false);
+ }
+ public static String hex(int x) {
+ return Long.toString(x & 0xffffffffL, 16);
+ }
+
+ public static void handshaker(FpslicDevice.Cell cell) {
+ cell.xlut(0x22);
+ cell.ylut(0x71);
+ cell.c(XLUT);
+ cell.f(false);
+ cell.t(false, false, true);
+ }
+
+
+ private static String pad(int i, String s) { if (s.length()>i) return s; return "0"+pad((i-1),s); }
+ public static String bin8(byte b) {
+ int n = b & 0xff;
+ String ret = "";
+ for(int i=7; i>=0; i--)
+ ret += (n & (1<<i))==0 ? "0" : "1";
+ return ret;
+ }
+
+ public static void bounce(FpslicDevice.Cell cell, int xi, int yi) {
+ cell.xlut((byte)0xCC);
+ cell.ylut((byte)0xCC);
+ cell.xi(xi);
+ cell.yi(yi);
+ cell.xo(false);
+ cell.yo(false);
+ }
+ public static void muller(FpslicDevice.Cell cell, int xi, int yi) {
+ cell.ylut(0xB2);
+ cell.c(YLUT);
+ cell.f(false);
+ cell.t(false, false, true);
+ cell.xi(xi);
+ cell.yi(yi);
+ cell.yo(false);
+ cell.xo(false);
+ }
+
+ public static int lutSwap(int x) {
+ return
+ (x & 0x80) |
+ ((x & 0x20) << 1) |
+ ((x & 0x40) >> 1) |
+ (x & 0x10) |
+ (x & 0x08) |
+ ((x & 0x02) << 1) |
+ ((x & 0x04) >> 1) |
+ (x & 0x01);
+ }
+
+ /** watches for a rising/falling edge on Yin, emits a pulse on Xout */
+ public static void pulse_detect(FpslicDevice.Cell c, int in, boolean falling) {
+ c.ylut(0x00);
+ c.xlut(0x00);
+ switch(in) {
+ case NW: case NE: case SW: case SE: {
+ c.xi(in);
+ loopback(c, XLUT);
+ if (!falling) c.ylut(lutSwap(0x0C)); /* x & !z */
+ else c.ylut(lutSwap(0x30)); /* !x & z */
+ c.xlut(LUT_SELF);
+ break;
+ }
+ case NORTH: case SOUTH: case EAST: case WEST: {
+ c.yi(in);
+ loopback(c, YLUT);
+ if (!falling) c.xlut(0x0C); /* y & !z */
+ else c.xlut(0x30); /* !y & z */
+ c.ylut(LUT_SELF);
+ break;
+ }
+ default: throw new Error();
+ }
+ }
+
+ /** watches for a pulse on Xin, copies value of Yin */
+ public static void pulse_copy(FpslicDevice.Cell cell, int xi, int yi, boolean invert) {
+ loopback(cell, YLUT);
+ if (!invert) cell.ylut(0xB8); /* yo = x ? yi : z => 1011 1000 */
+ else cell.ylut(0x74); /* yo = x ? !yi : z => 0111 0100 */
+ if (!invert) cell.xlut(lutSwap(0xB8)); /* yo = x ? yi : z => 1011 1000 */
+ else cell.xlut(lutSwap(0x74)); /* yo = x ? !yi : z => 0111 0100 */
+ cell.xi(xi);
+ cell.yi(yi);
+ }
+
+ public static void loopback(FpslicDevice.Cell cell, int cin) {
+ cell.f(false);
+ cell.b(false);
+ cell.t(false, false, true);
+ cell.yo(false);
+ cell.xo(false);
+ cell.c(cin);
+ }
+
+ public static void doit(FpslicDevice at40k, SlipwayBoard device) throws Exception {
+
+ FpslicDevice.Cell led = at40k.cell(1, 23);
+ led.v(L2, true);
+ led.h(L2, false);
+ led.yi(L2);
+ led.ylut(~LUT_SELF);
+ led.xlut(LUT_SELF);
+ led.yo(false);
+
+ FpslicDevice.Cell c = at40k.cell(1, 22);
+ c.out(L1, true);
+ c.out(L0, true);
+ c.oe(V4);
+ c.ylut(0xff);
+ c.h(L1, true);
+ c.h(L0, false);
+
+ c.v(L0, /*false*/true);
+
+ c.v(L1, true);
+ c.f(false);
+ c.b(false);
+ c.c(YLUT);
+
+ for(int i=0; i<4; i++) at40k.cell(i, 20).h(L0, false);
+ FpslicDevice.Cell z = at40k.cell(1, 20);
+ z.out(L0, true);
+ z.xlut(0xff);
+ z.c(XLUT);
+ z.yi(L0);
+ z.ylut(~LUT_SELF);
+ z.v(L0, true);
+ //z.h(L0, true);
+ z.h(L0, false);
+ z.f(false);
+ z.b(false);
+ z.hwire(L0).east().drives(z.hwire(L0), false);
+ z.hwire(L1).east().drives(z.hwire(L1), false);
+ z.vwire(L0).south().drives(z.vwire(L0), false);
+ z.vwire(L1).south().drives(z.vwire(L1), false);
+ z.oe(H4);
+
+ z = at40k.cell(0, 20);
+ z.oe(NONE);
+ z.out(L0, true);
+ z.out(L1, true);
+ z.out(L2, true);
+ //z.out(L3, true);
+ z.out(L4, true);
+ z.h(L0, true);
+ z.h(L1, true);
+ z.h(L2, true);
+ //z.h(L3, true);
+ z.h(L4, true);
+ z.f(false);
+ z.b(false);
+ z.yi(EAST);
+ z.ylut(LUT_SELF);
+ z.c(YLUT);
+
+ for(int y=20; y<=22; y++)
+ for(int x=2; x<=5; x++) {
+ c = at40k.cell(x, y);
+ copy(c, NW, WEST);
+ }
+
+ //c = at40k.cell(2, 22);
+ //c.h(L0, true);
+ //c.yi(L0);
+
+ c = at40k.cell(1, 21);
+ c.v(L0, true);
+ c.v(L2, true);
+ c.yi(L0);
+ c.out(L2, true);
+ c.ylut(LUT_SELF);
+ c.c(YLUT);
+ c.b(false);
+ c.f(false);
+ c.oe(NONE);
+ c.yo(false);
+
+
+
+ c = at40k.cell(13, 22);
+ c.xlut(LUT_OTHER | 0xF0);
+ c.c(XLUT);
+ c.t(false, false, true);
+ c.b(false);
+ c.f(false);
+ c.ylut(0xF0);
+ c.yi(EAST);
+ c.yo(false);
+ /*
+ // this gate detects a rising edge on its Xin (delayed copy on Yin); when viewed, it inverts its state
+ c = at40k.cell(14, 22);
+ c.ylut(0x00);
+ c.c(XLUT);
+ c.f(false);
+ c.b(false);
+ c.t(false, false, true);
+ c.xi(SE);
+ c.yi(SOUTH);
+ c.yo(false);
+ c.xo(false);
+ c.ylut(0xA6); // (x & !z) ? ~y : y
+ c.xlut(LUT_SELF);
+
+ c = at40k.cell(14, 20);
+ c.ylut(LUT_OTHER);
+ c.xi(NE);
+ c = at40k.cell(14, 21);
+ c.ylut(LUT_SELF);
+ c.xi(SOUTH);
+
+ c = at40k.cell(13, 22);
+ c.xlut(0x00);
+ c.xlut(LUT_OTHER);// | 0xF0);
+ */
+ //c = at40k.cell(13, 22);
+ //copy(c, NW, EAST);
+ /*
+ c.ylut(0x00);
+ c.c(YLUT);
+ c.f(false);
+ c.b(false);
+ c.t(false, false, true);
+ c.xi(SE);
+ c.yi(NORTH);
+ c.yo(false);
+ c.xo(false);
+ c.ylut(0x54); // (x || z) & !y
+ */
+
+ /*
+ c = at40k.cell(2, 21);
+ c.ylut(0x00);
+ c.c(YLUT);
+ c.f(false);
+ c.b(false);
+ c.t(false, false, true);
+ c.xi(SE);
+ c.yi(WEST);
+ c.yo(false);
+ c.xo(false);
+ c.ylut(0xE8);
+
+ //at40k.cell(2, 21).xlut(0xF0);
+
+ at40k.cell(3, 22).ylut(LUT_OTHER);
+ at40k.cell(3, 22).xi(SW);
+ */
+ //at40k.iob_top(5, true).enableOutput(SOUTH);
+ //at40k.iob_top(5, false).enableOutput(SE);
+ }
+
+ public static int yofs = mullers ? 19 : 22;
+ public static void counter(FpslicDevice at40k, SlipwayBoard device) throws Exception {
+ // watch for rising edge from south, emit pulse on Xout (to NE)
+ //copy(at40k.cell(16,23), SW, WEST);
+
+ for(int x=22; x>=1; x-=2) {
+ pulse_detect(at40k.cell(x, yofs), SE, false);
+ pulse_detect(at40k.cell(x, yofs-1), EAST, true);
+ pulse_copy(at40k.cell(x-1, yofs), SE, SOUTH, false);
+ pulse_copy(at40k.cell(x-1, yofs-1), NE, NORTH, true);
+
+ //pulse_detect(at40k.cell(15, 22), NORTH, false);
+ //pulse_detect(at40k.cell(16, 22), NW, true);
+ //pulse_copy(at40k.cell(16, 21), NW, WEST, false);
+ //pulse_copy(at40k.cell(15, 21), NE, EAST, true);
+ }
+ for(int x=23; x>1; x-=2) {
+ pulse_detect(at40k.cell(x-1, yofs-2), SW, false);
+ pulse_detect(at40k.cell(x-1, yofs-3), WEST, true);
+ pulse_copy(at40k.cell(x, yofs-2), SW, SOUTH, false);
+ pulse_copy(at40k.cell(x, yofs-3), NW, NORTH, true);
+
+ //pulse_detect(at40k.cell(15, 22), NORTH, false);
+ //pulse_detect(at40k.cell(16, 22), NW, true);
+ //pulse_copy(at40k.cell(16, 21), NW, WEST, false);
+ //pulse_copy(at40k.cell(15, 21), NE, EAST, true);
+ }
+ copy(at40k.cell(1, yofs-2), SOUTH, SOUTH);
+ copy(at40k.cell(1, yofs-3), NORTH, NORTH);
+ at40k.cell(1, yofs-3).ylut(~at40k.cell(1, yofs-3).ylut());
+ at40k.cell(1, yofs-3).xlut(~at40k.cell(1, yofs-3).xlut());
+
+ copy(at40k.cell(23, yofs), SOUTH, SOUTH);
+ copy(at40k.cell(23, yofs-1), SOUTH, SOUTH);
+
+ for(int i=23; i>yofs; i--) copy(at40k.cell(1, i), SOUTH, SOUTH);
+
+ //at40k.iob_top(1, true).slew(SLOW);
+ //at40k.iob_top(1, false).slew(SLOW);
+
+ }
+
+ public static void fill(FpslicDevice at40k, SlipwayBoard device, int num) throws Exception {
+ //muller(at40k.cell(PIPELEN,22), NE, WEST);
+ FpslicDevice.Cell a = at40k.cell(10,22);
+ FpslicDevice.Cell b = at40k.cell(11,22);
+ a.ylut(0x00);
+ for(int i=0; i<num; i++) {
+ //System.out.println(i);
+ b.lut(0xff, 0xff);
+ device.getFpslicDevice().flush();
+ try { Thread.sleep(1); } catch (Exception e) { }
+ b.lut(0x00, 0x00);
+ device.getFpslicDevice().flush();
+ try { Thread.sleep(1); } catch (Exception e) { }
+ }
+ b.ylut(0xB2);
+ a.ylut(0xB2);
+ }
+
+ public static void drain(FpslicDevice at40k, SlipwayBoard device) throws Exception {
+ FpslicDevice.Cell a = at40k.cell(10,22);
+ FpslicDevice.Cell b = at40k.cell(11,22);
+ a.lut(0x00, 0x00);
+ b.lut(0x00, 0x00);
+ for(int i=0; i<30; i++) {
+ //System.out.println(i);
+ a.lut(0xff, 0xff);
+ device.getFpslicDevice().flush();
+ try { Thread.sleep(1); } catch (Exception e) { }
+ a.lut(0x00, 0x00);
+ device.getFpslicDevice().flush();
+ try { Thread.sleep(1); } catch (Exception e) { }
+ }
+ b.ylut(0xB2);
+ a.ylut(0xB2);
+ }
+
+ public static void doitx(FpslicDevice at40k, SlipwayBoard device) throws Exception {
+ for(int i=5; i<PIPELEN+1; i++) bounce(at40k.cell(i, 23), SE, SOUTH);
+ for(int x=5; x<PIPELEN; x++) muller(at40k.cell(x, 22), x==PIPELEN-1 ? SE : NE, WEST);
+
+ bounce(at40k.cell(PIPELEN, 21), NW, WEST);
+
+ for(int x=5; x<PIPELEN; x++) muller(at40k.cell(x, 21), SW, x==PIPELEN-1 ? NORTH : EAST);
+ for(int x=4; x<PIPELEN+1; x++) bounce(at40k.cell(x, 20), NW, NORTH);
+
+ bounce(at40k.cell(4, 22), SE, EAST);
+ //muller(at40k.cell(4PIPELEN-1,21), SW, NORTH);
+
+ //muller(at40k.cell(4,22), NE, WEST);
+ //at40k.cell(4,22).ylut(0xEE);
+ muller(at40k.cell(5, 22), NE, SOUTH);
+ muller(at40k.cell(5, 21), NW, EAST);
+ /*
+ for(int x=4; x>=0; x--) {
+ at40k.cell(x, 21).ylut(0xAA);
+ at40k.cell(x, 21).yi(EAST);
+ at40k.cell(x, 21).yo(false);
+ }
+
+ at40k.cell(0, 22).ylut(0xAA);
+ at40k.cell(0, 22).yi(SOUTH);
+ at40k.cell(0, 22).yo(false);
+
+ at40k.cell(0, 23).ylut(~0xAA);
+ at40k.cell(0, 23).xlut(~0xcc);
+ at40k.cell(0, 23).yi(SOUTH);
+ at40k.cell(0, 23).yo(false);
+ */
+ for(int x=3; x<=23; x+=2) {
+ pulse_detect(at40k.cell(x-1, 19), SW, false);
+ pulse_detect(at40k.cell(x-1, 18), WEST, true);
+ pulse_copy(at40k.cell(x, 19), SW, SOUTH, false);
+ pulse_copy(at40k.cell(x, 18), NW, NORTH, true);
+
+ if (x<17) {
+ pulse_detect(at40k.cell(x-1, 16), SW, false);
+ pulse_detect(at40k.cell(x-1, 15), WEST, true);
+ pulse_copy(at40k.cell(x, 16), SW, SOUTH, false);
+ pulse_copy(at40k.cell(x, 15), NW, NORTH, true);
+ }
+ //pulse_detect(at40k.cell(15, 22), NORTH, false);
+ //pulse_detect(at40k.cell(16, 22), NW, true);
+ //pulse_copy(at40k.cell(16, 21), NW, WEST, false);
+ //pulse_copy(at40k.cell(15, 21), NE, EAST, true);
+ }
+ for(int x=14; x>=1; x--)
+ copy(at40k.cell(x, 17), EAST, EAST);
+ for(int x=4; x>=0; x--)
+ copy(at40k.cell(x, 21), EAST, EAST);
+ copy(at40k.cell(13, 17), SOUTH, SOUTH);
+
+ copy(at40k.cell(0, 20), NORTH, NORTH);
+ copy(at40k.cell(0, 19), NORTH, NORTH);
+ copy(at40k.cell(0, 18), NORTH, NORTH);
+ copy(at40k.cell(0, 17), NORTH, NORTH);
+ copy(at40k.cell(0, 16), NORTH, NORTH);
+ copy(at40k.cell(1, 16), WEST, WEST);
+ copy(at40k.cell(1, 15), NORTH, NORTH);
+
+ copy(at40k.cell(1, 20), SOUTH, SOUTH);
+ copy(at40k.cell(1, 19), SOUTH, SOUTH);
+ copy(at40k.cell(1, 18), SOUTH, SOUTH);
+
+ for(int y=20; y<=23; y++)
+ copy(at40k.cell(23, y), SOUTH, SOUTH);
+
+
+ //for(int x=19; x<=23; x++)
+ //copy(at40k.cell(x, 0), WEST, WEST);
+ //copy(at40k.cell(18, 19), NW, NW);
+ //at40k.iob_top(5, true).enableOutput(SOUTH);
+ //at40k.iob_top(5, false).enableOutput(SOUTH);
+ }
+}
--- /dev/null
+package edu.berkeley.slipway.demos;
+
+import edu.berkeley.slipway.*;
+import edu.berkeley.slipway.util.*;
+import static java.awt.event.KeyEvent.*;
+import com.atmel.fpslic.*;
+import static com.atmel.fpslic.FpslicConstants.*;
+import edu.berkeley.slipway.gui.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.color.*;
+import org.ibex.util.*;
+import java.io.*;
+import java.util.*;
+import gnu.io.*;
+
+public class Demo2 implements KeyListener {
+
+ public static void main(String[] s) throws Exception {
+ new Demo2().go();
+ }
+ public SlipwayBoard slipway;
+ public Demo2() throws Exception {
+ slipway = new SlipwayBoard();
+ }
+ public void go() throws Exception {
+ long begin = System.currentTimeMillis();
+ long end = System.currentTimeMillis();
+ Log.info(Demo.class, "finished in " + ((end-begin)/1000) + "s");
+ Thread.sleep(1000);
+
+
+ Log.info(Demo.class, "issuing command");
+
+ FpslicDevice device = slipway.getFpslicDevice();
+ FpslicDevice.Cell root = device.cell(5,5);
+
+ root.ylut(LUT_SELF);
+ root.yi(NORTH);
+ root.xi(NW);
+ root.wi(L0);
+ root.zi(L2);
+
+ root = root.north();
+ root.ylut(LUT_SELF);
+ root.yi(WEST);
+ root.out(1, true);
+ root.h(1, true);
+ root.wi(L1);
+ root.zi(L3);
+
+ root = root.west();
+ root.xi(SE);
+ root.ylut(LUT_SELF);
+ root.yi(SOUTH);
+ root.wi(L2);
+ root.zi(L4);
+
+ root = root.south();
+ root.ylut(LUT_SELF);
+ root.yi(EAST);
+ root.wi(L3);
+ root.zi(L0);
+ //root = root.n();
+
+ device.iob_bot(12, false).enableOutput(NW);
+ FpslicDevice.Cell c = device.cell(12, 0);
+ c.xo(c.east());
+ while(c.east() != null && c.east().east() != null) {
+ c.yo(c.east());
+ c = c.east();
+ }
+ device.flush();
+
+ FpslicDevice.Cell div = device.cell(19, 21);
+ while(div != null)
+ div = ExperimentUtils.divider(div);
+ device.flush();
+
+ int MAX=17;
+ for(int x=2; x<MAX+1; x++) {
+ c = device.cell(x, 20);
+ FpslicDevice.Cell bridge = x==2 ? c.sw() : c.nw();
+ FpslicDevice.Cell pred = x==MAX ? c.south() : c.east();
+ FpslicDevice.Cell next = x==2 ? c.south() : c.west();
+ muller(c, pred, bridge, next);
+
+ c = c.south();
+ bridge = x==MAX ? c.ne() : c.se();
+ pred = x==2 ? c.north() : c.west();
+ next = x==MAX ? c.north() : c.east();
+ muller(c, pred, bridge, next);
+ }
+ //device.cell(MAX+0,20).yi(WEST);
+ //device.cell(MAX+0,20).ylut(LUT_SELF);
+ //device.cell(MAX+1,20).yi(WEST);
+ //device.cell(MAX+1,20).ylut(LUT_SELF);
+ device.cell(MAX+2,20).yi(WEST);
+ device.cell(MAX+2,20).ylut(LUT_SELF);
+ device.cell(MAX+2,20).xlut(LUT_OTHER);
+ device.cell(18,20).ylut(LUT_SELF);
+ device.flush();
+ go2();
+ }
+
+ public void go2() throws Exception {
+ FpslicDevice device = slipway.getFpslicDevice();
+ setupScanCell();
+ device.flush();
+
+ vis = new Gui3(device, slipway);
+ vis.addKeyListener(this);
+ Frame fr = new Frame();
+ fr.setLayout(new BorderLayout());
+ fr.add(vis, BorderLayout.CENTER);
+ fr.pack();
+ fr.setSize(900, 900);
+ vis.repaint();
+ fr.repaint();
+ fr.show();
+ //synchronized(Demo.class) { Demo.class.wait(); }
+ while(true) {
+ try { Thread.sleep(500); } catch (Exception e) { }
+ synchronized(vis) {
+ scan();
+ }
+ }
+ }
+ Gui3 vis;
+ public void muller(FpslicDevice.Cell c, FpslicDevice.Cell pred, FpslicDevice.Cell bridge, FpslicDevice.Cell next) {
+ FpslicDevice device = slipway.getFpslicDevice();
+ bridge.yi(next);
+ bridge.xlut(LUT_OTHER);
+
+ c.yi(pred);
+ c.xi(bridge);
+ c.b(false);
+ c.f(false);
+ c.c(YLUT);
+ c.t(TMUX_FB);
+ c.ylut((LUT_SELF & ~LUT_OTHER) |
+ (LUT_Z & ~LUT_OTHER) |
+ (LUT_Z & LUT_SELF));
+ }
+
+ public void setupScanCell() {
+ FpslicDevice device = slipway.getFpslicDevice();
+ FpslicDevice fpslic = (FpslicDevice)device;
+ fpslic.cell(23,15).h(3, true);
+ fpslic.cell(23,15).yi(L3);
+ fpslic.cell(23,15).ylut(0xAA);
+ fpslic.iob_right(15, true).enableOutput(WEST);
+
+ fpslic.cell(23,0).ylut(0x00);
+ fpslic.iob_right(0, true).enableOutput(WEST);
+ fpslic.flush();
+ }
+
+ public void keyTyped(KeyEvent k) { }
+ public void keyReleased(KeyEvent k) { }
+ public void keyPressed(KeyEvent k) {
+ switch(k.getKeyCode()) {
+ case VK_SPACE:
+ scan();
+ break;
+ }
+ }
+ public void scan() {
+ for(int x=0; x<4; x++)
+ for(int y=0; y<4; y++)
+ scan(vis.ca[x][y]);
+ for(int x=0; x<4; x++)
+ for(int y=0; y<4; y++)
+ scan(vis.ca[x][y]);
+ }
+ public void scan(final GuiCell c) {
+ try {
+ final FpslicDevice.Cell cell = c.fpslicCell;
+ scan(slipway, cell, YLUT, true);
+ int x = cell.col;
+ int y = cell.row;
+ slipway.readFpgaData(new BCB(c));
+ scan(slipway, cell, YLUT, false);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void scan(SlipwayBoard slipway, FpslicDevice.Cell cell, int source, boolean setup) {
+ FpslicDevice dev = slipway.getFpslicDevice();
+ if (setup) {
+ //if (source != NONE) cell.c(source);
+ if (cell.b()) cell.b(false);
+ if (cell.f()) cell.f(false);
+ }
+ if (cell.out(L3)!=setup) cell.out(L3, setup);
+ if (cell.vx(L3)!=setup) cell.v(L3, setup);
+
+ FpslicDevice.SectorWire sw = cell.vwire(L3);
+ //System.out.println("wire is: " + sw);
+
+ if (sw.row > (12 & ~0x3) && sw.north()!=null && sw.north().drives(sw))
+ sw.north().drives(sw, false);
+ while(sw.row > (12 & ~0x3) && sw.south() != null) {
+ //System.out.println(sw + " -> " + sw.south());
+ if (sw.drives(sw.south())!=setup) sw.drives(sw.south(), setup);
+ sw = sw.south();
+ }
+ if (sw.row < (12 & ~0x3) && sw.south() != null && sw.south().drives(sw))
+ sw.north().drives(sw, false);
+ while(sw.row < (12 & ~0x3) && sw.north() != null) {
+ //System.out.println(sw + " -> " + sw.north());
+ if (sw.drives(sw.north())!=setup) sw.drives(sw.north(), setup);
+ sw = sw.north();
+ }
+
+ //cell = dev.cell(19, 15);
+ cell = dev.cell(cell.col, 15);
+ /*
+ System.out.println("cell is " + cell);
+ cell.xlut(0xff);
+ cell.ylut(0xff);
+ cell.b(false);
+ cell.f(false);
+ cell.c(XLUT);
+ cell.out(L3, true);
+ cell.oe(NONE);
+ */
+ if (cell.hx(L3) != setup) cell.h(L3, setup);
+ if (cell.vx(L3) != setup) cell.v(L3, setup);
+ sw = cell.hwire(L3);
+
+ if (sw.west()!=null && sw.west().drives(sw)) { sw.west().drives(sw, false); }
+ while(sw.east() != null) {
+ //System.out.println(sw + " -> " + sw.east());
+ if (sw.drives(sw.east())!=setup) sw.drives(sw.east(), setup);
+ sw = sw.east();
+ }
+
+ }
+
+
+ private class BCB extends SlipwayBoard.ByteCallback {
+ GuiCell c;
+ public BCB(GuiCell c) {
+ this.c = c;
+ }
+ public void call(byte b) throws Exception {
+ boolean on = (b & 0x80) != 0;
+ c.val = on;
+ vis.repaint();
+ }
+ }
+}
--- /dev/null
+package edu.berkeley.slipway.demos;
+
+import java.io.*;
+import java.util.*;
+import java.awt.*;
+import com.atmel.fpslic.*;
+import edu.berkeley.slipway.*;
+import edu.berkeley.slipway.gui.*;
+import edu.berkeley.slipway.util.*;
+import static com.atmel.fpslic.FpslicConstants.*;
+
+public class FastestMicropipelineFifoDemo extends MicropipelineFifoDemo {
+
+ public static void main(String[] s) throws Exception {
+ new FastestMicropipelineFifoDemo().mainx(s);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public FpslicDevice.Cell start;
+ public FastestMicropipelineFifoDemo() throws Exception {
+ start = fpslic.cell(21, 21);
+ }
+
+ protected FpslicDevice.Cell masterCell() { return start.north().north(); }
+
+ private int dividers = 0;
+ protected int numDivisors() { return dividers; }
+
+ /** drive this plane high to cause the "master" fifo stage to pause (hold current value) */
+ public static final int PLANE_PAUSE_MASTER_WHEN_HIGH = L0;
+
+ /** drive this plane high to cause the "slave" fifo stages to pause (hold current value) */
+ public static final int PLANE_PAUSE_SLAVES_WHEN_HIGH = L1;
+
+ /** drive this plane low to cause the "slave" fifo stages to pause (hold current value) */
+ public static final int PLANE_PAUSE_SLAVES_WHEN_LOW = L2;
+
+ /** drive this plane low to cause all fifo stages to reset (set current value to 0) */
+ public static final int PLANE_RESET_ALL_WHEN_LOW = L3;
+
+ /** unpauses the master stage */
+ public void unPauseMaster() {
+ fpslic.cell(0,PLANE_PAUSE_MASTER_WHEN_HIGH).ylut(0x00);
+ fpslic.flush();
+ }
+
+ /** unpauses the slave stages */
+ public void unPauseSlaves() {
+ fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_HIGH).ylut(0x00);
+ fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_LOW).ylut(0xff);
+ fpslic.flush();
+ }
+
+ /** pauses the master stage */
+ public void pauseMaster() {
+ fpslic.cell(0,PLANE_PAUSE_MASTER_WHEN_HIGH).ylut(0xff);
+ fpslic.flush();
+ }
+
+ /** pauses the slave stages */
+ public void pauseSlaves() {
+ fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_HIGH).ylut(0xff);
+ fpslic.cell(0,PLANE_PAUSE_SLAVES_WHEN_LOW).ylut(0x00);
+ fpslic.flush();
+ }
+
+ /** reset all stages (should be paused before doing this) */
+ public void resetAll() {
+ fpslic.cell(0,PLANE_RESET_ALL_WHEN_LOW).ylut(0x00);
+ fpslic.flush();
+ fpslic.cell(0,PLANE_RESET_ALL_WHEN_LOW).ylut(0xff);
+ fpslic.flush();
+ }
+
+ /** configures the ylut of the cell at (0,plane) to drive plane "plane" across the entire chip */
+ private void drivePlane(int plane) {
+ for(int i=0; i<=23; i++){
+ FpslicDevice.Cell c = fpslic.cell(0, i);
+ c.h(plane, true);
+ c.v(plane, true);
+ if (c.vwire(plane).south() != null)
+ c.vwire(plane).south().drives(c.vwire(plane), true);
+ for(FpslicDevice.SectorWire sw = c.hwire(plane).east();
+ sw!=null;
+ sw=sw.east())
+ sw.west().drives(sw, true);
+ }
+ fpslic.cell(0, plane-L0).c(YLUT);
+ fpslic.cell(0, plane-L0).b(false);
+ fpslic.cell(0, plane-L0).f(false);
+ fpslic.cell(0, plane-L0).out(plane, true);
+ }
+
+ /** causes the master cell's successor output to be set to the given value */
+ protected void forceMasterSuccessor(boolean high) {
+ masterCell().ylut(0xff);
+ masterCell().xo(false);
+ masterCell().yo(false);
+ masterCell().xlut(high ? 0xff : 0x00);
+ fpslic.flush();
+ }
+
+ /** causes the master cell's successor output to resume normal functionality, leaving it in state "state" */
+ protected void unForceMasterSuccessor(boolean state) {
+ pauseSlaves();
+ masterCell().xo(true);
+ masterCell().yo(true);
+ masterCell().xlut(LUT_Z);
+ fpslic.flush();
+ masterCell().ylut(!state ? 0x00 : 0xff);
+ fpslic.flush();
+ pauseMaster();
+ masterCell().ylut((LUT_SELF & ~LUT_OTHER) |
+ (LUT_Z & ~LUT_OTHER) |
+ (LUT_Z & LUT_SELF));
+ fpslic.flush();
+ unPauseMaster();
+ unPauseSlaves();
+ }
+
+
+ protected int init(int size) {
+ return init(size, this.start);
+ }
+ protected int init(int size, FpslicDevice.Cell start) {
+ for(int x=1; x<24; x++)
+ for(int y=0; y<24; y++) {
+ FpslicDevice.Cell c = fpslic.cell(x, y);
+ c.xlut(0x00);
+ c.ylut(0x00);
+ c.b(false);
+ c.f(false);
+ c.c(YLUT);
+ }
+ ExperimentUtils.setupScanCell(fpslic);
+ fpslic.flush();
+
+ this.start = start;
+ drivePlane(L0);
+ drivePlane(L1);
+ drivePlane(L2);
+ drivePlane(L3);
+
+ int rsize = 0;
+
+ // create a column of dividers
+ FpslicDevice.Cell div;
+
+ if (size == 4) {
+ rsize = 4;
+ pipe(start.west().north(), start.west().north().north(), new int[] { NE, SOUTH, NW, SOUTH });
+ div = start.east();
+ // annoying "bridge cell", because dividers must take input from the north
+ div.north().yo(start.north());
+ div.north().xo(start.north());
+ } else {
+ rsize = size-createPipeline(start, true, size-4, false);
+ unPauseMaster();
+ unPauseSlaves();
+ pipe(start.west().north(), start.west(), new int[] { NE, EAST, SW, SOUTH });
+ div = start.east();
+ // annoying "bridge cell", because dividers must take input from the north
+ div.north().yo(start.north());
+ div.north().xo(start.north());
+ }
+
+ dividers = 0;
+ while(div != null) {
+ FpslicDevice.Cell xdiv = ExperimentUtils.divider(div);
+ dividers++;
+ if (xdiv==null) break;
+ div = xdiv;
+ }
+ div = div.south().east(); // lower-right hand corner of the last divider placed
+ if (dividers < 10) {
+ div.east().yo(div);
+ div = div.east();
+ while(div.north() != null) {
+ div.north().yo(div);
+ div = div.north();
+ }
+ div.xo(div.south());
+ div.east().yo(div);
+ div.east().xo(div);
+ div = div.east();
+ div.east().xo(div);
+ div.east().yo(div);
+ div.south().yo(div);
+ div = div.south();
+ while(div != null && dividers < 10) {
+ FpslicDevice.Cell xdiv = ExperimentUtils.divider(div);
+ dividers++;
+ if (xdiv==null) { div = div.south().east(); break; }
+ if (dividers >= 10) { div = div.south().east(); break; }
+ div = xdiv;
+ }
+ }
+ while(div.south() != null) {
+ div.south().yo(div);
+ div = div.south();
+ }
+ while(div.east() != null) {
+ div.east().yo(div);
+ div = div.east();
+ }
+ // assumption that we wind up in the lower-right-hand corner
+
+ return rsize;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ /** create a pipeline starting at cell "c", with predecessor "prev", and move in the directions
+ * specified by "dirs" */
+ private FpslicDevice.Cell pipe(FpslicDevice.Cell c, FpslicDevice.Cell prev, int[] dirs) {
+ for(int i=0; i<dirs.length; i++) {
+ FpslicDevice.Cell next = c.dir(dirs[i]);
+ micropipelineStage(c, prev, next);
+ prev = c;
+ c = next;
+ }
+ return c;
+ }
+
+ /** this is really ugly and I no longer understand it */
+ private int createPipeline(FpslicDevice.Cell c, boolean downward, int length, boolean start) {
+ boolean stop = false;
+ do {
+ if (downward) {
+ if (c.row < 6) {
+ if (length < 8+4) { stop = true; break; }
+ length -= 8;
+ c = pipe(c, c.north(), new int[] { SW, EAST, SW, WEST, NW, NORTH });
+ c = c.se();
+ c = pipe(c, c.north(), new int[] { NE, NORTH });
+ c = c.sw().west();
+ downward = false;
+ } else {
+ if (length < 8+4) { stop = true; break; }
+ length -= 8;
+ c = micropipelineStage(c, c.north(), c.sw());
+ c = micropipelineStage(c, c.ne(), c.south());
+ c = micropipelineStage(c, c.north(), c.se());
+ c = micropipelineStage(c, c.nw(), c.south());
+ c = c.nw();
+ c = micropipelineStage(c, c.south(), c.ne());
+ c = micropipelineStage(c, c.sw(), c.north());
+ c = micropipelineStage(c, c.south(), c.nw());
+ micropipelineStage(c, c.se(), c.north());
+ c = c.south().south().south().south().east();
+ }
+ } else {
+ if (c.row > c.fpslic().getHeight()-7) {
+ if (length < 8+4) { stop = true; break; }
+ length -= 8;
+ c = pipe(c, c.south(), new int[] { NW, SOUTH });
+ c = c.nw();
+ c = pipe(c, c.south(), new int[] { NE, EAST, SE, WEST, SE, SOUTH });
+ c = c.nw().west();
+ downward = true;
+ } else {
+ if (length < 8+4) { stop = true; break; }
+ length -= 8;
+ FpslicDevice.Cell ret = c = pipe(c, c.south(), new int[] { NE, NORTH, NW, NORTH });
+ c = c.se();
+ c = pipe(c, c.north(), new int[] { SW, SOUTH, SE, SOUTH });
+ c = ret;
+ }
+ }
+ } while(false);
+ if (stop) {
+ length -= 4;
+ if (downward) {
+ c = micropipelineStage(c, c.north(), c.sw());
+ c = micropipelineStage(c, c.ne(), c.west());
+ c = micropipelineStage(c, c.east(), c.ne());
+ c = micropipelineStage(c, c.sw(), c.north());
+ } else {
+ c = pipe(c, c.south(), new int[] { NW, EAST, SE, SOUTH });
+ }
+ return length;
+ } else {
+ return createPipeline(c, downward, length, false);
+ }
+ }
+
+ private FpslicDevice.Cell micropipelineStage(FpslicDevice.Cell c,
+ FpslicDevice.Cell prev,
+ FpslicDevice.Cell next) {
+ boolean polarity = false;
+ switch(c.dir(next)) {
+ case NORTH: case SOUTH: case EAST: case WEST:
+ switch (c.dir(prev)) {
+ case NORTH: case SOUTH: case EAST: case WEST: throw new Error("cannot have prev&next both use y");
+ }
+ polarity = false;
+ break;
+ case NW: case SE: case SW: case NE:
+ switch (c.dir(prev)) {
+ case NW: case SE: case SW: case NE: throw new Error("cannot have prev&next both use x");
+ }
+ polarity = true;
+ break;
+ default: throw new Error();
+ }
+
+ c.yi(polarity ? prev : next);
+ c.xi(polarity ? next : prev);
+
+ c.b(false);
+ c.f(false);
+ c.yo(true);
+ c.xo(true);
+ c.c(ZMUX);
+
+ c.wi(PLANE_RESET_ALL_WHEN_LOW);
+ c.t(TMUX_W_AND_FB);
+
+ for(int i=L0; i<=L3; i++) c.h(i, true);
+
+ if (!polarity) {
+ if (c.row==masterCell().row && c.col==masterCell().col) {
+ c.zi(PLANE_PAUSE_MASTER_WHEN_HIGH);
+ } else {
+ c.zi(PLANE_PAUSE_SLAVES_WHEN_HIGH);
+ }
+ c.ylut((LUT_SELF & ~LUT_OTHER) |
+ (LUT_Z & ~LUT_OTHER) |
+ (LUT_Z & LUT_SELF));
+ c.xlut(LUT_Z);
+ } else {
+ /*
+ // internally asymmetric
+ c.zi(PLANE_PAUSE_SLAVES_WHEN_LOW);
+ c.xlut((LUT_SELF & ~LUT_OTHER) |
+ (LUT_Z & ~LUT_OTHER) |
+ (LUT_Z & LUT_SELF));
+ c.ylut(LUT_Z);
+ */
+
+ // internally symmetric
+ c.zi(PLANE_PAUSE_SLAVES_WHEN_HIGH);
+ c.ylut((~LUT_SELF & LUT_OTHER) |
+ (LUT_Z & ~LUT_SELF) |
+ (LUT_Z & LUT_OTHER));
+ c.xlut(LUT_Z);
+ }
+ return next;
+ }
+
+
+
+}
--- /dev/null
+package edu.berkeley.slipway.demos;
+
+import java.io.*;
+import java.util.*;
+import java.awt.*;
+import com.atmel.fpslic.*;
+import edu.berkeley.slipway.*;
+import edu.berkeley.slipway.gui.*;
+import edu.berkeley.slipway.util.*;
+import static com.atmel.fpslic.FpslicConstants.*;
+
+
+/**
+ * This demo runs the asynchronous micropipeline fifo experiment from
+ * the FCCM paper.
+ *
+ * Output is placed in misc/data/async/ as a collection of .csv
+ * files. Each file is named sizeXXX.csv, where XXX is the capacity
+ * of the fifo. Each line of each file is of the form
+ * occupancy,tokenrate where occupancy is the proportion of the fifo
+ * which is occupied (a number between 0 and 1) and tokenrate is the
+ * number of millions of tokens per second observed at a fixed point
+ * on the ring. All files should be concatenated in order to
+ * reproduce the graphs in the paper.
+ */
+public abstract class MicropipelineFifoDemo {
+
+ public SlipwayBoard slipway;
+ public FpslicDevice fpslic;
+ public FpslicDevice.Cell start;
+
+ // Abstract methods to implement //////////////////////////////////////////////////////////////////////////////
+
+ protected abstract int numDivisors();
+ protected abstract void forceMasterSuccessor(boolean high);
+ protected abstract void unForceMasterSuccessor(boolean state);
+ protected abstract void unPauseMaster();
+ protected abstract void unPauseSlaves();
+ protected abstract void pauseMaster();
+ protected abstract void pauseSlaves();
+ protected abstract void resetAll();
+ protected abstract int init(int size);
+ protected abstract int init(int size, FpslicDevice.Cell start);
+
+ // Constructors //////////////////////////////////////////////////////////////////////////////
+
+ public MicropipelineFifoDemo() throws Exception {
+ System.err.println("MicropipelineFifoDemo: initializing board...");
+ slipway = new SlipwayBoard();
+ fpslic = slipway.getFpslicDevice();
+ }
+
+ public void mainx(String[] s) throws Exception {
+ System.err.println("MicropipelineFifoDemo: setting up scan cell...");
+ ExperimentUtils.setupScanCell(fpslic);
+
+ for(int i=0; i<255; i++) {
+ slipway.readInterruptCount();
+ System.err.print("\rMicropipelineFifoDemo: paranoia -- flushing interrupt count: " + i + "/254 ");
+ }
+ System.err.println();
+
+ for(int i=1; i<402; i+=2) go(i);
+ System.err.println("MicropipelineFifoDemo: experiment is finished");
+ }
+
+
+ // Experiment Logic //////////////////////////////////////////////////////////////////////////////
+
+ /** drain the fifo */
+ protected void drain() {
+ while(true){
+ pauseMaster();
+ pauseSlaves();
+ resetAll();
+ unPauseMaster();
+ unPauseSlaves();
+ slipway.readInterruptCount();
+ try { Thread.sleep(100); } catch (Exception e) { }
+ int rc = slipway.readInterruptCount();
+ if (rc!=0) {
+ System.err.println("flush() failed => " + rc);
+ try { Thread.sleep(1000); } catch (Exception e) { }
+ continue;
+ }
+ break;
+ }
+ }
+
+ /** fill the fifo with "count" tokens */
+ protected void fill(int count) {
+ boolean yes = false;
+ for(int i=0; i<count; i++) {
+ pauseSlaves();
+ forceMasterSuccessor(yes);
+ unPauseSlaves();
+ yes = !yes;
+ }
+ if (count>0)
+ unForceMasterSuccessor(!yes);
+ }
+
+ public void go(int size) throws Exception {
+ int rsize = init(size, fpslic.cell(20, 20));
+
+ String sizes = rsize+"";
+ while(sizes.length()<3) sizes = "0"+sizes;
+ String fname = "misc/data/async/size"+sizes+".csv";
+ if (!new File(fname).exists()) {
+ System.err.println();
+ System.err.println("MicropipelineFifoDemo: fifo size is "+rsize+"...");
+ PrintWriter outfile = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fname)));
+ for(int i=rsize; i>=0; i-=2)
+ test(i, rsize, outfile);
+ outfile.flush();
+ outfile.close();
+ } else {
+ System.out.println("MicropipelineFifoDemo: file " + fname + " already exists; skipping");
+ }
+ }
+
+ public void test(int count, int size, PrintWriter outfile) throws Exception {
+ double[] results = new double[numtrials];
+
+
+ int clockdivisor = 64;
+ double occupancy = ((double)count)/((double)size);
+ int clockrate = 24; // (in mhz)
+
+ for(int i=0; i<results.length; i++) {
+ init(size);
+ fpslic.flush();
+ drain();
+ fpslic.flush();
+ fill(count);
+ fpslic.flush();
+
+ unPauseMaster();
+ unPauseSlaves();
+ fpslic.flush();
+
+ slipway.readInterruptCount();
+ Thread.sleep(1000);
+ int tokens = slipway.readInterruptCount();
+
+ double elapsed = (double)(slipway.readInterruptCountTime()/clockrate);
+
+ int multiplier = 1;
+ for(int j=0; j<numDivisors(); j++) multiplier *= 2;
+ multiplier /= clockdivisor;
+
+ double result = (tokens*multiplier)/elapsed; // in millions
+ results[i] = result;
+ }
+
+ double max = 0;
+ double min = Double.MAX_VALUE;
+ double total = 0;
+ for(int i=0; i<numtrials; i++) {
+ max = Math.max(max, results[i]);
+ min = Math.min(min, results[i]);
+ total += results[i];
+ }
+ total -= max;
+ total -= min;
+ total /= (numtrials-2);
+
+ // result is transitions/sec
+ outfile.println(size + ", " + occupancy + ", " + total);
+ outfile.flush();
+ System.out.println("num_tokens/capacity: "+count+"/"+size+
+ " occupancy="+((int)(occupancy*100.0)) +"%"+
+ " tokenrate=" + total);
+ }
+ private static final int numtrials = 5;
+
+ protected FpslicDevice.Cell topLeft() { return start.north().north(); }
+
+
+
+}
+
+
package edu.berkeley.slipway.gui;
import static com.atmel.fpslic.FpslicConstants.*;
-import static com.atmel.fpslic.FpslicUtil.*;
import edu.berkeley.slipway.*;
import java.awt.*;
import java.awt.geom.*;
import com.atmel.fpslic.*;
import edu.berkeley.slipway.*;
import static com.atmel.fpslic.FpslicConstants.*;
-import static com.atmel.fpslic.FpslicUtil.*;
import edu.berkeley.slipway.*;
import java.awt.*;
import java.awt.geom.*;
Graphics2D g;
G gg;
- Fpslic at40k;
- FtdiBoard drone;
+ FpslicDevice fpslic;
+ SlipwayBoard slipway;
private Cell[][] ca = new Cell[128][];
final JFileChooser fc = new JFileChooser();
int returnVal = fc.showSaveDialog(this);
Writer pw = new OutputStreamWriter(new FileOutputStream(fc.getSelectedFile()));
- FpslicUtil.writeMode4(pw, drone);
+ slipway.getFpslicDevice().writeMode4(pw);
pw.flush();
pw.close();
System.err.println("done writing");
try {
final JFileChooser fc = new JFileChooser();
int returnVal = fc.showOpenDialog(this);
- FpslicUtil.readMode4(new FileInputStream(fc.getSelectedFile()), drone);
+ slipway.getFpslicDevice().readMode4(new FileReader(fc.getSelectedFile()));
System.err.println("done reading");
repaint();
} catch (Exception e) {
}
}
- public Gui(Fpslic at40k, FtdiBoard drone) {
- this(at40k, drone, 24, 24);
+ public Gui(FpslicDevice fpslic, SlipwayBoard slipway) {
+ this(fpslic, slipway, 24, 24);
}
- public Gui(Fpslic at40k, FtdiBoard drone, int width, int height) {
- super(drone);
- this.at40k = at40k;
- this.drone = drone;
+ public Gui(FpslicDevice fpslic, SlipwayBoard slipway, int width, int height) {
+ super(slipway);
+ this.fpslic = fpslic;
+ this.slipway = slipway;
for(int i=0; i<ca.length; i++)
ca[i] = new Cell[128];
for(int x=0; x<width; x++)
for(int y=0; y<height; y++)
- new Cell(x,y, at40k.cell(x, y));
+ new Cell(x,y, fpslic.cell(x, y));
/*
- Fpslic.Cell c = at40k.cell(0,0);
+ FpslicDevice.Cell c = fpslic.cell(0,0);
for(int i=0; i<256; i++) {
c.ylut(i);
System.out.println(c.printYLut());
}
public class Cell {
- Fpslic.Cell cell;
+ FpslicDevice.Cell cell;
boolean in = false;
public boolean scanme = false;
public boolean xon = false;
public boolean xknown = false;
public boolean yknown = false;
int _x, _y;
- public Cell(int x, int y, Fpslic.Cell cell) {
+ public Cell(int x, int y, FpslicDevice.Cell cell) {
_x = x;
_y = y;
ca[_x][_y] = this;
return null;
}
- public static boolean xlut_relevant(Fpslic.Cell c) {
+ public static boolean xlut_relevant(FpslicDevice.Cell c) {
return c.xlut_relevant();
}
}
public void scan() {
- for(int x=0; x<at40k.getWidth(); x++)
- for(int y=0; y<at40k.getHeight(); y++)
+ for(int x=0; x<fpslic.getWidth(); x++)
+ for(int y=0; y<fpslic.getHeight(); y++)
if (ca[x][y] != null)
if (ca[x][y].scanme())
scan(ca[x][y]);
}
public void scan(final Gui.Cell c) {
try {
- final Fpslic.Cell cell = c.cell;
- scan(at40k, cell, NONE, true);
+ final FpslicDevice.Cell cell = c.cell;
+ scan(fpslic, cell, NONE, true);
boolean safe = !cell.fb_relevant();
if (cell.xo()) safe = false;
if (cell.yo()) safe = false;
int oldc = cell.c();
if (cell.xlut_relevant()) {
cell.c(XLUT);
- drone.readBus(new BCB(c, XLUT));
+ slipway.readFpgaData(new BCB(c, XLUT));
} else {
c.xknown = false;
}
if (cell.ylut_relevant()) {
cell.c(YLUT);
- drone.readBus(new BCB(c, YLUT));
+ slipway.readFpgaData(new BCB(c, YLUT));
} else {
c.yknown = false;
}
if (!cell.xlut_relevant()) {
c.xknown = false;
} else {
- drone.readBus(new BCB(c, XLUT));
+ slipway.readFpgaData(new BCB(c, XLUT));
}
/*
if (!cell.yo())
- for(Fpslic.Cell c2 : new Fpslic.Cell[] { cell.north(), cell.south(), cell.east(), cell.west() })
+ for(FpslicDevice.Cell c2 : new FpslicDevice.Cell[] { cell.north(), cell.south(), cell.east(), cell.west() })
if (c2!=null && !c2.relevant()) {
- scan(at40k, cell, NONE, false);
+ scan(fpslic, cell, NONE, false);
c2.yo(cell);
c2.c(YLUT);
- scan(at40k, c2, NONE, true);
- drone.readBus(new BCB(c, YLUT));
- scan(at40k, c2, NONE, false);
+ scan(fpslic, c2, NONE, true);
+ slipway.readFpgaData(new BCB(c, YLUT));
+ scan(fpslic, c2, NONE, false);
c2.yi(NONE);
return;
}
if (!cell.ylut_relevant()) {
c.yknown = false;
} else {
- drone.readBus(new BCB(c, YLUT));
+ slipway.readFpgaData(new BCB(c, YLUT));
}
/*
if (!cell.xo())
- for(Fpslic.Cell c2 : new Fpslic.Cell[] { cell.nw(), cell.sw(), cell.ne(), cell.se() })
+ for(FpslicDevice.Cell c2 : new FpslicDevice.Cell[] { cell.nw(), cell.sw(), cell.ne(), cell.se() })
if (c2!=null && !c2.relevant()) {
- scan(at40k, cell, NONE, false);
+ scan(fpslic, cell, NONE, false);
c2.xo(cell);
- scan(at40k, c2, NONE, true);
+ scan(fpslic, c2, NONE, true);
c2.c(XLUT);
- drone.readBus(new BCB(c, XLUT));
- scan(at40k, c2, NONE, false);
+ slipway.readFpgaData(new BCB(c, XLUT));
+ scan(fpslic, c2, NONE, false);
c2.xi(NONE);
return;
}
break;
case ZMUX: {
/*
- scan(at40k, cell, NONE, false);
+ scan(fpslic, cell, NONE, false);
c.xknown = false;
c.yknown = false;
if (!cell.xo())
- for(Fpslic.Cell c2 : new Fpslic.Cell[] { cell.nw(), cell.sw(), cell.ne(), cell.se() })
+ for(FpslicDevice.Cell c2 : new FpslicDevice.Cell[] { cell.nw(), cell.sw(), cell.ne(), cell.se() })
if (c2!=null && !c2.relevant()) {
- scan(at40k, cell, NONE, false);
+ scan(fpslic, cell, NONE, false);
c2.xo(cell);
- scan(at40k, c2, NONE, true);
+ scan(fpslic, c2, NONE, true);
c2.c(XLUT);
- drone.readBus(new BCB(c, XLUT));
- scan(at40k, c2, NONE, false);
+ slipway.readFpgaData(new BCB(c, XLUT));
+ scan(fpslic, c2, NONE, false);
c2.xi(NONE);
return;
}
if (!cell.yo())
- for(Fpslic.Cell c2 : new Fpslic.Cell[] { cell.north(), cell.south(), cell.east(), cell.west() })
+ for(FpslicDevice.Cell c2 : new FpslicDevice.Cell[] { cell.north(), cell.south(), cell.east(), cell.west() })
if (c2!=null && !c2.relevant()) {
c2.yo(cell);
c2.c(YLUT);
- scan(at40k, c2, NONE, true);
- drone.readBus(new BCB(c, YLUT));
- scan(at40k, c2, NONE, false);
+ scan(fpslic, c2, NONE, true);
+ slipway.readFpgaData(new BCB(c, YLUT));
+ scan(fpslic, c2, NONE, false);
c2.yi(NONE);
break;
}
}
}
- scan(at40k, cell, NONE, false);
+ scan(fpslic, cell, NONE, false);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
- public static void scan(Fpslic dev, Fpslic.Cell cell, int source, boolean setup) {
+ public static void scan(FpslicDevice dev, FpslicDevice.Cell cell, int source, boolean setup) {
if (setup) {
if (source != NONE) cell.c(source);
if (cell.b()) cell.b(false);
if (cell.out(L3)!=setup) cell.out(L3, setup);
if (cell.vx(L3)!=setup) cell.v(L3, setup);
- Fpslic.SectorWire sw = cell.vwire(L3);
+ FpslicDevice.SectorWire sw = cell.vwire(L3);
//System.out.println("wire is: " + sw);
if (sw.row > (12 & ~0x3) && sw.north()!=null && sw.north().drives(sw))
int made = 0;
- private class BCB extends FtdiBoard.ByteCallback {
+ private class BCB extends SlipwayBoard.ByteCallback {
Gui.Cell c;
int who;
public BCB(Gui.Cell c, int who) {
import com.atmel.fpslic.*;
import edu.berkeley.slipway.*;
import static com.atmel.fpslic.FpslicConstants.*;
-import static com.atmel.fpslic.FpslicUtil.*;
import edu.berkeley.slipway.*;
import java.awt.*;
import java.awt.geom.*;
Graphics2D g;
G gg;
- Fpslic at40k;
- FtdiBoard drone;
+ FpslicDevice at40k;
+ SlipwayBoard drone;
private Cell[][] ca = new Cell[128][];
public static final Color nonselectedcell = new Color(0xee, 0xee, 0xee);
public static final Color selectedcell = new Color(0x00, 0x00, 0x00);
- private FtdiBoard ftdiboard;
- public Gui2(Fpslic at40k, FtdiBoard drone) {
+ private SlipwayBoard ftdiboard;
+ public Gui2(FpslicDevice at40k, SlipwayBoard drone) {
this(at40k, drone, 24, 24);
}
- public Gui2(Fpslic at40k, FtdiBoard drone, int width, int height) {
+ public Gui2(FpslicDevice at40k, SlipwayBoard drone, int width, int height) {
this.at40k = at40k;
this.drone = drone;
for(int i=0; i<ca.length; i++)
}
public class Cell {
- Fpslic.Cell cell;
+ FpslicDevice.Cell cell;
boolean in = false;
public boolean scanme = false;
public boolean xon = false;
public boolean xknown = false;
public boolean yknown = false;
int _x, _y;
- public Cell(int x, int y, Fpslic.Cell cell) {
+ public Cell(int x, int y, FpslicDevice.Cell cell) {
_x = x;
_y = y;
ca[_x][_y] = this;
return null;
}
- public static boolean xlut_relevant(Fpslic.Cell c) {
+ public static boolean xlut_relevant(FpslicDevice.Cell c) {
return c.xlut_relevant();
}
int made = 0;
- private class BCB extends FtdiBoard.ByteCallback {
+ private class BCB extends SlipwayBoard.ByteCallback {
Gui2.Cell c;
int who;
public BCB(Gui2.Cell c, int who) {
import com.atmel.fpslic.*;
import edu.berkeley.slipway.*;
import static com.atmel.fpslic.FpslicConstants.*;
-import static com.atmel.fpslic.FpslicUtil.*;
import static java.awt.event.KeyEvent.*;
import edu.berkeley.slipway.*;
import java.awt.*;
public class Gui3 extends Canvas implements MouseWheelListener, MouseMotionListener, KeyListener {
- Fpslic at40k;
- FtdiBoard drone;
+ FpslicDevice at40k;
+ SlipwayBoard slipway;
private int width;
private int height;
private int magnify = 0;
public GuiCell[][] ca = new GuiCell[128][];
- private FtdiBoard ftdiboard;
- public Gui3(Fpslic at40k, FtdiBoard drone) {
- this(at40k, drone, 24, 24);
+ private SlipwayBoard ftdiboard;
+ public Gui3(FpslicDevice at40k, SlipwayBoard slipway) {
+ this(at40k, slipway, 24, 24);
}
- public Gui3(Fpslic at40k, FtdiBoard drone, int width, int height) {
+ public Gui3(FpslicDevice at40k, SlipwayBoard slipway, int width, int height) {
this.at40k = at40k;
- this.drone = drone;
+ this.slipway = slipway;
this.width = width;
this.height = height;
for(int i=0; i<ca.length; i++)
repaint();
}
- Fpslic.Cell selectedCell = null;
+ FpslicDevice.Cell selectedCell = null;
public void _paint(Graphics2D g_) {
int SIZE = 100;
//g_.setStroke(new BasicStroke((float)1.0/SIZE));
private static final int LOCAL_ROUTING_CHANNEL_WIDTH = 7;
public boolean val = false;
- public final Fpslic.Cell fpslicCell;
+ public final FpslicDevice.Cell fpslicCell;
private GuiGate xgate = new GuiGate(this);
private GuiGate ygate = new GuiGate(this);
R gateArea = null;
- public GuiCell(Fpslic.Cell fpslicCell) {
+ public GuiCell(FpslicDevice.Cell fpslicCell) {
this.fpslicCell = fpslicCell;
}
import com.atmel.fpslic.*;
import static com.atmel.fpslic.FpslicConstants.*;
-import static com.atmel.fpslic.FpslicUtil.*;
import edu.berkeley.slipway.*;
import java.awt.*;
import java.awt.geom.*;
--- /dev/null
+package edu.berkeley.slipway.gui;
+
+import static com.atmel.fpslic.FpslicConstants.*;
+import static edu.berkeley.slipway.gui.GuiConstants.*;
+import com.atmel.fpslic.*;
+import edu.berkeley.slipway.*;
+import java.awt.*;
+
+public class Inspector {
+
+ private static P bump(P p, R r) {
+ p = p.translate(0, 15);
+ if (p.y + 15 > r.maxy()) {
+ p = new P(p.x + 200, r.miny() + 20);
+ }
+ return p;
+ }
+ public static void draw(G g, R r, FpslicDevice.Cell cell) {
+ g.color(0x000000);
+ r.fill(g);
+ g.color(0xffffff);
+ g.setFont(new Font("monospaced", 0, 14));
+ if (cell==null) return;
+
+ int line = (int)(r.miny() + 10);
+ P p = new P(r.minx() + 10, r.miny() + 20);
+ g.drawString("selected: " + cell.col + "," + cell.row, p); p = bump(p, r);
+ g.drawString(" xlut: " + XLUT_EQUATIONS[cell.xlut() & 0xff], p); p = bump(p, r);
+ g.drawString(" ylut: " + YLUT_EQUATIONS[cell.ylut() & 0xff], p); p = bump(p, r);
+ String xi = "??";
+ switch(cell.xi()) {
+ case NW : xi = "NW"; break;
+ case NE : xi = "NE"; break;
+ case SW : xi = "SW"; break;
+ case SE : xi = "SE"; break;
+ case NONE : xi = "."; break;
+ default: xi = "L"+(cell.xi()-L0); break;
+ }
+ g.drawString("x-in mux: " + xi, p); p = bump(p, r);
+
+ String yi = "??";
+ switch(cell.yi()) {
+ case NORTH : yi = "NORTH"; break;
+ case SOUTH : yi = "SOUTH"; break;
+ case EAST : yi = "EAST"; break;
+ case WEST : yi = "WEST"; break;
+ case NONE : yi = "."; break;
+ default: yi = "L"+(cell.yi()-L0); break;
+ }
+ g.drawString("y-in mux: " + yi, p); p = bump(p, r);
+
+ g.drawString("w-in mux: " + (cell.wi()==NONE ? "." : ("L"+(cell.wi()-L0))),
+ p); p = bump(p, r);
+ g.drawString("z-in mux: " + (cell.zi()==NONE ? "." : ("L"+(cell.zi()-L0))),
+ p); p = bump(p, r);
+
+ String tm = "??";
+ switch(cell.t()) {
+ case TMUX_FB: tm = "fb"; break;
+ case TMUX_W_AND_FB: tm = "w&fb"; break;
+ case TMUX_Z: tm = "z"; break;
+ case TMUX_W_AND_Z: tm = "w&z"; break;
+ case TMUX_W: tm = "w"; break;
+ }
+ g.drawString("t-in mux: " + tm, p); p = bump(p, r);
+
+ g.drawString(" set/rst: " + (cell.ff_reset_value() ? "reset=SET" : "."),
+ p); p = bump(p, r);
+
+ String outs = "";
+ for(int i=0; i<5; i++) outs += (cell.out(L0+i) ? (i+" ") : ". ");
+ g.drawString(" out: " + outs,
+ p); p = bump(p, r);
+ String hs = "";
+ for(int i=0; i<5; i++) hs += (cell.hx(L0+i) ? (i+" ") : ". ");
+ g.drawString(" h conn: " + hs,
+ p); p = bump(p, r);
+ String vs = "";
+ for(int i=0; i<5; i++) vs += (cell.vx(L0+i) ? (i+" ") : ". ");
+ g.drawString(" v conn: " + vs,
+ p); p = bump(p, r);
+ g.drawString("out enab: " + (cell.oe()==H4 ? "H4" : cell.oe()==V4 ? "V4" : "."),
+ p); p = bump(p, r);
+ g.drawString(" c-mux: " + (cell.c()==ZMUX ? "zmux" : cell.c()==XLUT ? "x-lut" : "y-lut"),
+ p); p = bump(p, r);
+ g.drawString(" fb src: " + (cell.f() ? "clocked" : "."),
+ p); p = bump(p, r);
+ g.drawString(" bypass: " + (cell.b() ? "clocked" : "."),
+ p); p = bump(p, r);
+ g.drawString(" x out: " + (cell.xo() ? (cell.b() ? "register" : "center") : "."),
+ p); p = bump(p, r);
+ g.drawString(" y out: " + (cell.yo() ? (cell.b() ? "register" : "center") : "."),
+ p); p = bump(p, r);
+
+ }
+}
\ No newline at end of file
package edu.berkeley.slipway.gui;
import static com.atmel.fpslic.FpslicConstants.*;
-import static com.atmel.fpslic.FpslicUtil.*;
import edu.berkeley.slipway.*;
import java.awt.*;
import java.awt.geom.*;
import com.atmel.fpslic.*;
import static com.atmel.fpslic.FpslicConstants.*;
-import static com.atmel.fpslic.FpslicUtil.*;
import edu.berkeley.slipway.*;
import java.awt.*;
import java.awt.geom.*;
private Point2D recenter = new Point2D.Double(-100, 2500);
private Point2D recenter2;
- private FtdiBoard ftdiboard;
+ private SlipwayBoard ftdiboard;
- public ZoomingPanel(FtdiBoard ftdiboard) {
+ public ZoomingPanel(SlipwayBoard ftdiboard) {
this.ftdiboard = ftdiboard;
setDoubleBuffered(true);
addKeyListener(this);
}
}
Gui.Cell cell = whichCell(mousex, mousey);
- Fpslic.Cell c = cell == null ? null : cell.cell;
+ FpslicDevice.Cell c = cell == null ? null : cell.cell;
if ((k.getModifiers() & k.ALT_MASK) != 0 || (k.getModifiers() & k.META_MASK) != 0)
switch(k.getKeyCode()) {
case VK_S:
return;
}
case VK_I: {
- System.out.println("interrupt count => " + ftdiboard.readCount());
+ System.out.println("interrupt count => " + ftdiboard.readInterruptCount());
repaint();
return;
}
import com.atmel.fpslic.*;
import static com.atmel.fpslic.FpslicConstants.*;
-import static com.atmel.fpslic.FpslicUtil.*;
import edu.berkeley.slipway.*;
import java.awt.*;
import java.awt.geom.*;
}
}
Gui2.Cell cell = whichCell(mousex, mousey);
- Fpslic.Cell c = cell == null ? null : cell.cell;
+ FpslicDevice.Cell c = cell == null ? null : cell.cell;
if ((k.getModifiers() & k.ALT_MASK) != 0 || (k.getModifiers() & k.META_MASK) != 0)
switch(k.getKeyCode()) {
case VK_0: {
--- /dev/null
+// Copyright 2006-2007 all rights reserved; see LICENSE file for BSD-style license
+
+package edu.berkeley.slipway.mpar;
+import java.util.*;
+
+/** a mapping from keys of type <tt>K</tt> to <i>sets</i> of values of type <tt>T</tt> */
+public final class HashMapBag<K,V> implements MapBag<K,V> {
+
+ private final HashMap<K,HashSet<V>> hm = new HashMap<K,HashSet<V>>();
+
+ public void add(K k, V v) {
+ HashSet<V> hs = hm.get(k);
+ if (hs==null) hm.put(k, hs = new HashSet<V>());
+ size -= hs.size();
+ hs.add(v);
+ size += hs.size();
+ }
+
+ public void addAll(K k, Iterable<V> iv) {
+ for(V v : iv) add(k, v);
+ }
+
+ public int size(K k) {
+ HashSet<V> ret = hm.get(k);
+ return ret==null ? 0 : ret.size();
+ }
+ public HashSet<V> getAll(K k) {
+ HashSet<V> ret = hm.get(k);
+ if (ret==null) return new HashSet<V>();
+ return ret;
+ }
+
+ public void remove(K k, V v) {
+ if (hm.get(k)==null) return;
+ HashSet<V> hs = hm.get(k);
+ if (hs==null) return;
+ size -= hs.size();
+ hs.remove(v);
+ size += hs.size();
+ }
+
+ public void removeAll(K k, Iterable<V> iv) {
+ for(V v : iv) remove(k, v);
+ }
+
+ public void clear() { hm.clear(); }
+
+ public boolean contains(K k, V v) {
+ return hm.get(k)!=null && hm.get(k).contains(v);
+ }
+
+ public void addAll(HashMapBag<K,V> hmb) {
+ for(K k : hmb) addAll(k, hmb.getAll(k));
+ }
+ public void removeAll(HashMapBag<K,V> hmb) {
+ for(K k : hmb) removeAll(k, hmb.getAll(k));
+ }
+
+ public Iterator<K> iterator() { return hm.keySet().iterator(); }
+ public int size() { return size; }
+ private int size = 0;
+}
package edu.berkeley.slipway.mpar;
import com.atmel.fpslic.*;
+import java.awt.*;
import byucc.edif.tools.merge.*;
import byucc.edif.*;
import java.io.*;
import java.util.*;
import edu.berkeley.slipway.*;
+import edu.berkeley.abits.*;
import com.atmel.fpslic.*;
import static com.atmel.fpslic.FpslicConstants.*;
+import static edu.berkeley.slipway.mpar.PhysicalFpslic.*;
// FIXME: sometimes gets stuck in a loop routing the last few nets
public class MPARDemo {
- public static final double alphaParameter = 00.9;
- public static final double betaParameter = 02.5;
- public static final double gammaParameter = 1.0;
- /*
- test code for inter-sector switchboxes
- public static void main2() throws Exception {
- Fpslic fpslic = new FtdiBoard();
- // set up scan cell
- fpslic.cell(23,15).h(3, true);
- fpslic.cell(23,15).yi(L3);
- fpslic.cell(23,15).ylut(0xAA);
- fpslic.iob_right(15, true).enableOutput(WEST);
- fpslic.cell(23,0).ylut(0x00);
- fpslic.iob_right(0, true).enableOutput(WEST);
- fpslic.flush();
- for(int x=0; x<20; x++) {
- for(int y=0; y<20; y++) {
- for(int l=0; l<5; l++) {
- for(int v = 0; v <= 1; v++) {
- boolean vert = v==1;
- int newx = vert ? x : x-1;
- int newy = vert ? y-1 : y;
- if (newx<0 || newy<0) continue;
- if (vert && (y%4) != 0) continue;
- if (!vert && (x%4) != 0) continue;
-
- int layer = l;
- if (layer==3) continue;
- Fpslic.Cell c = fpslic.cell(x, y);
- Fpslic.Cell c2 = fpslic.cell(newx, newy);
- Fpslic.SectorWire sw1 = vert ? c.vwire(layer) : c.hwire(layer);
- Fpslic.SectorWire sw2 = vert ? c2.vwire(layer) : c2.hwire(layer);
- sw1.drives(sw2, true);
-
- c.c(YLUT);
- if (vert) c.v(L0 + layer, true);
- else c.h(L0 + layer, true);
- c.out(L0 + layer, true);
- c.b(false);
-
- c2.yi(L0 + layer);
- if (vert) c2.v(L0 + layer, true);
- else c2.h(L0 + layer, true);
- c2.ylut(LUT_SELF);
- c2.c(YLUT);
- c2.b(false);
-
- System.out.print(x+","+y+","+l+","+(vert?"v":"h")+": ");
- c.ylut(0x00);
- fpslic.flush();
- boolean good = scan(fpslic, c2)==0;
- if (!good) fails++;
- System.out.print(good ? "ok " : "bad ");
- c.ylut(0xff);
- fpslic.flush();
- good = scan(fpslic, c2)!=0;
- if (!good) fails++;
- System.out.print(good ? "ok " : "bad ");
- System.out.println();
- sw1.drives(sw2, false);
- if (vert) c.v(layer, false);
- else c.h(layer, false);
- c.out(layer, false);
- }
- }
- }
- }
- System.out.println("fails = " + fails);
-
- }
- public static int fails = 0;
- */
+ public static final double alphaParameter = 0.9;
+ public static final double betaParameter = 0.5;
+ public static final double wireCost = 0.005;
+ public static final double wireCostPlacement = 0.01; // cost of an uncongested net (cost of congested net is 1)
+ //public static final double gammaParameter = 1.0;
+ public static final double lambda = 0.7;
+
+ public static double temperature = 300.0;
+ public static double congestion = 0;
+ public static double timingpenalty = 0;
public static void main(String[] s) throws Exception {
- EdifEnvironment topEnv = new EdifEnvironment("top");
- EdifLibraryManager elm = new EdifLibraryManager(topEnv);
- EdifLibrary initLib = new EdifLibrary(elm, "initLib");
- EdifEnvironment env = EdifMergeParser.parseAndMerge(s, initLib);
- System.out.println("top is " + env.getTopCell());
- NetList fnl = new NetList();
-
- for(Iterator<EdifCellInstance> it = (Iterator<EdifCellInstance>)env.getTopCell().cellInstanceIterator();
- it.hasNext();
- ) {
- NetList.Node n = fnl.createNode(it.next(), null);
- }
- Fpslic fpslic = new FtdiBoard();
- int width = 20;
- int height = 20;
- PhysicalDevice pd = new PhysicalFpslic(fpslic, width, height);
+ NetList fnl = new NetList(s[0]);
+ int width = 12;
+ int height = 12;
- int px = 0;
- int py = 0;
+ //SlipwayBoard slipway = new SlipwayBoard();
+ Board slipway = new FakeBoard(24, 24);
- // crude map
+ FpslicDevice fpslic = (FpslicDevice)slipway.getDevice();
+ while(true) {
+ PhysicalDevice pd = new PhysicalFpslic(fpslic, width, height);
+
+ Placement placement = new Placement(fnl, pd);
+ Routing routing = new Routing(placement);
Random rand = new Random();
- boolean[][] used = new boolean[width][height];
- for(NetList.Node n : fnl.nodes) {
- while(true) {
- px = Math.abs(rand.nextInt()) % width;
- py = Math.abs(rand.nextInt()) % height;
- if (!used[px][py]) {
- used[px][py] = true;
- System.out.println("placed " + n + " at ("+px+","+py+")");
- pd.getCell(px, py).place(n);
- break;
- }
- }
- }
+ placement.random(rand);
+ routing.routeAll();
int trial = 0;
- HashSet<NetList.LogicalNet> needUnroute = new HashSet<NetList.LogicalNet>();
- while(true) {
+ int num_moves = width*height;
+
+ Visualization vis = new Visualization((PhysicalFpslic)pd);
+
+ boolean alldone = false;
+ long lastDraw = System.currentTimeMillis();
+ OUT: while(true) {
System.out.println();
- System.out.println("routing trial " + (++trial));
- for(NetList.LogicalNet net : fnl.nets) {
- if (net.getSize() <= 1) continue;
- net.route(fpslic, pd);
- }
- double congestion = 0;
- int overrouted = 0;
- needUnroute.clear();
- for(PhysicalDevice.PhysicalNet pn : pd) {
- if (pn.isCongested()) {
- overrouted++;
- congestion += pn.getCongestion();
+ double max_swap_dist = 3 * Math.max(width,height) * Math.exp(-1 / temperature);
+ System.out.println("round " + (++trial) + " (temp="+temperature+", maxdist="+max_swap_dist+")");
+
+ if (alldone) break;
+
+ congestion = routing.measureCongestion();
+ timingpenalty = routing.measureTimingpenalty();
+ double wirecost = routing.measureWireCost();
+ int swaps = 0;
+ num_moves = 200;
+
+ for(int i=0; i<num_moves; i++) {
+ System.out.print("\r [place: " + i + "/" + num_moves + " congestion="+congestion+"]");
+ NetList.Node node1 = fnl.randomNode(rand);
+ PhysicalDevice.PhysicalCell cell1 = placement.nodeToCell(node1);
+ PhysicalDevice.PhysicalCell cell2 = cell1.randomCellWithin(rand, max_swap_dist);
+ NetList.Node node2 = placement.cellToNode(cell2);
+
+ // FIXME: cache and reuse "newrouting"
+ // also: fold down newrouting to collapse parentage
+ routing.checkpoint();
+ routing.unroute(node1);
+ routing.unroute(node2);
+ placement.unplace(cell1);
+ placement.unplace(cell2);
+ placement.place(node1, cell2);
+ placement.place(node2, cell1);
+ routing.routeAll();
+
+ double newcongestion = routing.measureCongestion();
+ double newwirecost = routing.measureWireCost();
+ double newtimingpenalty = routing.measureTimingpenalty();
+ double lam = 0.1;
+ double deltaCost =
+ lam * ((newcongestion - congestion) / Math.max(0.001, congestion))
+ +
+ //(1-lam) * ((newwirecost - wirecost) / wirecost)
+ //+
+ (1-lam) * ((newtimingpenalty - timingpenalty) / Math.max(0.001, timingpenalty))
+ ;
+ double swapProbability = Math.exp((-1 * deltaCost) / temperature);
+ //double dist = Math.sqrt( (5-p2x)*(5-p2x) + (5-p2y)*(5-p2y) );
+ double rad = 4;
+ /*
+ if (rand2 == null)
+ swapProbability = Math.max(0, Math.min(swapProbability, dist / Math.sqrt(rad+rad)));
+ */
+ boolean doSwap = Math.random() < swapProbability;
+ if (doSwap) {
+ swaps++;
+ congestion = newcongestion;
+ wirecost = newwirecost;
+ timingpenalty = newtimingpenalty;
+ } else {
+ placement.unplace(cell1);
+ placement.unplace(cell2);
+ placement.place(node1, cell1);
+ placement.place(node2, cell2);
+ routing.rollback();
}
- pn.updateCongestion();
- if (pn.isCongested())
- for(NetList.LogicalNet n : pn.getLogicalNets())
- needUnroute.add(n);
}
- System.out.println(" overrouted="+overrouted+", congestion="+congestion +
- ", ripping up " + needUnroute.size() +" nets of " + fnl.nets.size());
- if (overrouted <= 0) break;
- for(NetList.LogicalNet net : needUnroute) net.unroute();
+ double acceptance = ((double)swaps) / num_moves;
+ double gamma = 0;
+ if (acceptance > 0.96) gamma = 0.5;
+ else if (acceptance > 0.8) gamma = 0.9;
+ else if (acceptance > 0.15) gamma = 0.95;
+ else gamma = 0.8;
+
+ System.out.println(" acceptance="+acceptance);
+ temperature = temperature * gamma;
+ int num_routes = num_moves - swaps;
+ num_routes = 2;
+ for(int i=0; i<num_routes; i++) {
+ int overrouted = routing.measureOverloaded();
+ routing.unrouteOverloaded();
+ routing.reRouteAll();
+ System.out.print("\r [route "+i+"/"+num_routes+"] overrouted="+overrouted+" congestion="+routing.measureCongestion()+" penalty="+timingpenalty);
+ routing.updateCongestion(alphaParameter, betaParameter);
+ if (overrouted==0 && timingpenalty < 1) alldone = true;
+ }
+ num_moves = (int)(300 * gamma * gamma);
+ vis.draw(placement, routing, false);
+ System.out.println();
}
+ vis.draw(placement, routing, true);
+ placement.setPlacement();
+ routing.setPips(true);
+ System.out.println("wire utilization: " + Math.round(routing.measureWireUtilization()*100));
// set up scan cell
fpslic.cell(23,15).h(3, true);
fpslic.cell(23,0).ylut(0x00);
fpslic.iob_right(0, true).enableOutput(WEST);
fpslic.flush();
-
+ /*
int xwidth = 8;
- while(true) {
+ temperature = 0;
+ while(temperature==0) {
int a = Math.abs(rand.nextInt()) % (1 << xwidth);
int b = Math.abs(rand.nextInt()) % (1 << xwidth);
- setInput(fnl, fpslic, "a", a);
- setInput(fnl, fpslic, "b", b);
- setInput(fnl, fpslic, "ci", 0);
- int result = getOutput(fnl, fpslic, "out");
+ setInput(fnl, fpslic, "a", a, placement);
+ setInput(fnl, fpslic, "b", b, placement);
+ setInput(fnl, fpslic, "ci", 0, placement);
+ int result = getOutput(fnl, fpslic, slipway, "out", placement);
+ int expect = (a+b) & ~(-1 << (xwidth+1));
System.out.println(Integer.toString(a,16) + " + " +
Integer.toString(b,16) + " = " +
Integer.toString(result,16) +
- " [ " + (a+b==result ? "ok" : "bad" ) + " ] ");
+ " [ " + (expect==result ? "ok" : "bad" ) + " ] " + (Integer.toString((result^(expect)),16)));
}
+ */
+ }
}
private static int ret;
- public static synchronized int scan(final Fpslic device, final Fpslic.Cell cell) {
+ public static synchronized int scan(final FpslicDevice device, final SlipwayBoard slipway, final FpslicDevice.Cell cell) {
try {
- scan(device, cell, YLUT, true);
- ((FtdiBoard)device).readBus(new FtdiBoard.ByteCallback() {
+ scan(device, cell, XLUT, true);
+ slipway.readFpgaData(new SlipwayBoard.ByteCallback() {
public void call(byte b) throws Exception {
ret = b;
synchronized(device) {
device.wait();
} catch (Exception e) { throw new RuntimeException(e); }
}
- scan(device, cell, YLUT, false);
+ scan(device, cell, XLUT, false);
return ret;
} catch (Exception e) { throw new RuntimeException(e); }
}
- public static void scan(Fpslic dev, Fpslic.Cell cell, int source, boolean setup) {
+ public static void scan(FpslicDevice dev, FpslicDevice.Cell cell, int source, boolean setup) {
if (setup) {
//if (source != NONE) cell.c(source);
if (cell.b()) cell.b(false);
if (cell.out(L3)!=setup) cell.out(L3, setup);
if (cell.vx(L3)!=setup) cell.v(L3, setup);
- Fpslic.SectorWire sw = cell.vwire(L3);
+ FpslicDevice.SectorWire sw = cell.vwire(L3);
//System.out.println("wire is: " + sw);
if (sw.row > (12 & ~0x3) && sw.north()!=null && sw.north().drives(sw))
}
- public static void setInput(NetList fnl, Fpslic fpslic, String prefix, int val) {
- for(int i=0; ; i++) {
- NetList.Node n = fnl.top.get(prefix + "["+i+"]");
- if (n==null && i==0) n = fnl.top.get(prefix);
- if (n==null) return;
- Fpslic.Cell c = n.getPlacement(fpslic);
- c.c(XLUT);
- c.b(false);
- c.xlut((val & 0x1)==0 ? 0x00 : 0xff);
- val = val >> 1;
- }
+ public static void setInput(NetList fnl, FpslicDevice fpslic, String prefix, int val, Placement placement) {
+ for(int i=0; ; i++) {
+ NetList.Node n = fnl.top.get(prefix + "["+i+"]");
+ if (n==null && i==0) n = fnl.top.get(prefix);
+ if (n==null) return;
+ FpslicDevice.Cell c = ((PhysicalFpslic.PhysicalFpslicCell)placement.nodeToCell(n)).cell();
+ c.c(XLUT);
+ c.b(false);
+ c.xlut((val & 0x1)==0 ? 0x00 : 0xff);
+ val = val >> 1;
}
- public static int getOutput(NetList fnl, Fpslic fpslic, String prefix) {
+ }
+ public static int getOutput(NetList fnl, FpslicDevice fpslic, SlipwayBoard slipway, String prefix, Placement placement) {
int val = 0;
for(int i=0; ; i++) {
NetList.Node n = fnl.top.get(prefix+"["+i+"]");
if (n==null && i==0) n = fnl.top.get(prefix);
if (n==null) return val;
- Fpslic.Cell c = n.getPlacement(fpslic);
+ FpslicDevice.Cell c = ((PhysicalFpslic.PhysicalFpslicCell)placement.nodeToCell(n)).cell();
c.xlut(LUT_SELF);
c.c(XLUT);
c.b(false);
fpslic.flush();
- int scan = scan(fpslic, c);
+ int scan = scan(fpslic, slipway, c);
val |= ((scan==0 ? 0 : 1) << i);
}
}
--- /dev/null
+// Copyright 2006-2007 all rights reserved; see LICENSE file for BSD-style license
+
+package edu.berkeley.slipway.mpar;
+import java.util.*;
+
+/** a mapping from keys of type <tt>K</tt> to <i>sets</i> of values of type <tt>V</tt> */
+public interface MapBag<K,V> extends Iterable<K> {
+ public void add(K k, V v);
+ public void addAll(K k, Iterable<V> iv);
+ public Iterator<K> iterator();
+}
import byucc.edif.*;
import java.io.*;
import java.util.*;
+import java.awt.*;
import edu.berkeley.slipway.*;
import com.atmel.fpslic.*;
import static com.atmel.fpslic.FpslicConstants.*;
import static edu.berkeley.slipway.mpar.MPARDemo.*;
-public class NetList {
+public class NetList implements Iterable<NetList.Node> {
+
+ public NetList(String s) throws EdifNameConflictException, InvalidEdifNameException {
+ EdifEnvironment topEnv = new EdifEnvironment("top");
+ EdifLibraryManager elm = new EdifLibraryManager(topEnv);
+ EdifLibrary initLib = new EdifLibrary(elm, "initLib");
+ EdifEnvironment env = EdifMergeParser.parseAndMerge(new String[] { s }, initLib);
+ for(Iterator<EdifCellInstance> it = (Iterator<EdifCellInstance>)env.getTopCell().cellInstanceIterator();
+ it.hasNext();
+ ) {
+ createNode(it.next(), null);
+ }
+ }
private HashMap<String,Integer> ids = new HashMap<String,Integer>();
- public HashSet<Node> nodes = new HashSet<Node>();
+ public HashSet<Node> nodes = new HashSet<Node>();
+ public ArrayList<Node> nodes_ = new ArrayList<Node>();
+
public HashSet<LogicalNet> nets = new HashSet<LogicalNet>();
+ public Iterable<NetList.LogicalNet> getLogicalNets() { return nets; }
/** a node is some primitive element; a potential configuration of a CLB */
- public class Node {
- public PhysicalDevice.PhysicalCell physicalCell = null;
+ public class Node implements Iterable<Node.Port> {
private final String type;
private final int id;
- public int x = -1;
- public int y = -1;
-
private HashMap<String,Port> ports = new HashMap<String,Port>();
+ public Iterator<Port> iterator() { return ports.values().iterator(); }
public Node(String type) {
nodes.add(this);
+ nodes_.add(this);
this.type = type.toLowerCase();
Integer num = ids.get(type);
this.id = num == null ? 0 : num.intValue();
}
public String getType() { return type; }
public String toString() {
- if (x==-1 || y==-1)
- return type + "["+id+"]";
- return type + "@("+x+","+y+")";
+ return type;
}
public Port getPort(String name, boolean driver) {
Port p = ports.get(name);
return p;
}
- public Fpslic.Cell getPlacement(Fpslic fpslic) { return fpslic.cell(x, y); }
-
private int portIndex = 0;
-
/** a port is an input or output to a Node */
public class Port {
private final String name;
/** a Net is a collection of ports which are wired together */
public class LogicalNet implements Iterable<Node.Port> {
- private Node.Port driver = null;
- private HashSet<Node.Port> ports = new HashSet<Node.Port>();
- private HashSet<PhysicalDevice.PhysicalPip> pips = new HashSet<PhysicalDevice.PhysicalPip>();
- private HashSet<PhysicalDevice.PhysicalNet> pns = new HashSet<PhysicalDevice.PhysicalNet>();
-
- public void addPhysicalNet(PhysicalDevice.PhysicalNet pn) { pns.add(pn); }
- public void removePhysicalNet(PhysicalDevice.PhysicalNet pn) { pns.remove(pn); }
- public void addPhysicalPip(PhysicalDevice.PhysicalPip pip) { pips.add(pip); }
+ Node.Port driver = null;
+ HashSet<Node.Port> ports = new HashSet<Node.Port>();
public LogicalNet() { nets.add(this); }
public Iterator<Node.Port> iterator() { return ports.iterator(); }
public int getSize() { return ports.size(); }
- public boolean routed = false;
- public void unroute() {
- for(PhysicalDevice.PhysicalPip pip : pips) pip.set(false);
- while(pns.size() > 0) pns.iterator().next().removeLogicalNet(this);
- pips.clear();
- pns.clear();
- routed = false;
- }
- public void route(Fpslic fpslic, PhysicalDevice pd) {
- if (driver == null) return;
- if (routed) return;
- Node.Port[] dests = new Node.Port[ports.size() - (ports.contains(driver) ? 1 : 0)];
- int j = 0;
- for(Node.Port p : ports)
- if (p != driver)
- dests[j++] = p;
- PhysicalDevice.PhysicalNet[] destsp = new PhysicalDevice.PhysicalNet[dests.length];
- for(int i=0; i<dests.length; i++) {
- Node.Port dest = dests[i];
- switch(dest.index) {
- case 0: destsp[i] = dest.getNode().physicalCell.getNet("xi"); break;
- case 1: destsp[i] = dest.getNode().physicalCell.getNet("yi"); break;
- default: throw new Error();
- }
- }
- driver.getNode().physicalCell.getNet("out").route(destsp, this);
- routed = true;
- }
+
public void add(Node.Port p) {
if (p.driver) {
if (driver != null && driver != p)
}
return n;
}
+
+ public Node randomNode(Random rand) {
+ return nodes_.get(Math.abs(rand.nextInt()) % nodes_.size());
+ }
+
+ public Iterator<Node> iterator() { return nodes.iterator(); }
}
public abstract class PhysicalDevice implements Iterable<PhysicalDevice.PhysicalNet> {
public abstract PhysicalCell getCell(int col, int row);
+ public abstract PhysicalCell randomCell(Random rand);
private HashSet<PhysicalNet> allPhysicalNets = new HashSet<PhysicalNet>();
public Iterator<PhysicalNet> iterator() { return allPhysicalNets.iterator(); }
public abstract PhysicalNet getNet(String name);
public abstract void setFunction(String type);
public abstract void place(NetList.Node n);
+ public abstract PhysicalCell randomCellWithin(Random rand, double percentOfDevice);
}
+ private int master_idx = 0;
+
+ public int getNumPhysicalNets() { return master_idx; }
public class PhysicalNet implements Iterable<PhysicalPip>, Comparable<PhysicalNet> {
- // per-par-iteration variables
- private double congestion = 0;
- private int load = 0;
+ public final int idx = master_idx++;
// temporary variables used during route searches
- private double distance = Double.MAX_VALUE;
- private PhysicalNet backpointer = null;
+ double distance = Double.MAX_VALUE;
+ double delay = Double.MAX_VALUE;
+ PhysicalNet backpointer = null;
+ int iteration = 0;
+ int depth = 0;
+ boolean remaining = false;
// adjacent pips
- private final HashSet<PhysicalPip> pips = new HashSet<PhysicalPip>();
+ public final HashSet<PhysicalPip> pips = new HashSet<PhysicalPip>();
private String name;
- // logical nets currently mapped onto this physical net
- private HashSet<NetList.LogicalNet> logicalNets = new HashSet<NetList.LogicalNet>();
-
- public double getCongestion() { return congestion; }
- public boolean isCongested() { return load >= 2; }
- public void updateCongestion() {
- congestion = congestion * alphaParameter;
- if (isCongested()) congestion += betaParameter;
- }
-
- public Iterable<NetList.LogicalNet> getLogicalNets() { return logicalNets; }
- public void addLogicalNet(NetList.LogicalNet net) {
- if (logicalNets.contains(net)) return;
- logicalNets.add(net);
- load++;
- if (load >= 2) congestion += betaParameter;
- net.addPhysicalNet(this);
- }
- public void removeLogicalNet(NetList.LogicalNet net) {
- if (!logicalNets.contains(net)) return;
- logicalNets.remove(net);
- load--;
- net.removePhysicalNet(this);
- }
-
/** ordering is based on distance so we can use the Java PriorityQueue class */
public int compareTo(PhysicalNet pn) {
double x = distance - pn.distance;
- return distance > pn.distance
+ return x>0
? 1
- : distance < pn.distance
+ : x<0
? -1
: 0;
}
return pip;
return null;
}
- public void route(PhysicalNet[] dests, NetList.LogicalNet logicalNet) {
- HashSet<PhysicalNet> remainingDests = new HashSet<PhysicalNet>();
- for(PhysicalNet dest : dests) remainingDests.add(dest);
-
- HashSet<PhysicalNet> needsReset = new HashSet<PhysicalNet>();
- PriorityQueue<PhysicalNet> pq = new PriorityQueue<PhysicalNet>();
- needsReset.add(this);
- this.distance = 0;
- pq.add(this);
-
- OUTER: while(true) {
- PhysicalNet pn = pq.poll();
- if (pn==null) throw new Error("unroutable! " + this + " -> " + dests[0]);
- double frontier = pn.distance;
- for(PhysicalPip pip : pn)
- for(PhysicalNet net : pip.getDrivenNets()) {
- double newfrontier = frontier + pip.getCost(pn, net) + net.getCongestion();
-
- // penalty for using any net already routed in this iteration (makes routing order-sensitive)
- if (net.load >= 1) newfrontier = newfrontier + 20;
-
- if (net.distance <= newfrontier) continue;
- pq.remove(net); // if already in there
- net.distance = newfrontier;
- pq.add(net);
- needsReset.add(net);
- net.backpointer = pn;
-
- if (remainingDests.contains(net)) {
- remainingDests.remove(net);
- if (remainingDests.size()==0) break OUTER;
- // Vaughn Betz style multiterminal routing: once we reach one sink, make every node on the path
- // "distance zero" from the source.
- for(PhysicalNet pnx = net; pnx != null; pnx = pnx.backpointer) {
- pnx.distance = 0;
- pq.add(pnx);
- }
- break;
- }
- }
- }
-
- for(PhysicalNet dest : dests)
- for(PhysicalNet pn = dest; pn != null && pn.backpointer != null; pn = pn.backpointer) {
- pn.addLogicalNet(logicalNet);
- pn.distance = Double.MAX_VALUE;
- PhysicalPip pip = pn.getPipFrom(pn.backpointer);
- pip.set(true);
- logicalNet.addPhysicalPip(pip);
- }
-
- for(PhysicalNet pn : needsReset) {
- pn.distance = Double.MAX_VALUE;
- pn.backpointer = null;
- }
- }
}
public abstract class PhysicalPip {
- private PhysicalNet driver;
- private PhysicalNet[] driven;
+ public PhysicalNet driver;
+ public PhysicalNet[] driven;
private String name;
- private double defaultCost;
+ double defaultCost;
+ double defaultDelay = 1;
+ public abstract boolean prohibited();
public String toString() { return name; }
public PhysicalNet getDriverNet() { return driver; }
public PhysicalNet[] getDrivenNets() { return driven; }
+ public double getDelay(PhysicalNet in, PhysicalNet out) { return defaultDelay; }
public double getCost(PhysicalNet in, PhysicalNet out) { return defaultCost; }
- public PhysicalPip(String name, PhysicalNet driver, PhysicalNet[] driven) { this(name, driver, driven, 0.05); }
+ public abstract int getX();
+ public abstract int getY();
+ public PhysicalPip(String name, PhysicalNet driver, PhysicalNet[] driven) { this(name, driver, driven, wireCost); }
public PhysicalPip(String name, PhysicalNet driver, PhysicalNet[] driven, double defaultCost) {
this.name = name;
this.driver = driver;
this.driven = driven;
- this.defaultCost = defaultCost;
+ this.defaultCost = 1;
if (driver != null) driver.addPip(this);
for(PhysicalNet pn : driven) pn.addPip(this);
}
import static edu.berkeley.slipway.mpar.MPARDemo.*;
public class PhysicalFpslic extends PhysicalDevice {
- private final Fpslic fpslic;
+ public static int CELLSEP = 40;
+ public static int PLANESEP = 3;
+
+ private final FpslicDevice fpslic;
public final int width;
public final int height;
return cells[col][row];
}
- public PhysicalFpslic(final Fpslic fpslic, int width, int height) {
+ public PhysicalFpslic(final FpslicDevice fpslic, int width, int height) {
this.fpslic = fpslic;
this.width = width;
this.height = height;
for(int xc=x; xc<x+4; xc++) {
PhysicalNet vwire = new PhysicalNet("("+xc+","+y+"-"+(y+3)+")");
for(int yc=y; yc<y+4; yc++)
- sectorWires[xc][yc][p][0] = vwire;
+ if (xc < sectorWires.length && yc < sectorWires[xc].length)
+ sectorWires[xc][yc][p][0] = vwire;
}
for(int yc=y; yc<y+4; yc++) {
PhysicalNet hwire = new PhysicalNet("("+x+"-"+(x+3)+","+yc+")");
for(int xc=x; xc<x+4; xc++)
- sectorWires[xc][yc][p][1] = hwire;
+ if (xc < sectorWires.length && yc < sectorWires[xc].length)
+ sectorWires[xc][yc][p][1] = hwire;
}
}
final int xc = x;
final int yc = y;
final int pc = p;
- new PhysicalPip("xxx",
- sectorWires[x-1][y][p][1],
- new PhysicalNet[] { sectorWires[x][y][p][1] },
- 5) {
+ new PhysicalFpslicPip(x,
+ y,
+ -1 * (4-p) * PLANESEP,
+ -1 * (0+p) * PLANESEP,
+ "xxx",
+ sectorWires[x-1][y][p][1],
+ new PhysicalNet[] { sectorWires[x][y][p][1] },
+ 5) {
public void set(boolean connected) {
fpslic.cell(xc-1, yc).hwire(pc).drives(fpslic.cell(xc, yc).hwire(pc), connected);
}
};
- new PhysicalPip("xxx",
- sectorWires[x][y][p][1],
- new PhysicalNet[] { sectorWires[x-1][y][p][1] },
- 5) {
+ new PhysicalFpslicPip(x,
+ y,
+ -1 * (4-p) * PLANESEP,
+ -1 * (0+p) * PLANESEP,
+ "xxx",
+ sectorWires[x][y][p][1],
+ new PhysicalNet[] { sectorWires[x-1][y][p][1] },
+ 5) {
public void set(boolean connected) {
fpslic.cell(xc, yc).hwire(pc).drives(fpslic.cell(xc-1, yc).hwire(pc), connected);
}
final int xc = x;
final int yc = y;
final int pc = p;
- new PhysicalPip("xxx",
- sectorWires[x][y-1][p][0],
- new PhysicalNet[] { sectorWires[x][y][p][0] },
- 5) {
+ new PhysicalFpslicPip(x,
+ y,
+ -1 * (4-p) * PLANESEP,
+ -1 * (0+p) * PLANESEP,
+ "xxx",
+ sectorWires[x][y-1][p][0],
+ new PhysicalNet[] { sectorWires[x][y][p][0] },
+ 5) {
public void set(boolean connected) {
fpslic.cell(xc, yc-1).vwire(pc).drives(fpslic.cell(xc, yc).vwire(pc), connected);
}
};
- new PhysicalPip("xxx",
- sectorWires[x][y][p][0],
- new PhysicalNet[] { sectorWires[x][y-1][p][0] },
- 5) {
+ new PhysicalFpslicPip(x,
+ y,
+ -1 * (4-p) * PLANESEP,
+ -1 * (0+p) * PLANESEP,
+ "xxx",
+ sectorWires[x][y][p][0],
+ new PhysicalNet[] { sectorWires[x][y-1][p][0] },
+ 5) {
public void set(boolean connected) {
fpslic.cell(xc, yc).vwire(pc).drives(fpslic.cell(xc, yc-1).vwire(pc), connected);
}
return sectorWires[col][row][plane][horizontal ? 1 : 0];
}
+ public PhysicalCell randomCell(Random rand) {
+ int x = (Math.abs(rand.nextInt()) % width);
+ int y = (Math.abs(rand.nextInt()) % height);
+ return getCell(x, y);
+ }
+
public class PhysicalFpslicCell extends PhysicalCell {
+ private int x;
+ private int y;
private int col;
private int row;
private PhysicalNet outputNet;
private PhysicalNet yin;
private PhysicalNet[] local = new PhysicalNet[5];
+ public PhysicalCell randomCellWithin(Random rand, double percentOfDevice) {
+ int distance = (int)(percentOfDevice * Math.max(width, height));
+ if (distance < 4) distance = 4;
+ // FIXME ugly
+ while(true) {
+ int dx = (Math.abs(rand.nextInt()) % (distance*2+1));
+ int dy = (Math.abs(rand.nextInt()) % (distance*2+1));
+ PhysicalCell pc = getCell(col+dx-distance, row+dy-distance);
+ if (pc != null) return pc;
+ }
+ }
public void place(NetList.Node n) {
- int x = col;
- int y = row;
- n.x = x;
- n.y = y;
- n.physicalCell = this;
- Fpslic.Cell cell = fpslic.cell(x,y);
+ this.x = col;
+ this.y = row;
+ FpslicDevice.Cell cell = fpslic.cell(x,y);
cell.c(XLUT);
cell.b(false);
cell.f(false);
cell.xi(NW);
cell.yi(EAST);
+ //cell.xo(true);
+ //cell.yo(true);
String type = n.getType();
if (type.equals("and2")) cell.xlut(LUT_SELF & LUT_OTHER);
else if (type.equals("or2")) cell.xlut(LUT_SELF | LUT_OTHER);
else if (type.equals("cell0")) return;
}
- private Fpslic.Cell cell() { return fpslic.cell(col, row); }
+ public FpslicDevice.Cell cell() { return fpslic.cell(col, row); }
public PhysicalNet getNet(String name) {
if (name.equals("out")) return outputNet;
if (name.equals("xi")) return xin;
}
public void setFunction(String type) {
- Fpslic.Cell cell = cell();
+ FpslicDevice.Cell cell = cell();
cell.c(XLUT);
cell.xo(false);
cell.b(false);
public void link() {
// FIXME wow, this is a horrendous hack!
+
if (getCell(col-1, row+1) != null)
- new PhysicalPip(this+".xiNW", getCell(col-1, row+1).getNet("out"), new PhysicalNet[] { xin }, 5) {
+ new PhysicalFpslicPip(col, row, 0, 0,
+ this+".xiNW", getCell(col-1, row+1).getNet("out"), new PhysicalNet[] { xin }, 5) {
public void set(boolean connected) { cell().xi(connected ? NW : NONE); }
};
if (getCell(col-1, row-1) != null)
- new PhysicalPip(this+".xiSW", getCell(col-1, row-1).getNet("out"), new PhysicalNet[] { xin }, 5) {
+ new PhysicalFpslicPip(col, row, 0, 0,
+ this+".xiSW", getCell(col-1, row-1).getNet("out"), new PhysicalNet[] { xin }, 5) {
public void set(boolean connected) { cell().xi(connected ? SW : NONE); }
};
if (getCell(col+1, row+1) != null)
- new PhysicalPip(this+".xiNE", getCell(col+1, row+1).getNet("out"), new PhysicalNet[] { xin }, 5) {
+ new PhysicalFpslicPip(col, row, 0, 0,
+ this+".xiNE", getCell(col+1, row+1).getNet("out"), new PhysicalNet[] { xin }, 5) {
public void set(boolean connected) { cell().xi(connected ? NE : NONE); }
};
if (getCell(col+1, row-1) != null)
- new PhysicalPip(this+".xiSE", getCell(col+1, row-1).getNet("out"), new PhysicalNet[] { xin }, 5) {
+ new PhysicalFpslicPip(col, row, 0, 0,
+ this+".xiSE", getCell(col+1, row-1).getNet("out"), new PhysicalNet[] { xin }, 5) {
public void set(boolean connected) { cell().xi(connected ? SE : NONE); }
};
+
+ if (getCell(col-1, row) != null)
+ new PhysicalFpslicPip(col, row, 0, 0,
+ this+".yiW", getCell(col-1, row).getNet("out"), new PhysicalNet[] { yin }, 5) {
+ public void set(boolean connected) { cell().yi(connected ? WEST : NONE); }
+ };
+ if (getCell(col, row-1) != null)
+ new PhysicalFpslicPip(col, row, 0, 0,
+ this+".yiN", getCell(col, row-1).getNet("out"), new PhysicalNet[] { yin }, 5) {
+ public void set(boolean connected) { cell().yi(connected ? NORTH : NONE); }
+ };
+ if (getCell(col+1, row) != null)
+ new PhysicalFpslicPip(col, row, 0, 0,
+ this+".yiE", getCell(col+1, row).getNet("out"), new PhysicalNet[] { yin }, 5) {
+ public void set(boolean connected) { cell().yi(connected ? EAST : NONE); }
+ };
+ if (getCell(col, row+1) != null)
+ new PhysicalFpslicPip(col, row, 0, 0,
+ this+".yiS", getCell(col, row+1).getNet("out"), new PhysicalNet[] { yin }, 5) {
+ public void set(boolean connected) { cell().yi(connected ? SOUTH : NONE); }
+ };
+
}
private PhysicalFpslicCell(int col, int row) {
final int i = j;
local[i] = new PhysicalNet(this.toString()+".L"+i);
- new PhysicalPip(this+".h"+i, null, new PhysicalNet[] { local[i], getSectorWire(col, row, i, true) }) {
+ new PhysicalFpslicPip(col, row, -1 * (4-j) * PLANESEP, -1 * j * PLANESEP,
+ this+".h"+i, null, new PhysicalNet[] {
+ local[i], getSectorWire(col, row, i, true) }) {
public void set(boolean connected) { cell().h(i, connected); }
};
- new PhysicalPip(this+".v"+i, null, new PhysicalNet[] { local[i], getSectorWire(col, row, i, false) }) {
+ new PhysicalFpslicPip(col, row, -1 * (4-j) * PLANESEP, -1 * j * PLANESEP,
+ this+".v"+i, null, new PhysicalNet[] {
+ local[i], getSectorWire(col, row, i, false) }) {
public void set(boolean connected) { cell().v(i, connected); }
};
- new PhysicalPip(this+".xi"+i, local[i], new PhysicalNet[] { xin }) {
+ new PhysicalFpslicPip(col, row, -1 * (4-j) * PLANESEP + 15, -1 * j * PLANESEP + 15,
+ this+".xi"+i, local[i], new PhysicalNet[] { xin }) {
public void set(boolean connected) { cell().xi(connected ? i : NONE); }
};
- new PhysicalPip(this+".yi"+i, local[i], new PhysicalNet[] { yin }) {
+ new PhysicalFpslicPip(col, row, -1 * (4-j) * PLANESEP + 15, -1 * j * PLANESEP + 15,
+ this+".yi"+i, local[i], new PhysicalNet[] { yin }) {
public void set(boolean connected) { cell().yi(connected ? i : NONE); }
};
- new PhysicalPip(this+".o"+i, outputNet, new PhysicalNet[] { local[i] }) {
+ new PhysicalFpslicPip(col, row, -1 * (4-j) * PLANESEP + 15, -1 * j * PLANESEP + 15,
+ this+".o"+i, outputNet, new PhysicalNet[] { local[i] }) {
public void set(boolean connected) { cell().out(i, connected); }
};
}
public String toString() { return "cell@("+col+","+row+")"; }
}
+ public abstract class PhysicalFpslicPip extends PhysicalPip {
+ public PhysicalFpslicPip(int x, int y, int ox, int oy, String name, PhysicalNet driver, PhysicalNet[] driven, int q) {
+ this(x, y, ox, oy, name, driver, driven);
+ }
+ public PhysicalFpslicPip(int x, int y, int ox, int oy, String name, PhysicalNet driver, PhysicalNet[] driven) {
+ super(name, driver, driven);
+ this.x = x;
+ this.y = y;
+ this.ox = ox;
+ this.oy = oy;
+ }
+ private int ox;
+ private int oy;
+ private int x;
+ private int y;
+ public boolean prohibited() {
+ return Math.abs(x-badx) <= badr && Math.abs(y-bady) <= badr;
+ }
+ public int getX() {
+ return x * CELLSEP + ox;
+ }
+ public int getY() {
+ return ((height * CELLSEP) - (y * CELLSEP)) + oy;
+ }
+ public double getCost(PhysicalNet in, PhysicalNet out) {
+ if (prohibited()) return 100 * ((2*badr)-(Math.abs(badx-x) + Math.abs(bady-y)));
+ return defaultCost;
+ }
+ public double getDelay(PhysicalNet in, PhysicalNet out) {
+ if (prohibited()) return 10000 * defaultDelay;
+ return defaultDelay;
+ }
+ }
+
+ static int badx = 5;
+ static int bady = 5;
+ static int badr = 3;
}
\ No newline at end of file
--- /dev/null
+package edu.berkeley.slipway.mpar;
+import com.atmel.fpslic.*;
+import java.awt.*;
+import byucc.edif.tools.merge.*;
+import byucc.edif.*;
+import java.io.*;
+import java.util.*;
+import edu.berkeley.slipway.*;
+import edu.berkeley.abits.*;
+import com.atmel.fpslic.*;
+import static com.atmel.fpslic.FpslicConstants.*;
+import static edu.berkeley.slipway.mpar.PhysicalDevice.*;
+import static edu.berkeley.slipway.mpar.NetList.*;
+
+public class Placement {
+
+ public final NetList netlist;
+ public final PhysicalDevice pd;
+
+ public HashMap<PhysicalDevice.PhysicalCell, NetList.Node> cellToNode =
+ new HashMap<PhysicalDevice.PhysicalCell, NetList.Node>();
+ public HashMap<NetList.Node, PhysicalDevice.PhysicalCell> nodeToCell =
+ new HashMap<NetList.Node, PhysicalDevice.PhysicalCell>();
+
+ public Placement(NetList netlist, PhysicalDevice pd) {
+ this.netlist = netlist;
+ this.pd = pd;
+ }
+
+ public void unplace(PhysicalDevice.PhysicalCell pc) {
+ NetList.Node n = cellToNode.get(pc);
+ if (n != null) unplace(n);
+ }
+ public void unplace(NetList.Node n) {
+ PhysicalDevice.PhysicalCell pc = nodeToCell.get(n);
+ cellToNode.remove(pc);
+ nodeToCell.remove(n);
+ }
+ public void place(NetList.Node n, PhysicalDevice.PhysicalCell pc) {
+ if (n==null) return;
+ if (pc==null) return;
+ unplace(n);
+ unplace(pc);
+ cellToNode.put(pc, n);
+ nodeToCell.put(n, pc);
+ }
+
+ public void setPlacement() {
+ for(PhysicalDevice.PhysicalCell pc : cellToNode.keySet()) {
+ NetList.Node node = cellToNode.get(pc);
+ pc.place(node);
+ }
+ }
+
+ public boolean isPlaced(NetList.Node n) { return nodeToCell.get(n) != null; }
+ public boolean isPlaced(PhysicalDevice.PhysicalCell pc) { return cellToNode.get(pc) != null; }
+
+ public PhysicalDevice.PhysicalCell nodeToCell(NetList.Node n) { return nodeToCell.get(n); }
+ public NetList.Node cellToNode(PhysicalDevice.PhysicalCell pc) { return cellToNode.get(pc); }
+
+ public void random(Random rand) {
+ for(NetList.Node n : netlist.nodes) {
+ while(true) {
+ PhysicalDevice.PhysicalCell pc = pd.randomCell(rand);
+ if (isPlaced(pc)) continue;
+ place(n, pc);
+ break;
+ }
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package edu.berkeley.slipway.mpar;
+import com.atmel.fpslic.*;
+import java.awt.*;
+import byucc.edif.tools.merge.*;
+import byucc.edif.*;
+import java.io.*;
+import java.util.*;
+import edu.berkeley.slipway.*;
+import edu.berkeley.abits.*;
+import com.atmel.fpslic.*;
+import static com.atmel.fpslic.FpslicConstants.*;
+import static edu.berkeley.slipway.mpar.PhysicalDevice.*;
+import static edu.berkeley.slipway.mpar.NetList.*;
+
+
+// FIXME: make sure everything is O(design), not O(device)
+public class Routing {
+
+ public final Placement placement;
+ public final NetList netlist;
+ public final PhysicalDevice pd;
+
+ private HashSet<Route> removed = new HashSet<Route>();
+ private HashSet<Route> added = new HashSet<Route>();
+ public void checkpoint() {
+ removed.clear();
+ added.clear();
+ }
+ public void rollback() {
+ for (Route r : added) r.remove(false);
+ for (Route r : removed) r.add();
+ }
+
+ public Routing(Placement p) {
+ this.placement = p;
+ this.netlist = p.netlist;
+ this.pd = p.pd;
+ congestion = new double[pd.getNumPhysicalNets()];
+ load = new int[pd.getNumPhysicalNets()];
+ }
+
+ private double[] congestion;
+ private int[] load;
+ public HashMap<NetList.LogicalNet, Route> routes =
+ new HashMap<NetList.LogicalNet, Route>();
+
+ private class Route {
+ private NetList.LogicalNet logicalNet;
+ private HashSet<PhysicalDevice.PhysicalNet> nets;
+ private HashSet<PhysicalDevice.PhysicalPip> pips;
+ double timingpenalty;
+ public Route(NetList.LogicalNet logicalNet,
+ HashSet<PhysicalDevice.PhysicalNet> nets,
+ HashSet<PhysicalDevice.PhysicalPip> pips
+ ) {
+ this.logicalNet = logicalNet;
+ this.nets = nets;
+ this.pips = pips;
+ }
+ public void add() {
+ for(PhysicalDevice.PhysicalNet net : nets)
+ load[net.idx]++;
+ added.add(this);
+ routes.put(logicalNet, this);
+ }
+ public void remove() { remove(true); }
+ public void remove(boolean note) {
+ for(PhysicalDevice.PhysicalNet net : nets)
+ load[net.idx]--;
+ if (note) removed.add(this);
+ routes.remove(logicalNet);
+ }
+ }
+
+ public void setPips(boolean on) {
+ for (Route r : routes.values())
+ for (PhysicalDevice.PhysicalPip pip : r.pips)
+ pip.set(on);
+ }
+
+ public int getLoad(PhysicalDevice.PhysicalNet pn) { return load[pn.idx]; }
+ public double getCongestion(PhysicalDevice.PhysicalNet pn) { return congestion[pn.idx]; }
+
+ public void routeAll() throws RoutingFailedException {
+ for(NetList.LogicalNet net : netlist.nets)
+ route(net);
+ }
+ public void reRouteAll() throws RoutingFailedException {
+ for(NetList.LogicalNet net : netlist.nets) {
+ unroute(net);
+ route(net);
+ }
+ }
+ public void unRouteAll() {
+ for(NetList.LogicalNet signal : netlist.getLogicalNets())
+ unroute(signal);
+ }
+
+
+ public void unroute(NetList.Node node) {
+ if (node==null) return;
+ for(NetList.Node.Port p : node)
+ unroute(p.net);
+ }
+ /*
+ public void unroute(PhysicalDevice.PhysicalNet net) {
+ while(netToSignals.size(net) > 0)
+ unroute(netToSignals.getAll(net).iterator().next());
+ }
+ */
+ public void unroute(NetList.LogicalNet signal) {
+ if (signal==null) return;
+ Route r = routes.get(signal);
+ if (r != null) r.remove();
+ }
+
+ public void unrouteOverloaded() {
+ /*
+ FIXME
+ for(PhysicalDevice.PhysicalNet pn : pd)
+ if (getLoad(pn) > 1)
+ unroute(pn);
+ */
+ }
+
+ public void updateCongestion(double alphaParameter, double betaParameter) {
+ for(PhysicalDevice.PhysicalNet net : pd) {
+ double c = getCongestion(net);
+ c = c * alphaParameter;
+ if (getLoad(net) > 1) c += betaParameter;
+ congestion[net.idx] = c;
+ }
+ }
+
+ public static class RoutingFailedException extends Exception { }
+
+ public static int iteration = 1;
+
+ private HashSet<PhysicalDevice.PhysicalNet> remainingDests = new HashSet<PhysicalDevice.PhysicalNet>();
+ private PriorityQueue<PhysicalDevice.PhysicalNet> pq = new PriorityQueue<PhysicalDevice.PhysicalNet>();
+ public void route(NetList.LogicalNet logicalNet) throws RoutingFailedException {
+ double maxDelay = 10;
+ boolean tryHard = true;
+ double ts = 0;
+ if (logicalNet.driver == null) return;
+ if (logicalNet.getSize() <= 1) return;
+ if (isRouted(logicalNet)) return;
+
+ int remaining = 0;
+ for(NetList.Node.Port p : logicalNet.ports)
+ if (p != logicalNet.driver) {
+ PhysicalDevice.PhysicalNet dest;
+ switch(p.index) {
+ case 0: dest = placement.nodeToCell(p.getNode()).getNet("xi"); break;
+ case 1: dest = placement.nodeToCell(p.getNode()).getNet("yi"); break;
+ default: throw new Error();
+ }
+ dest.remaining = true;
+ remaining++;
+ }
+ iteration++;
+
+ PhysicalDevice.PhysicalNet source = placement.nodeToCell(logicalNet.driver.getNode()).getNet("out");
+ pq.clear();
+ source.distance = -1 * maxDelay;
+ source.depth = 0;
+ source.iteration = iteration;
+ pq.add(source);
+
+ HashSet<PhysicalDevice.PhysicalNet> nets = new HashSet<PhysicalDevice.PhysicalNet>();
+ HashSet<PhysicalDevice.PhysicalPip> pips = new HashSet<PhysicalDevice.PhysicalPip>();
+ OUTER: while(true) {
+ PhysicalDevice.PhysicalNet pn = pq.poll();
+ if (pn==null) throw new RoutingFailedException();
+ double frontier = pn.distance;
+ for(PhysicalDevice.PhysicalPip pip : pn) {
+ for(PhysicalDevice.PhysicalNet net : pip.getDrivenNets()) {
+ if (net.iteration != iteration) {
+ net.iteration = iteration;
+ net.distance = Double.MAX_VALUE;
+ }
+ double newfrontier = frontier + pip.getCost(pn, net);
+ newfrontier += getCongestion(net);
+ if (getLoad(net) > 0) newfrontier += 1000;
+
+ // penalty for using any net already routed in this iteration (makes routing order-sensitive)
+ //if (net.load >= 1) newfrontier = newfrontier + 20;
+
+ if (net.distance <= newfrontier) continue;
+ net.distance = newfrontier;
+ pq.add(net);
+ net.backpointer = pn;
+ net.depth = pn.depth+1;
+
+ if (!net.remaining) continue;
+ remaining--;
+ net.remaining = false;
+ // Vaughn Betz style multiterminal routing: once we reach one sink, make every node on the path
+ // "distance zero" from the source.
+ nets.add(source);
+ if (newfrontier > 0) ts += newfrontier;
+ for(PhysicalDevice.PhysicalNet p = net; p != source; p = p.backpointer) {
+ PhysicalDevice.PhysicalPip pipx = p.getPipFrom(p.backpointer); // FIXME: this call is actually slow
+ pips.add(pipx);
+ if (pipx.driver != null) nets.add(pipx.driver);
+ for(PhysicalDevice.PhysicalNet n : pipx.driven) nets.add(n);
+ p.distance = source.distance;
+ pq.add(p);
+ nets.add(p);
+ }
+ if (remaining==0) break OUTER;
+ }
+ }
+ }
+ Route r = new Route(logicalNet, nets, pips);
+ r.add();
+ r.timingpenalty = ts;
+ }
+
+
+ public boolean isRouted(NetList.LogicalNet n) { return routes.get(n) != null; }
+ //public boolean isRouted(PhysicalDevice.PhysicalNet pn) { return netToSignal.get(pn) != null; }
+ //public PhysicalDevice.PhysicalNet signalToNet(NetList.LogicalNet n) { return signalToNets.get(n); }
+ //public NetList.LogicalNet netToSignal(PhysicalDevice.PhysicalNet pn) { return netToSignals.get(pn); }
+
+ public double measureCongestion() {
+ double congestion = 0;
+ for(PhysicalDevice.PhysicalNet pn : pd)
+ if (getLoad(pn) > 1)
+ congestion += getLoad(pn)-1;
+ for(NetList.LogicalNet ln : netlist.nets)
+ if (!isRouted(ln))
+ congestion = Double.MAX_VALUE;
+ return congestion;
+ }
+
+ public double measureWireCost() {
+ double cong = 0;
+ for(PhysicalDevice.PhysicalNet pn : pd)
+ cong += getLoad(pn);
+ return cong;
+ }
+
+ public double measureTimingpenalty() {
+ double ret = 0;
+ for(Route r : routes.values())
+ ret += r.timingpenalty;
+ return ret;
+ }
+
+ public int measureOverloaded() {
+ int ret = 0;
+ for(PhysicalDevice.PhysicalNet pn : pd)
+ if (getLoad(pn) > 1)
+ ret++;
+ return ret;
+ }
+
+ public double measureWireUtilization() {
+ int numwires = 0;
+ int used = 0;
+ for(PhysicalDevice.PhysicalNet pn : pd) {
+ numwires++;
+ used += getLoad(pn);
+ }
+ return ((double)used)/((double)numwires);
+ }
+
+ public void draw(Graphics2D g) {
+ for(NetList.LogicalNet signal : netlist.nets)
+ draw(g, signal);
+ }
+ public void draw(Graphics2D g, NetList.LogicalNet signal) {
+ g.setColor(/*getLoad(pip1.driver) >= 2 ? Color.red :*/ Color.blue);
+ for(Route r : routes.values()) {
+ for(PhysicalDevice.PhysicalNet net : r.nets) {
+ for(PhysicalDevice.PhysicalPip pip1 : net) {
+ if (!r.pips.contains(pip1)) continue;
+ for(PhysicalDevice.PhysicalPip pip2 : net) {
+ if (!r.pips.contains(pip2)) continue;
+
+ g.drawLine(pip1.getX(),
+ pip1.getY(),
+ pip2.getX(),
+ pip2.getY());
+
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+package edu.berkeley.slipway.mpar;
+import com.atmel.fpslic.*;
+import java.awt.*;
+import java.awt.event.*;
+import byucc.edif.tools.merge.*;
+import byucc.edif.*;
+import java.io.*;
+import java.util.*;
+import edu.berkeley.slipway.*;
+import edu.berkeley.abits.*;
+import com.atmel.fpslic.*;
+import static com.atmel.fpslic.FpslicConstants.*;
+import static edu.berkeley.slipway.mpar.PhysicalFpslic.*;
+
+public class Visualization extends Frame implements MouseMotionListener, MouseListener {
+ public void mouseEntered(MouseEvent e) { }
+ public void mouseExited(MouseEvent e) { }
+ public void mousePressed(MouseEvent e){ }
+ public void mouseReleased(MouseEvent e) { }
+ public void mouseDragged(MouseEvent e) { }
+ public void mouseClicked(MouseEvent e) {
+ MPARDemo.temperature += 0.05;
+ }
+ public void mouseMoved(MouseEvent e) {
+ PhysicalFpslic.badx = (e.getX() / CELLSEP)-1;
+ PhysicalFpslic.bady = (getHeight()-e.getY()) / CELLSEP;
+ }
+
+ public static final Color MOVED = new Color(0x88, 0x88, 0x88);
+ public static final Color PLAIN = new Color(0xff, 0x88, 0x88);
+ public static final Color EMPTY = new Color(0x88, 0xff, 0x88);
+
+ private final PhysicalFpslic pd;
+
+ public Visualization(PhysicalFpslic pd) {
+ this.pd = pd;
+ setSize(CELLSEP*(pd.width+2), CELLSEP*(pd.height+2));
+ show();
+ setSize(CELLSEP*(pd.width+2), CELLSEP*(pd.height+2));
+ addMouseListener(this);
+ addMouseMotionListener(this);
+ }
+
+ public void draw(Placement placement, Routing routing, boolean drawRouting) {
+ Graphics2D g = (Graphics2D)getGraphics();
+ g.translate(CELLSEP,CELLSEP);
+ g.setColor(Color.white);
+ g.fillRect(-CELLSEP, -CELLSEP, getWidth(), getHeight());
+ g.setColor(Color.black);
+ g.drawString("temperature = " + MPARDemo.temperature, 10, 0);
+ g.drawString("congestion = " + MPARDemo.congestion, 10, 15);
+ g.drawString("slack = " + (-1 * MPARDemo.timingpenalty), 10, 30);
+ for(int x=0; x<pd.width; x++)
+ for(int y=0; y<pd.height; y++) {
+ double d = Math.sqrt( (PhysicalFpslic.badx-x)*
+ (PhysicalFpslic.badx-x)+
+ (PhysicalFpslic.bady-y)*
+ (PhysicalFpslic.bady-y) );
+ d = (PhysicalFpslic.badr - d);
+ if (d<0) d = 0;
+ d /= PhysicalFpslic.badr;
+ int a = 255 - ((int)(255*d));
+ g.setColor(new Color(a, a, a));
+ g.fillRect(( x*CELLSEP - (PLANESEP*3)),
+ ((pd.height * CELLSEP) - (y*CELLSEP + (PLANESEP*3))),
+ CELLSEP,
+ CELLSEP);
+ }
+ if (drawRouting) {
+ routing.draw(g);
+ }
+ for(int x=0; x<pd.width; x++)
+ for(int y=0; y<pd.height; y++) {
+ if (placement.cellToNode(pd.getCell(x,y)) != null)
+ g.setColor(PLAIN);
+ else
+ g.setColor(EMPTY);
+ g.fillRect(( x*CELLSEP)+2,
+ ((pd.height * CELLSEP) - (y*CELLSEP))+2,
+ CELLSEP-5*PLANESEP-2,
+ CELLSEP-5*PLANESEP-2);
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package edu.berkeley.slipway.util;
+
+import java.io.*;
+import java.util.*;
+import java.awt.*;
+import com.atmel.fpslic.*;
+import edu.berkeley.slipway.*;
+import edu.berkeley.slipway.gui.*;
+import static com.atmel.fpslic.FpslicConstants.*;
+
+/** useful test structures */
+public class ExperimentUtils {
+
+ /**
+ * Creates a 2x2 cell frequency divider with top left corner at
+ * c, taking input from c.north() and providing output on the
+ * orthogonal axis at c.south(). Returns c.south().south() for
+ * easy daisy-chaining.
+ */
+ public static FpslicDevice.Cell divider(FpslicDevice.Cell c) {
+ FpslicDevice.Cell detect1 = c;
+ FpslicDevice.Cell detect2 = c.east();
+
+ detect1.yi(NORTH);
+ detect1.ylut(LUT_SELF);
+ detect1.xlut(LUT_OTHER & (~LUT_Z));
+ detect1.c(YLUT);
+ detect1.t(TMUX_FB);
+ detect1.f(false);
+ detect1.b(false);
+
+ detect2.xi(NW);
+ detect2.ylut(LUT_OTHER);
+ detect2.xlut((~LUT_SELF) & LUT_Z);
+ detect2.c(YLUT);
+ detect2.t(TMUX_FB);
+ detect2.f(false);
+ detect2.b(false);
+
+ detect1.south().yi(EAST);
+ detect1.south().xi(NE);
+ detect1.south().c(YLUT);
+ detect1.south().t(TMUX_FB);
+ detect1.south().f(false);
+ detect1.south().b(false);
+ detect1.south().ylut( (LUT_OTHER & (~LUT_SELF)) |
+ ((~LUT_OTHER) & LUT_Z)
+ );
+ detect1.south().xlut( (LUT_SELF & (~LUT_OTHER)) |
+ ((~LUT_SELF) & LUT_Z)
+ );
+
+ detect2.south().yi(WEST);
+ detect2.south().xi(NW);
+ detect2.south().c(YLUT);
+ detect2.south().t(TMUX_FB);
+ detect2.south().f(false);
+ detect2.south().b(false);
+ detect2.south().ylut( (LUT_OTHER & (LUT_SELF)) |
+ ((~LUT_OTHER) & LUT_Z)
+ );
+ detect2.south().xlut( (LUT_SELF & (~LUT_OTHER)) |
+ ((~LUT_SELF) & LUT_Z)
+ );
+
+ if (c.south().south()==null) return null;
+ if (c.south().south().south()==null) return null;
+ return c.south().south();
+ }
+
+ /** set up the scan cell */
+ public static void setupScanCell(FpslicDevice fpslic) {
+ fpslic.cell(23,15).h(3, true);
+ fpslic.cell(23,15).yi(L3);
+ fpslic.cell(23,15).ylut(0xAA);
+ fpslic.iob_right(15, true).enableOutput(WEST);
+
+ fpslic.cell(23,0).ylut(0x00);
+ fpslic.iob_right(0, true).enableOutput(WEST);
+ fpslic.flush();
+ }
+
+}
\ No newline at end of file