50f59b558ab40e4017cacb00ebce8e26319b37d7
[slipway.git] / src / edu / berkeley / slipway / mpar / NetList.java
1 package edu.berkeley.slipway.mpar;
2 import com.atmel.fpslic.*;
3 import byucc.edif.tools.merge.*;
4 import byucc.edif.*;
5 import java.io.*;
6 import java.util.*;
7 import edu.berkeley.slipway.*;
8 import com.atmel.fpslic.*;
9 import static com.atmel.fpslic.FpslicConstants.*;
10 import static edu.berkeley.slipway.mpar.MPARDemo.*;
11
12 public class NetList {
13
14     private HashMap<String,Integer> ids = new HashMap<String,Integer>();
15
16     public HashSet<Node>        nodes = new HashSet<Node>();
17     public HashSet<LogicalNet>  nets  = new HashSet<LogicalNet>();
18
19     /** a node is some primitive element; a potential configuration of a CLB */
20     public class Node {
21         public PhysicalDevice.PhysicalCell physicalCell = null;
22         private final String type;
23         private final int    id;
24
25         public int x = -1;
26         public int y = -1;
27
28         private HashMap<String,Port> ports = new HashMap<String,Port>();
29
30         public Node(String type) {
31             nodes.add(this);
32             this.type = type.toLowerCase();
33             Integer num = ids.get(type);
34             this.id = num == null ? 0 : num.intValue();
35             ids.put(type, this.id+1);
36         }
37         public String getType() { return type; }
38         public String toString() {
39             if (x==-1 || y==-1)
40                 return type + "["+id+"]";
41             return type + "@("+x+","+y+")";
42         }
43         public Port getPort(String name, boolean driver) {
44             Port p = ports.get(name);
45             if (p==null) ports.put(name, p = new Port(name, driver));
46             return p;
47         }
48
49         public Fpslic.Cell getPlacement(Fpslic fpslic) { return fpslic.cell(x, y); }
50
51         private int portIndex = 0;
52
53         /** a port is an input or output to a Node */
54         public class Port {
55             private final String name;
56             private final boolean driver;
57             LogicalNet    net;
58             public final int index;
59             public Port(String name, boolean driver) {
60                 this.name = name;
61                 this.driver = driver;
62                 this.index = driver ? 0 : portIndex++;
63             }
64             public String toString() { return Node.this + "." + name; }
65             public Node getNode() { return Node.this; }
66             public void connect(Port p) {
67                 if (net != null)          { net.add(p);
68                 } else if (p.net != null) { p.net.add(this);
69                 } else {
70                     new LogicalNet().add(this);
71                     this.net.add(p);
72                 }
73             }
74         }
75     }
76
77     /** a Net is a collection of ports which are wired together */
78     public class LogicalNet implements Iterable<Node.Port> {
79         private Node.Port driver = null;
80         private HashSet<Node.Port> ports = new HashSet<Node.Port>();
81         private HashSet<PhysicalDevice.PhysicalPip> pips = new HashSet<PhysicalDevice.PhysicalPip>();
82         private HashSet<PhysicalDevice.PhysicalNet> pns = new HashSet<PhysicalDevice.PhysicalNet>();
83
84         public void addPhysicalNet(PhysicalDevice.PhysicalNet pn) { pns.add(pn); }
85         public void removePhysicalNet(PhysicalDevice.PhysicalNet pn) { pns.remove(pn); }
86         public void addPhysicalPip(PhysicalDevice.PhysicalPip pip) { pips.add(pip); }
87
88         public LogicalNet() { nets.add(this); }
89         public Iterator<Node.Port> iterator() { return ports.iterator(); }
90         public int getSize() { return ports.size(); }
91         public boolean routed = false;
92         public void unroute() {
93             for(PhysicalDevice.PhysicalPip pip : pips) pip.set(false);
94             while(pns.size() > 0) pns.iterator().next().removeLogicalNet(this);
95             pips.clear();
96             pns.clear();
97             routed = false;
98         }
99         public void route(Fpslic fpslic, PhysicalDevice pd) {
100             if (driver == null) return;
101             if (routed) return;
102             Node.Port[] dests = new Node.Port[ports.size() - (ports.contains(driver) ? 1 : 0)];
103             int j = 0;
104             for(Node.Port p : ports)
105                 if (p != driver)
106                     dests[j++] = p;
107             PhysicalDevice.PhysicalNet[] destsp = new PhysicalDevice.PhysicalNet[dests.length];
108             for(int i=0; i<dests.length; i++) {
109                 Node.Port dest = dests[i];
110                 switch(dest.index) {
111                     case 0: destsp[i] = dest.getNode().physicalCell.getNet("xi"); break;
112                     case 1: destsp[i] = dest.getNode().physicalCell.getNet("yi"); break;
113                     default: throw new Error();
114                 }
115             }
116             driver.getNode().physicalCell.getNet("out").route(destsp, this);
117             routed = true;
118         }
119         public void add(Node.Port p) {
120             if (p.driver) {
121                 if (driver != null && driver != p)
122                     throw new RuntimeException("two drivers on a port!\n  "+driver+"\n  "+p);
123                 driver = p;
124             }
125             if (p.net==this || ports.contains(p)) return;
126             ports.add(p);
127             add(p.net);
128             p.net = this;
129         }
130         public void add(LogicalNet n) {
131             if (n==this || n==null) return;
132             for(Node.Port p : n) add(p);
133             nets.remove(n);
134         }
135         public String toString() {
136             StringBuffer ret = new StringBuffer();
137             ret.append(driver==null ? "()" : driver.toString());
138             ret.append(" -> ");
139             for(Node.Port p : this)
140                 if (p!=driver)
141                     ret.append(p+" ");
142             return ret.toString();
143         }
144     }
145
146
147     public HashMap<EdifCellInstance,NetList.Node> cache =
148         new HashMap<EdifCellInstance,NetList.Node>();
149     public HashMap<String,NetList.Node> top =
150         new HashMap<String,NetList.Node>();
151        
152     public NetList.Node createNode(EdifCellInstance eci, String portName) {
153         NetList.Node n = eci==null ? top.get(portName) : cache.get(eci);
154         if (n != null) return n;
155         if (eci==null) {
156             n = new NetList.Node("top_"+portName);
157             top.put(portName, n);
158             return n;
159         } else {
160             n = new NetList.Node(eci.getType());
161             cache.put(eci,n);
162         }
163         for(EdifPortRef epr : eci.getAllEPRs()) {
164             EdifPort ep = epr.getPort();
165             EdifNet  en = epr.getNet();
166             String name = ep.getOldName();
167             boolean driver = ep.getDirection()==ep.OUT;
168             if (eci==null) driver = !driver;
169             if (eci==null) name = driver ? "out" : "xi";
170             NetList.Node.Port p = n.getPort(name, driver);
171             for(EdifPortRef epr2 : en.getConnectedPortRefs()) {
172                 EdifCellInstance eci2 = epr2.getCellInstance();
173                 EdifPort ep2 = epr2.getPort();
174                 Node n2 = createNode(eci2, ep2.getOldName());
175                 driver = ep2.getDirection()==ep.OUT;
176                 name = ep2.getOldName();
177                 if (eci2==null) driver = !driver;
178                 if (eci2==null) name = driver ? "out" : "xi";
179                 NetList.Node.Port p2 = n2.getPort(name, driver);
180                 p.connect(p2);
181             }
182         }
183         return n;
184     }
185 }