major cleanup of mpar code
[slipway.git] / src / edu / berkeley / slipway / mpar / PhysicalDevice.java
index 8d8b9ed..70397e7 100644 (file)
 package edu.berkeley.slipway.mpar;
-import com.atmel.fpslic.*;
 import byucc.edif.tools.merge.*;
 import byucc.edif.*;
 import java.io.*;
 import java.util.*;
 import edu.berkeley.slipway.*;
-import com.atmel.fpslic.*;
-import static com.atmel.fpslic.FpslicConstants.*;
 import static edu.berkeley.slipway.mpar.MPARDemo.*;
 
-public class PhysicalDevice {
-    private final Fpslic fpslic;
-        
-    public final int width;
-    public final int height;
-    private final PhysicalNet[][][][] sectorWires;
-    private final PhysicalCell[][] cells;
+public abstract class PhysicalDevice implements Iterable<PhysicalDevice.PhysicalNet> {
 
-    public PhysicalCell getCell(int col, int row) {
-        if (col<0) return null;
-        if (row<0) return null;
-        if (col>=width) return null;
-        if (row>=height) return null;
-        return cells[col][row];
-    }
+    public abstract PhysicalCell getCell(int col, int row);
 
-    public PhysicalDevice(final Fpslic fpslic, int width, int height) {
-        this.fpslic = fpslic;
-        this.width = width;
-        this.height = height;
-        sectorWires = new PhysicalNet[width][height][5][2];
-        for(int x=0; x<width; x+=4)
-            for(int y=0; y<height; y+=4)
-                for(int p=0; p<5; p++) {
-                    for(int xc=x; xc<x+4; xc++) {
-                        PhysicalNet vwire = new PhysicalNet("("+xc+","+y+"-"+(y+3)+")");
-                        for(int yc=y; yc<y+4; yc++)
-                            sectorWires[xc][yc][p][0] = vwire;
-                    }
-                    for(int yc=y; yc<y+4; yc++) {
-                        PhysicalNet hwire = new PhysicalNet("("+x+"-"+(x+3)+","+yc+")");
-                        for(int xc=x; xc<x+4; xc++)
-                            sectorWires[xc][yc][p][1] = hwire;
-                    }
-                }
+    private HashSet<PhysicalNet> allPhysicalNets = new HashSet<PhysicalNet>();
+    public Iterator<PhysicalNet> iterator() { return allPhysicalNets.iterator(); }
 
-        for(int x=4; x<width; x+=4) {
-            for(int y=0; y<height; y++) {
-                for(int p=0; p<5; p++) {
-                    final int xc = x;
-                    final int yc = y;
-                    final int pc = p;
-                    new PhysicalPip("xxx",
-                                    sectorWires[x-1][y][p][1],
-                                    new PhysicalNet[] { sectorWires[x][y][p][1] },
-                                    5) {
-                        public void set(boolean connected) {
-                            fpslic.cell(xc-1, yc).hwire(pc).drives(fpslic.cell(xc, yc).hwire(pc), connected);
-                        }
-                    };
-                    new PhysicalPip("xxx",
-                                    sectorWires[x][y][p][1],
-                                    new PhysicalNet[] { sectorWires[x-1][y][p][1] },
-                                    5) {
-                        public void set(boolean connected) {
-                            fpslic.cell(xc, yc).hwire(pc).drives(fpslic.cell(xc-1, yc).hwire(pc), connected);
-                        }
-                    };
-                }
-            }
-        }
-
-        for(int x=0; x<width; x++) {
-            for(int y=4; y<height; y+=4) {
-                for(int p=0; p<5; p++) {
-                    final int xc = x;
-                    final int yc = y;
-                    final int pc = p;
-                    new PhysicalPip("xxx",
-                                    sectorWires[x][y-1][p][0],
-                                    new PhysicalNet[] { sectorWires[x][y][p][0] },
-                                    5) {
-                        public void set(boolean connected) {
-                            fpslic.cell(xc, yc-1).vwire(pc).drives(fpslic.cell(xc, yc).vwire(pc), connected);
-                        }
-                    };
-                    new PhysicalPip("xxx",
-                                    sectorWires[x][y][p][0],
-                                    new PhysicalNet[] { sectorWires[x][y-1][p][0] },
-                                    5) {
-                        public void set(boolean connected) {
-                            fpslic.cell(xc, yc).vwire(pc).drives(fpslic.cell(xc, yc-1).vwire(pc), connected);
-                        }
-                    };
-                }
-            }
-        }
-
-        cells = new PhysicalCell[width][height];
-        for(int x=0; x<width; x++)
-            for(int y=0; y<height; y++) {
-                cells[x][y] = new PhysicalCell(x, y);
-            }
-        for(int x=0; x<width; x++)
-            for(int y=0; y<height; y++)
-                cells[x][y].link();
+    public abstract class PhysicalCell {
+        public abstract PhysicalNet getNet(String name);
+        public abstract void setFunction(String type);
+        public abstract void place(NetList.Node n);
     }
 
-    private PhysicalNet getSectorWire(int col, int row, int plane, boolean horizontal) {
-        return sectorWires[col][row][plane][horizontal ? 1 : 0];
-    }
-
-    public class PhysicalCell {
-
-        public PhysicalNet getNet(String name) {
-            if (name.equals("out")) return outputNet;
-            if (name.equals("xi"))  return xin;
-            if (name.equals("yi"))  return yin;
-            throw new RuntimeException("unknown");
-        }
-
-        private int col;
-        private int row;
-        private PhysicalNet   outputNet;
-        private PhysicalNet   xin;
-        private PhysicalNet   yin;
-        private PhysicalNet[] local = new PhysicalNet[5];
-
-        private Fpslic.Cell cell() { return fpslic.cell(col, row); }
-
-        public void setFunction(String type) {
-            Fpslic.Cell cell = cell();
-            cell.c(XLUT);
-            cell.xo(false);
-            cell.b(false);
-            cell.f(false);
-            if      (type.equals("and2"))    cell.xlut(LUT_SELF & LUT_OTHER);
-            else if (type.equals("or2"))     cell.xlut(LUT_SELF | LUT_OTHER);
-            else if (type.equals("xor2"))    cell.xlut(LUT_SELF ^ LUT_OTHER);
-            else if (type.equals("buf"))     cell.xlut(LUT_SELF);
-            else if (type.equals("inv"))     cell.xlut(~LUT_SELF);
-        }
-
-        public void link() {
-            // FIXME wow, this is a horrendous hack!
-            if (getCell(col-1, row+1) != null)
-                new PhysicalPip(this+".xiNW", getCell(col-1, row+1).getNet("out"), new PhysicalNet[] { xin }, 5) {
-                    public void set(boolean connected) { cell().xi(connected ? NW : NONE); }
-                };
-            if (getCell(col-1, row-1) != null)
-                new PhysicalPip(this+".xiSW", getCell(col-1, row-1).getNet("out"), new PhysicalNet[] { xin }, 5) {
-                    public void set(boolean connected) { cell().xi(connected ? SW : NONE); }
-                };
-            if (getCell(col+1, row+1) != null)
-                new PhysicalPip(this+".xiNE", getCell(col+1, row+1).getNet("out"), new PhysicalNet[] { xin }, 5) {
-                    public void set(boolean connected) { cell().xi(connected ? NE : NONE); }
-                };
-            if (getCell(col+1, row-1) != null)
-                new PhysicalPip(this+".xiSE", getCell(col+1, row-1).getNet("out"), new PhysicalNet[] { xin }, 5) {
-                    public void set(boolean connected) { cell().xi(connected ? SE : NONE); }
-                };
-        }
-
-        private PhysicalCell(int col, int row) {
-            this.row = row;
-            this.col = col;
-            outputNet = new PhysicalNet(this.toString()+".out");
-            xin       = new PhysicalNet(this.toString()+".xi");
-            yin       = new PhysicalNet(this.toString()+".yi");
-            for(int j=0; j<5; j++) {
-
-                // plane 3 is reserved for debugging
-                if (j==3) continue;
-
-                final int i = j;
-                local[i] = new PhysicalNet(this.toString()+".L"+i);
-                new PhysicalPip(this+".h"+i,  null,      new PhysicalNet[] { local[i], getSectorWire(col, row, i, true) }) {
-                    public void set(boolean connected) { cell().h(i, connected); }
-                };
-                new PhysicalPip(this+".v"+i,  null,      new PhysicalNet[] { local[i], getSectorWire(col, row, i, false) }) {
-                    public void set(boolean connected) { cell().v(i, connected); }
-                };
-                new PhysicalPip(this+".xi"+i, local[i],  new PhysicalNet[] { xin }) {
-                    public void set(boolean connected) { cell().xi(connected ? i : NONE); }
-                };
-                new PhysicalPip(this+".yi"+i, local[i],  new PhysicalNet[] { yin }) {
-                    public void set(boolean connected) { cell().yi(connected ? i : NONE); }
-                };
-                new PhysicalPip(this+".o"+i,  outputNet, new PhysicalNet[] { local[i] }) {
-                    public void set(boolean connected) { cell().out(i, connected); }
-                };
-            }
-        }
-        public  String toString() { return "cell@("+col+","+row+")"; }
+    public class PhysicalNet implements Iterable<PhysicalPip>, Comparable<PhysicalNet> {
 
-    }
+        // per-par-iteration variables
+        private  double      congestion = 0;
+        private  int         load = 0;
 
-    public void route(PhysicalNet source, PhysicalNet[] dests, FlatNetlist.Net owner) {
-        HashSet<PhysicalNet> remainingDests = new HashSet<PhysicalNet>();
-        for(PhysicalNet dest : dests) remainingDests.add(dest);
+        // temporary variables used during route searches
+        private  double      distance = Double.MAX_VALUE;
+        private  PhysicalNet backpointer = null;
 
-        HashSet<PhysicalNet> needsReset = new HashSet<PhysicalNet>();
-        PriorityQueue<PhysicalNet> pq = new PriorityQueue<PhysicalNet>();
-        needsReset.add(source);
-        source.distance = 0;
-        pq.add(source);
+        // adjacent pips
+        private final HashSet<PhysicalPip> pips = new HashSet<PhysicalPip>();
 
-        OUTER: while(true) {
-            PhysicalNet pn = pq.poll();
-            if (pn==null) throw new Error("unroutable! " + source + " -> " + dests[0]);
-            double frontier = pn.distance;
-            for(PhysicalPip pip : pn)
-                for(PhysicalNet net : pip.getDrivenNets()) {
-                    double newfrontier = frontier + 0.05 + net.congestion;
+        private String name;
 
-                    // penalty for using any net already routed in this iteration (makes routing order-sensitive)
-                    if (net.load >= 1) newfrontier = newfrontier + 20;
+        // logical nets currently mapped onto this physical net
+        private HashSet<NetList.LogicalNet> logicalNets = new HashSet<NetList.LogicalNet>();
 
-                    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;
-                    }
-                }
+        public double getCongestion() { return congestion; }
+        public boolean isCongested() { return load >= 2; }
+        public void updateCongestion() {
+            congestion = congestion * alphaParameter;
+            if (isCongested()) congestion += betaParameter;
         }
 
-        for(PhysicalNet dest : dests) {
-            PhysicalNet pn = dest;
-            while(pn != null && pn.backpointer != null) {
-                pn.owners.add(owner);
-                owner.pns.add(pn);
-                if (pn.distance != Double.MAX_VALUE) {
-                    pn.distance = Double.MAX_VALUE;
-                    pn.load++;
-                    if (pn.load>=2) pn.congestion += betaParameter;
-                }
-                PhysicalPip pip = pn.getPipFrom(pn.backpointer);
-                pip.set(true);
-                owner.pips.add(pip);
-                pn = pn.backpointer;
-            }
-            // FIXME: check pn==source at this point
+        public Iterable<NetList.LogicalNet> getLogicalNets() { return logicalNets; }
+        public void addLogicalNet(NetList.LogicalNet net) {
+            if (logicalNets.contains(net)) return;
+            logicalNets.add(net);
+            load++;
+            if (load >= 2) congestion += betaParameter;
+            net.addPhysicalNet(this);
         }
-
-        for(PhysicalNet pn : needsReset) {
-            pn.distance    = Double.MAX_VALUE;
-            pn.backpointer = null;
+        public void removeLogicalNet(NetList.LogicalNet net) {
+            if (!logicalNets.contains(net)) return;
+            logicalNets.remove(net);
+            load--;
+            net.removePhysicalNet(this);
         }
-    }
-    public HashSet<PhysicalNet> allPhysicalNets = new HashSet<PhysicalNet>();
-    public class PhysicalNet implements Iterable<PhysicalPip>, Comparable<PhysicalNet> {
-        public double      congestion = 0;
-        public int         load = 0;
-        public double      distance = Double.MAX_VALUE;
-        public PhysicalNet backpointer = null;
 
+        /** 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
@@ -277,9 +69,7 @@ public class PhysicalDevice {
                 : 0;
         }
 
-        private final HashSet<PhysicalPip> pips = new HashSet<PhysicalPip>();
         public Iterator<PhysicalPip> iterator() { return pips.iterator(); }
-        private String name;
         public PhysicalNet(String name) {
             this.name = name;
             allPhysicalNets.add(this);
@@ -293,20 +83,75 @@ public class PhysicalDevice {
                         return pip;
             return null;
         }
-        public HashSet<FlatNetlist.Net> owners = new HashSet<FlatNetlist.Net>();
+        public void route(PhysicalNet[] dests, NetList.LogicalNet logicalNet) {
+            HashSet<PhysicalNet> remainingDests = new HashSet<PhysicalNet>();
+            for(PhysicalNet dest : dests) remainingDests.add(dest);
+
+            HashSet<PhysicalNet> needsReset = new HashSet<PhysicalNet>();
+            PriorityQueue<PhysicalNet> pq = new PriorityQueue<PhysicalNet>();
+            needsReset.add(this);
+            this.distance = 0;
+            pq.add(this);
+
+            OUTER: while(true) {
+                PhysicalNet pn = pq.poll();
+                if (pn==null) throw new Error("unroutable! " + this + " -> " + dests[0]);
+                double frontier = pn.distance;
+                for(PhysicalPip pip : pn)
+                    for(PhysicalNet net : pip.getDrivenNets()) {
+                        double newfrontier = frontier + pip.getCost(pn, net) + net.getCongestion();
+
+                        // penalty for using any net already routed in this iteration (makes routing order-sensitive)
+                        if (net.load >= 1) newfrontier = newfrontier + 20;
+
+                        if (net.distance <= newfrontier) continue;
+                        pq.remove(net);  // if already in there
+                        net.distance = newfrontier;
+                        pq.add(net);
+                        needsReset.add(net);
+                        net.backpointer = pn;
+
+                        if (remainingDests.contains(net)) {
+                            remainingDests.remove(net);
+                            if (remainingDests.size()==0) break OUTER;
+                            // Vaughn Betz style multiterminal routing: once we reach one sink, make every node on the path
+                            // "distance zero" from the source.
+                            for(PhysicalNet pnx = net; pnx != null; pnx = pnx.backpointer) {
+                                pnx.distance = 0;
+                                pq.add(pnx);
+                            }
+                            break;
+                        }
+                    }
+            }
+
+            for(PhysicalNet dest : dests)
+                for(PhysicalNet pn = dest; pn != null && pn.backpointer != null; pn = pn.backpointer) {
+                    pn.addLogicalNet(logicalNet);
+                    pn.distance = Double.MAX_VALUE;
+                    PhysicalPip pip = pn.getPipFrom(pn.backpointer);
+                    pip.set(true);
+                    logicalNet.addPhysicalPip(pip);
+                }
+
+            for(PhysicalNet pn : needsReset) {
+                pn.distance    = Double.MAX_VALUE;
+                pn.backpointer = null;
+            }
+        }
     }
         
     public abstract class PhysicalPip {
         private PhysicalNet   driver;
         private PhysicalNet[] driven;
         private String name;
-        private int defaultCost;
+        private double defaultCost;
         public String toString() { return name; }
         public PhysicalNet   getDriverNet()  { return driver; }
         public PhysicalNet[] getDrivenNets() { return driven; }
-        public int           getCost(PhysicalNet in, PhysicalNet out) { return defaultCost; }
-        public PhysicalPip(String name, PhysicalNet driver, PhysicalNet[] driven) { this(name, driver, driven, 100); }
-        public PhysicalPip(String name, PhysicalNet driver, PhysicalNet[] driven, int defaultCost) {
+        public double        getCost(PhysicalNet in, PhysicalNet out) { return defaultCost; }
+        public PhysicalPip(String name, PhysicalNet driver, PhysicalNet[] driven) { this(name, driver, driven, 0.05); }
+        public PhysicalPip(String name, PhysicalNet driver, PhysicalNet[] driven, double defaultCost) {
             this.name = name;
             this.driver = driver;
             this.driven = driven;