From 5301afc9e47f0dd6f96858d1c70407e0df5b53cf Mon Sep 17 00:00:00 2001 From: megacz Date: Wed, 31 Dec 2008 22:25:24 -0800 Subject: [PATCH] updates that were lying around but never got checked in; includes reorg of gui --- Makefile | 26 +- src/com/atmel/fpslic/FpslicBoard.java | 139 +++ src/com/atmel/fpslic/FpslicDevice.java | 966 +++++++++++++++++ src/edu/berkeley/abits/Board.java | 30 + src/edu/berkeley/abits/Device.java | 8 + src/edu/berkeley/slipway/SlipwayBoard.java | 324 ++++++ src/edu/berkeley/slipway/SlipwaySlave.c | 282 +++++ src/edu/berkeley/slipway/demos/Demo.java | 1096 ++++++++++++++++++++ src/edu/berkeley/slipway/demos/Demo2.java | 254 +++++ .../demos/FastestMicropipelineFifoDemo.java | 354 +++++++ .../slipway/demos/MicropipelineFifoDemo.java | 183 ++++ src/edu/berkeley/slipway/gui/G.java | 1 - src/edu/berkeley/slipway/gui/Gui.java | 95 +- src/edu/berkeley/slipway/gui/Gui2.java | 19 +- src/edu/berkeley/slipway/gui/Gui3.java | 17 +- src/edu/berkeley/slipway/gui/GuiCell.java | 4 +- src/edu/berkeley/slipway/gui/GuiConstants.java | 1 - src/edu/berkeley/slipway/gui/Inspector.java | 96 ++ src/edu/berkeley/slipway/gui/P.java | 1 - src/edu/berkeley/slipway/gui/ZoomingPanel.java | 9 +- src/edu/berkeley/slipway/gui/ZoomingPanel2.java | 3 +- src/edu/berkeley/slipway/mpar/HashMapBag.java | 62 ++ src/edu/berkeley/slipway/mpar/MPARDemo.java | 302 +++--- src/edu/berkeley/slipway/mpar/MapBag.java | 11 + src/edu/berkeley/slipway/mpar/NetList.java | 80 +- src/edu/berkeley/slipway/mpar/PhysicalDevice.java | 119 +-- src/edu/berkeley/slipway/mpar/PhysicalFpslic.java | 184 +++- src/edu/berkeley/slipway/mpar/Placement.java | 72 ++ src/edu/berkeley/slipway/mpar/Routing.java | 292 ++++++ src/edu/berkeley/slipway/mpar/Visualization.java | 85 ++ src/edu/berkeley/slipway/util/ExperimentUtils.java | 83 ++ 31 files changed, 4776 insertions(+), 422 deletions(-) create mode 100644 src/com/atmel/fpslic/FpslicBoard.java create mode 100644 src/com/atmel/fpslic/FpslicDevice.java create mode 100644 src/edu/berkeley/abits/Board.java create mode 100644 src/edu/berkeley/abits/Device.java create mode 100644 src/edu/berkeley/slipway/SlipwayBoard.java create mode 100644 src/edu/berkeley/slipway/SlipwaySlave.c create mode 100644 src/edu/berkeley/slipway/demos/Demo.java create mode 100644 src/edu/berkeley/slipway/demos/Demo2.java create mode 100644 src/edu/berkeley/slipway/demos/FastestMicropipelineFifoDemo.java create mode 100644 src/edu/berkeley/slipway/demos/MicropipelineFifoDemo.java create mode 100644 src/edu/berkeley/slipway/gui/Inspector.java create mode 100644 src/edu/berkeley/slipway/gui/Keyboard.java create mode 100644 src/edu/berkeley/slipway/mpar/HashMapBag.java create mode 100644 src/edu/berkeley/slipway/mpar/MapBag.java create mode 100644 src/edu/berkeley/slipway/mpar/Placement.java create mode 100644 src/edu/berkeley/slipway/mpar/Routing.java create mode 100644 src/edu/berkeley/slipway/mpar/Visualization.java create mode 100644 src/edu/berkeley/slipway/util/ExperimentUtils.java diff --git a/Makefile b/Makefile index 8245190..615e63b 100644 --- a/Makefile +++ b/Makefile @@ -6,13 +6,23 @@ linkerflags = 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 $@` @@ -56,7 +66,7 @@ javac = javac -cp upstream/jhdl-edifparser.jar ## 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 $@ @@ -115,10 +125,6 @@ upstream/avr-libc/.built: upstream/avr-libc upstream/gcc/.built 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 ########################################################################## diff --git a/src/com/atmel/fpslic/FpslicBoard.java b/src/com/atmel/fpslic/FpslicBoard.java new file mode 100644 index 0000000..4016b60 --- /dev/null +++ b/src/com/atmel/fpslic/FpslicBoard.java @@ -0,0 +1,139 @@ +package com.atmel.fpslic; + +import edu.berkeley.abits.*; +import java.io.*; + +/** + * Implementation of Board 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<=0; i--) { + boolean bit = (bits & (1<>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 w 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 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(); + } + +} diff --git a/src/edu/berkeley/abits/Board.java b/src/edu/berkeley/abits/Board.java new file mode 100644 index 0000000..318b095 --- /dev/null +++ b/src/edu/berkeley/abits/Board.java @@ -0,0 +1,30 @@ +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); + } +} diff --git a/src/edu/berkeley/abits/Device.java b/src/edu/berkeley/abits/Device.java new file mode 100644 index 0000000..7bf6639 --- /dev/null +++ b/src/edu/berkeley/abits/Device.java @@ -0,0 +1,8 @@ +package edu.berkeley.abits; + +public interface Device { + + public int getWidth(); + public int getHeight(); + +} diff --git a/src/edu/berkeley/slipway/SlipwayBoard.java b/src/edu/berkeley/slipway/SlipwayBoard.java new file mode 100644 index 0000000..2c30035 --- /dev/null +++ b/src/edu/berkeley/slipway/SlipwayBoard.java @@ -0,0 +1,324 @@ +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 SlipwaySlave.c) + */ +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 getDevice() */ + 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 readInterruptCount() */ + 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); + } +} + diff --git a/src/edu/berkeley/slipway/SlipwaySlave.c b/src/edu/berkeley/slipway/SlipwaySlave.c new file mode 100644 index 0000000..163e717 --- /dev/null +++ b/src/edu/berkeley/slipway/SlipwaySlave.c @@ -0,0 +1,282 @@ +// +// 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 +#include +#include +#include + +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 (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<> 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<> 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; + +} + diff --git a/src/edu/berkeley/slipway/demos/Demo.java b/src/edu/berkeley/slipway/demos/Demo.java new file mode 100644 index 0000000..08f9ca6 --- /dev/null +++ b/src/edu/berkeley/slipway/demos/Demo.java @@ -0,0 +1,1096 @@ +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; ii) 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<> 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=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); + } +} diff --git a/src/edu/berkeley/slipway/demos/Demo2.java b/src/edu/berkeley/slipway/demos/Demo2.java new file mode 100644 index 0000000..56c07b3 --- /dev/null +++ b/src/edu/berkeley/slipway/demos/Demo2.java @@ -0,0 +1,254 @@ +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 (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(); + } + } +} diff --git a/src/edu/berkeley/slipway/demos/FastestMicropipelineFifoDemo.java b/src/edu/berkeley/slipway/demos/FastestMicropipelineFifoDemo.java new file mode 100644 index 0000000..509160d --- /dev/null +++ b/src/edu/berkeley/slipway/demos/FastestMicropipelineFifoDemo.java @@ -0,0 +1,354 @@ +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 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; + } + + + +} diff --git a/src/edu/berkeley/slipway/demos/MicropipelineFifoDemo.java b/src/edu/berkeley/slipway/demos/MicropipelineFifoDemo.java new file mode 100644 index 0000000..22d7c40 --- /dev/null +++ b/src/edu/berkeley/slipway/demos/MicropipelineFifoDemo.java @@ -0,0 +1,183 @@ +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; i0) + 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 (12 & ~0x3) && sw.north()!=null && sw.north().drives(sw)) @@ -928,7 +927,7 @@ public class Gui extends ZoomingPanel implements KeyListener, MouseMotionListene 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) { diff --git a/src/edu/berkeley/slipway/gui/Gui2.java b/src/edu/berkeley/slipway/gui/Gui2.java index efc5957..813c24e 100644 --- a/src/edu/berkeley/slipway/gui/Gui2.java +++ b/src/edu/berkeley/slipway/gui/Gui2.java @@ -3,7 +3,6 @@ package edu.berkeley.slipway.gui; 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.*; @@ -20,8 +19,8 @@ public class Gui2 extends ZoomingPanel2 implements KeyListener, MouseMotionListe Graphics2D g; G gg; - Fpslic at40k; - FtdiBoard drone; + FpslicDevice at40k; + SlipwayBoard drone; private Cell[][] ca = new Cell[128][]; @@ -29,11 +28,11 @@ public class Gui2 extends ZoomingPanel2 implements KeyListener, MouseMotionListe 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 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 diff --git a/src/edu/berkeley/slipway/gui/Keyboard.java b/src/edu/berkeley/slipway/gui/Keyboard.java new file mode 100644 index 0000000..e69de29 diff --git a/src/edu/berkeley/slipway/gui/P.java b/src/edu/berkeley/slipway/gui/P.java index 90ec157..338b913 100644 --- a/src/edu/berkeley/slipway/gui/P.java +++ b/src/edu/berkeley/slipway/gui/P.java @@ -1,7 +1,6 @@ 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.*; diff --git a/src/edu/berkeley/slipway/gui/ZoomingPanel.java b/src/edu/berkeley/slipway/gui/ZoomingPanel.java index fc51932..14e73c0 100644 --- a/src/edu/berkeley/slipway/gui/ZoomingPanel.java +++ b/src/edu/berkeley/slipway/gui/ZoomingPanel.java @@ -2,7 +2,6 @@ package edu.berkeley.slipway.gui; 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.*; @@ -27,9 +26,9 @@ public abstract class ZoomingPanel extends JComponent implements KeyListener, Mo 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); @@ -111,7 +110,7 @@ public abstract class ZoomingPanel extends JComponent implements KeyListener, Mo } } 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: @@ -243,7 +242,7 @@ public abstract class ZoomingPanel extends JComponent implements KeyListener, Mo return; } case VK_I: { - System.out.println("interrupt count => " + ftdiboard.readCount()); + System.out.println("interrupt count => " + ftdiboard.readInterruptCount()); repaint(); return; } diff --git a/src/edu/berkeley/slipway/gui/ZoomingPanel2.java b/src/edu/berkeley/slipway/gui/ZoomingPanel2.java index ee7cb97..a3dddc2 100644 --- a/src/edu/berkeley/slipway/gui/ZoomingPanel2.java +++ b/src/edu/berkeley/slipway/gui/ZoomingPanel2.java @@ -2,7 +2,6 @@ package edu.berkeley.slipway.gui; 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.*; @@ -118,7 +117,7 @@ public abstract class ZoomingPanel2 extends JComponent implements KeyListener, M } } 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: { diff --git a/src/edu/berkeley/slipway/mpar/HashMapBag.java b/src/edu/berkeley/slipway/mpar/HashMapBag.java new file mode 100644 index 0000000..90eb4f2 --- /dev/null +++ b/src/edu/berkeley/slipway/mpar/HashMapBag.java @@ -0,0 +1,62 @@ +// 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 K to sets of values of type T */ +public final class HashMapBag implements MapBag { + + private final HashMap> hm = new HashMap>(); + + public void add(K k, V v) { + HashSet hs = hm.get(k); + if (hs==null) hm.put(k, hs = new HashSet()); + size -= hs.size(); + hs.add(v); + size += hs.size(); + } + + public void addAll(K k, Iterable iv) { + for(V v : iv) add(k, v); + } + + public int size(K k) { + HashSet ret = hm.get(k); + return ret==null ? 0 : ret.size(); + } + public HashSet getAll(K k) { + HashSet ret = hm.get(k); + if (ret==null) return new HashSet(); + return ret; + } + + public void remove(K k, V v) { + if (hm.get(k)==null) return; + HashSet hs = hm.get(k); + if (hs==null) return; + size -= hs.size(); + hs.remove(v); + size += hs.size(); + } + + public void removeAll(K k, Iterable 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 hmb) { + for(K k : hmb) addAll(k, hmb.getAll(k)); + } + public void removeAll(HashMapBag hmb) { + for(K k : hmb) removeAll(k, hmb.getAll(k)); + } + + public Iterator iterator() { return hm.keySet().iterator(); } + public int size() { return size; } + private int size = 0; +} diff --git a/src/edu/berkeley/slipway/mpar/MPARDemo.java b/src/edu/berkeley/slipway/mpar/MPARDemo.java index 7c19aed..6eb1bd6 100644 --- a/src/edu/berkeley/slipway/mpar/MPARDemo.java +++ b/src/edu/berkeley/slipway/mpar/MPARDemo.java @@ -1,12 +1,15 @@ 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 @@ -27,145 +30,134 @@ import static com.atmel.fpslic.FpslicConstants.*; 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 it = (Iterator)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 needUnroute = new HashSet(); - 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 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 (12 & ~0x3) && sw.north()!=null && sw.north().drives(sw)) @@ -266,30 +262,30 @@ public class MPARDemo { } - 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); } } diff --git a/src/edu/berkeley/slipway/mpar/MapBag.java b/src/edu/berkeley/slipway/mpar/MapBag.java new file mode 100644 index 0000000..bb63c5a --- /dev/null +++ b/src/edu/berkeley/slipway/mpar/MapBag.java @@ -0,0 +1,11 @@ +// 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 K to sets of values of type V */ +public interface MapBag extends Iterable { + public void add(K k, V v); + public void addAll(K k, Iterable iv); + public Iterator iterator(); +} diff --git a/src/edu/berkeley/slipway/mpar/NetList.java b/src/edu/berkeley/slipway/mpar/NetList.java index 50f59b5..60e2d9b 100644 --- a/src/edu/berkeley/slipway/mpar/NetList.java +++ b/src/edu/berkeley/slipway/mpar/NetList.java @@ -4,31 +4,45 @@ import byucc.edif.tools.merge.*; 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 { + + 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 it = (Iterator)env.getTopCell().cellInstanceIterator(); + it.hasNext(); + ) { + createNode(it.next(), null); + } + } private HashMap ids = new HashMap(); - public HashSet nodes = new HashSet(); + public HashSet nodes = new HashSet(); + public ArrayList nodes_ = new ArrayList(); + public HashSet nets = new HashSet(); + public Iterable 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 { private final String type; private final int id; - public int x = -1; - public int y = -1; - private HashMap ports = new HashMap(); + public Iterator 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(); @@ -36,9 +50,7 @@ public class NetList { } 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); @@ -46,10 +58,7 @@ public class NetList { 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; @@ -76,46 +85,13 @@ public class NetList { /** a Net is a collection of ports which are wired together */ public class LogicalNet implements Iterable { - private Node.Port driver = null; - private HashSet ports = new HashSet(); - private HashSet pips = new HashSet(); - private HashSet pns = new HashSet(); - - 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 ports = new HashSet(); public LogicalNet() { nets.add(this); } public Iterator 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 iterator() { return nodes.iterator(); } } diff --git a/src/edu/berkeley/slipway/mpar/PhysicalDevice.java b/src/edu/berkeley/slipway/mpar/PhysicalDevice.java index 70397e7..e611e7a 100644 --- a/src/edu/berkeley/slipway/mpar/PhysicalDevice.java +++ b/src/edu/berkeley/slipway/mpar/PhysicalDevice.java @@ -9,6 +9,7 @@ import static edu.berkeley.slipway.mpar.MPARDemo.*; public abstract class PhysicalDevice implements Iterable { public abstract PhysicalCell getCell(int col, int row); + public abstract PhysicalCell randomCell(Random rand); private HashSet allPhysicalNets = new HashSet(); public Iterator iterator() { return allPhysicalNets.iterator(); } @@ -17,54 +18,35 @@ public abstract class PhysicalDevice implements Iterable, Comparable { - // 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 pips = new HashSet(); + public final HashSet pips = new HashSet(); private String name; - // logical nets currently mapped onto this physical net - private HashSet logicalNets = new HashSet(); - - public double getCongestion() { return congestion; } - public boolean isCongested() { return load >= 2; } - public void updateCongestion() { - congestion = congestion * alphaParameter; - if (isCongested()) congestion += betaParameter; - } - - public Iterable 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; } @@ -83,79 +65,28 @@ public abstract class PhysicalDevice implements Iterable remainingDests = new HashSet(); - for(PhysicalNet dest : dests) remainingDests.add(dest); - - HashSet needsReset = new HashSet(); - PriorityQueue pq = new PriorityQueue(); - 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); } diff --git a/src/edu/berkeley/slipway/mpar/PhysicalFpslic.java b/src/edu/berkeley/slipway/mpar/PhysicalFpslic.java index 748145f..e524c64 100644 --- a/src/edu/berkeley/slipway/mpar/PhysicalFpslic.java +++ b/src/edu/berkeley/slipway/mpar/PhysicalFpslic.java @@ -10,7 +10,10 @@ import static com.atmel.fpslic.FpslicConstants.*; 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; @@ -25,7 +28,7 @@ public class PhysicalFpslic extends PhysicalDevice { 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; @@ -36,12 +39,14 @@ public class PhysicalFpslic extends PhysicalDevice { for(int xc=x; xc cellToNode = + new HashMap(); + public HashMap nodeToCell = + new HashMap(); + + 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 diff --git a/src/edu/berkeley/slipway/mpar/Routing.java b/src/edu/berkeley/slipway/mpar/Routing.java new file mode 100644 index 0000000..f86f912 --- /dev/null +++ b/src/edu/berkeley/slipway/mpar/Routing.java @@ -0,0 +1,292 @@ +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 removed = new HashSet(); + private HashSet added = new HashSet(); + 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 routes = + new HashMap(); + + private class Route { + private NetList.LogicalNet logicalNet; + private HashSet nets; + private HashSet pips; + double timingpenalty; + public Route(NetList.LogicalNet logicalNet, + HashSet nets, + HashSet 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 remainingDests = new HashSet(); + private PriorityQueue pq = new PriorityQueue(); + 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 nets = new HashSet(); + HashSet pips = new HashSet(); + 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 diff --git a/src/edu/berkeley/slipway/mpar/Visualization.java b/src/edu/berkeley/slipway/mpar/Visualization.java new file mode 100644 index 0000000..a6e8a64 --- /dev/null +++ b/src/edu/berkeley/slipway/mpar/Visualization.java @@ -0,0 +1,85 @@ +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