added minor support for global wires
[slipway.git] / src / com / atmel / fpslic / Fpslic.java
index fa7dc5d..6709138 100644 (file)
@@ -60,12 +60,19 @@ public abstract class Fpslic {
         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 SectorWire(boolean horizontal, int plane, int col, int row, boolean global) {
             this.horizontal=horizontal;
-            this.global = false;
+            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++)
@@ -77,8 +84,8 @@ public abstract class Fpslic {
         private int z(int z)       { return (horizontal ? 0x30 : 0x20) | z; }
         public int code(boolean topleft) {
             switch(plane) {
-                case 0: return z(6)+(topleft?0:1);
-                case 1: return z(8)+(topleft?0:1);
+                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);
@@ -116,11 +123,24 @@ public abstract class Fpslic {
             throw new Error("not implemented");
         }
 
+        public void dork() {
+            mode4zyx(switchbox(north()), (1<<6), (1<<6));
+        }
+
         public void drives(SectorWire w, boolean enable) {
-            mode4zyx(switchbox(w), enable?0x02:0x00, 0x07);
+            // 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;
         }
@@ -171,11 +191,21 @@ public abstract class Fpslic {
         public final int col;
         public final int row;
 
+        public String toString() { return "cell@("+col+","+row+")"; }
+
         public Cell(int col, int row) {
             this.row = row;
             this.col = col;
         }
         
+        public Fpslic fpslic() { return Fpslic.this; }
+        public int hashCode() { return col ^ row ^ Fpslic.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); }
@@ -256,8 +286,8 @@ public abstract class Fpslic {
 
         public void h(int plane, boolean enable) {
             switch(plane) {
-                case 0: mode4(0x08, row, col, 2, enable); return;
-                case 1: mode4(0x08, row, col, 0, enable); return;
+                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;
@@ -267,8 +297,8 @@ public abstract class Fpslic {
         
         public boolean hx(int plane) {
             switch(plane) {
-                case 0: return (mode4(0x08, row, col) & (1<<2)) != 0;
-                case 1: return (mode4(0x08, row, col) & (1<<0)) != 0;
+                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;
@@ -309,14 +339,11 @@ public abstract class Fpslic {
         }
 
         public int t() {
-            System.err.println("found " + (mode4(1, row, col) & 0x34));
-            switch(mode4(1, row, col) & 0x34) {
-                case 0x20: return TMUX_Z;
-                case 0x24: return TMUX_W_AND_Z;
-                case 0x34: return TMUX_FB;
-                case 0x14: return TMUX_W_AND_FB;
+            switch(mode4(1, row, col) & 0x30) {
                 case 0x00: return TMUX_W;
-                    //default: throw new RuntimeException("unknown!");
+                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; 
             }
         }
@@ -324,15 +351,14 @@ public abstract class Fpslic {
         public void t(int code) {
             int result = 0;
             switch(code) {
-                case TMUX_Z:        result = 0x20; break; // TOTALLYBOGUS throw new Error("not implemented, but should be possible");
-                case TMUX_W_AND_Z:  result = 0x24; break;
-                case TMUX_FB:       result = 0x34; break; /* I think this is actually W_AND_FB, sadly */
-                case TMUX_W_AND_FB: result = 0x14; break;
                 case TMUX_W:        result = 0x00; break;
-                    //default: throw new RuntimeException("unknown code! " + code);
+                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, 0x34);
+            mode4(1, row, col, result, 0x30);
         }
         /*
         private void fmux(int source) {
@@ -469,11 +495,13 @@ public abstract class Fpslic {
                 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 L4: mode4(0x03, row, col, 4, true);  mode4(0x05, row, col,    0); break;
-                case L3: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 1<<0); break;
-                case L2: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 1<<1); break;
-                case L1: mode4(0x03, row, col, 4, false); mode4(0x05, row, col, 1<<2); 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");
             }
@@ -495,7 +523,7 @@ public abstract class Fpslic {
         public int yi() {
             if ((mode4(0x02, row, col) & (1<<6))!=0) return L4;
             switch(mode4(0x04, row, col) & 0xff) {
-                case 0x80: return NORTH;
+                case (1<<7): return NORTH;
                 case (1<<5): return SOUTH;
                 case (1<<6): return WEST;
                 case (1<<4): return EAST;
@@ -587,7 +615,7 @@ public abstract class Fpslic {
         }
 
         public int zi() {
-            switch(mode4(0x02, row, col) & 0xDB) {
+            switch(mode4(0x02, row, col) & 0x9B) {
                 case (1<<7): return L4;
                 case (1<<5): return L3;
                 case (1<<4): return L2;
@@ -596,20 +624,72 @@ public abstract class Fpslic {
                 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) & 0xDB));
-            }
+                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 /*&& ne().xi_relevant()*/;
-                case NW: return nw() != null && nw().xi()==SE /*&& nw().xi_relevant()*/;
-                case SE: return se() != null && se().xi()==NW /*&& se().xi_relevant()*/;
-                case SW: return sw() != null && sw().xi()==NE /*&& sw().xi_relevant()*/;
+                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;
             }
         }
@@ -667,13 +747,19 @@ public abstract class Fpslic {
             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()) {
@@ -683,6 +769,8 @@ public abstract class Fpslic {
                 case 0x30: return true;
             }
             return false;
+            */
+            return true;
         }