implement port percolation
[fleet.git] / src / edu / berkeley / fleet / two / ShipDescription.java
1 package edu.berkeley.fleet.two;
2 import edu.berkeley.fleet.api.*;
3 import edu.berkeley.fleet.fpga.verilog.Verilog.PercolatedPort;
4 import java.io.*;
5 import java.util.*;
6
7 /** NOT YET FINALIZED: A description (specification) of a ship */
8 public class ShipDescription implements Iterable<DockDescription> {
9
10     private String name;
11     private LinkedHashMap<String,DockDescription> docks     = new LinkedHashMap<String,DockDescription>();
12     private HashMap<String,String>                sections  = new HashMap<String,String>();
13     private HashMap<String,Constant>              constants = new HashMap<String,Constant>();
14
15     public String getName() { return name; }
16     public String getSection(String sectionName) { return sections.get(sectionName); }
17     public DockDescription getDockDescription(String name) { return docks.get(name); }
18     public Iterator<DockDescription> iterator() { return docks.values().iterator(); }
19
20     public final LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
21
22     public ShipDescription(String name, BufferedReader r) throws IOException {
23         if (name.endsWith(".ship")) name = name.substring(0, name.length()-".ship".length());
24         this.name = name;
25         String sectionName = null;
26         StringBuffer sb = new StringBuffer();
27         while(true) {
28             String s = r.readLine();
29             if (s==null || s.startsWith("==")) {
30                 if (sectionName != null) sections.put(sectionName, sb.toString());
31                 if (s==null) break;
32                 sb = new StringBuffer();
33                 sectionName = s.trim();
34                 while(sectionName.startsWith("="))
35                     sectionName = sectionName.substring(1);
36                 while(sectionName.endsWith("="))
37                     sectionName = sectionName.substring(0, sectionName.length()-1);
38                 sectionName = sectionName.trim().toLowerCase();
39                 continue;
40             }
41             sb.append(s+"\n");
42         }
43         for(String s : sections.keySet())
44             processSection(s);
45     }
46
47     public Constant getConstant(String name) {
48         return constants.get(name);
49     }
50
51     private void processSection(String section) throws IOException {
52         if (section.equals("")) {
53             BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
54             for(String s = br.readLine(); s != null; s = br.readLine()) {
55                 if (s.trim().length()==0) continue;
56                 String key = s.substring(0, s.indexOf(':')).trim();
57                 String val = s.substring(s.indexOf(':')+1).trim();
58                 if (key.toLowerCase().equals("ship"))
59                     name = val.trim();
60             }
61         } else if (section.equals("constants")) {
62             BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
63             for(String s = br.readLine(); s != null; s = br.readLine()) {
64                 if (s.indexOf(':')==-1) continue;
65                 String key = s.substring(0, s.indexOf(':')).trim();
66                 if (key.startsWith("constant")) {
67                     String constname = key.substring("constant".length()+1).trim();
68                     String val       = s.substring(s.indexOf(':')+1).trim();
69                     constants.put(constname, new Constant(val));
70                 }
71             }
72         } else if (section.equals("ports")) {
73             BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
74             boolean rightSide = false;
75             DockDescription p = null;
76             for(String s = br.readLine(); s != null; s = br.readLine()) {
77                 if (s.trim().length()==0) { rightSide = true; continue; }
78
79                 String key = s.substring(0, s.indexOf(':')).trim();
80                 boolean inbox = false;
81                 key = key.replaceAll("  +", " ");
82                 if      (key.equals("data in"))   { inbox = true;  }
83                 else if (key.equals("data out"))  { inbox = false; }
84                 else if (key.equals("in"))        { inbox = true;  }
85                 else if (key.equals("out"))       { inbox = false; }
86                 else if (key.startsWith("percolate")) { 
87                     key = s;
88                     key = key.substring("percolate".length()+1).trim();
89                     PercolatedPort.PortType type = null;
90                     if (key.startsWith("up")) type = PercolatedPort.PortType.UP;
91                     if (key.startsWith("down")) type = PercolatedPort.PortType.DOWN;
92                     if (key.startsWith("inout")) type = PercolatedPort.PortType.INOUT;
93                     key = key.substring(key.indexOf(':')+1).trim();
94                     String name = key.substring(0, key.indexOf(' '));
95                     int width = Integer.parseInt(key.substring(key.indexOf(' ')).trim());
96                     percolatedPorts.add(new PercolatedPort(name, width, type));
97                     continue;
98                 }
99                 else if (key.startsWith("constant")) {
100                     String constname = key.substring("constant".length()+1).trim();
101                     String val       = s.substring(s.indexOf(':')+1).trim();
102                     p.addConstant(constname, new Constant(val));
103                     continue;
104                 } else if (key.startsWith("shortcut to")) {
105                     continue;
106                 }
107                 else throw new RuntimeException("unknown port type: \""+key+"\"");
108
109                 p = null;
110                 String val = s.substring(s.indexOf(':')+1).trim();
111                 String boxname = val.indexOf('.') != -1 ? val.substring(0, val.indexOf('.')) : val;
112                 String dest    = val.indexOf('.') != -1 ? val.substring(val.indexOf('.')+1)  : "";
113                 p = docks.get(boxname);
114                 if (p==null) {
115                     p = new DockDescription(this, boxname, !rightSide, inbox);
116                     docks.put(boxname, p);
117                 }
118             }
119         }
120     }
121
122     public void printTeX(PrintWriter pw) throws Exception {
123         ShipDescription sd = this;
124         pw.println("\\pagebreak");
125         pw.println("\\section*{The {\\tt "+sd.getName()+"} Ship}");
126         pw.println("\\addcontentsline{toc}{subsection}{"+sd.getName()+"}");
127         String tex = sd.getSection("tex");
128         /*
129         for(DockDescription bbd : sd) {
130             pw.println("{\\bf "+(bbd.isInputDock() ? "Input: " : "Output: ")+"{\\tt "+bbd.getName()+"}}\n\n");
131         }
132         */
133         int boxGap = 5;
134         int boxHeight = 25;
135         int boxWidth = 75;
136
137         int leftSize = 0;
138         int rightSize = 0;
139         for(DockDescription bbd : sd)
140             if (bbd.isLeft()) leftSize += (boxHeight+boxGap);
141             else              rightSize += (boxHeight+boxGap);
142
143         int totalHeight = Math.max(leftSize, rightSize);
144         int shipWidth = (int)(boxWidth * 1.5);
145         int totalWidth = boxGap*2 + boxWidth*2 + shipWidth;
146
147         pw.println("");
148         pw.println("\\begin{center}");
149         pw.println("\\begin{empfile}["+sd.getName()+"]");
150         pw.println("\\begin{emp}["+sd.getName()+"]("+(totalWidth+10)+","+(totalHeight+10)+")");
151         pw.println("  beginfig(1)");
152         pw.println("      pickup pencircle scaled 1pt;");
153         pw.println("      draw "+
154                    "("+((totalWidth-shipWidth)/2)+","+0+")--"+
155                    "("+((totalWidth-shipWidth)/2)+","+totalHeight+")--"+
156                    "("+(totalWidth-((totalWidth-shipWidth)/2))+","+totalHeight+")--"+
157                    "("+(totalWidth-((totalWidth-shipWidth)/2))+","+0+")--"+
158                    "("+((totalWidth-shipWidth)/2)+","+0+");");
159         int left = 0;
160         int right = 0;
161         for(DockDescription bbd : sd) {
162             int ypos = (totalHeight - (boxGap/2) - (bbd.isLeft() ? left : right));
163             int half = (totalWidth-shipWidth)/2;
164             int p1 = bbd.isLeft() ? (half-5) : ((totalWidth-half)+5);
165             int p3 = bbd.isLeft() ? (p1 - boxWidth) : (p1 + boxWidth);
166             if (bbd.isInputDock()) {
167                 int p1x = p1;
168                 p1 = p3;
169                 p3 = p1x;
170             }
171             boolean goo = ((bbd.isLeft() && bbd.isInputDock()) || (!bbd.isLeft() && bbd.isOutputDock()));
172             int p2 = goo ? (p3 - (boxHeight/2)) : (p3 + (boxHeight/2));
173             if (bbd.isLeft()) left += (boxHeight+boxGap);
174             else              right += (boxHeight+boxGap);
175             if (goo) {
176                 pw.println("      label.rt(btex \\tt "+bbd.getName()+" etex, ("+(p1+3)+","+(ypos-boxHeight/2)+"));");
177             } else {
178                 pw.println("      label.lft(btex \\tt "+bbd.getName()+" etex, ("+(p1-3)+","+(ypos-boxHeight/2)+"));");
179             }
180             pw.println("      draw "+
181                        "  ("+p1+","+ypos+")--"+
182                        "  ("+p2+","+ypos+")--"+
183                        "  ("+p3+","+(ypos-(boxHeight/2))+")--"+
184                        "  ("+p2+","+(ypos-boxHeight)+")--"+
185                        "  ("+p1+","+(ypos-boxHeight)+")--"+
186                        "  ("+p1+","+ypos+");");
187             if (bbd.isLeft()) leftSize += boxHeight;
188             else              rightSize += boxHeight;
189         }
190         pw.println("  endfig;");
191         pw.println("\\end{emp}");
192         pw.println("\\end{empfile}");
193         pw.println("\\end{center}");
194         pw.println("");
195
196         if (tex!=null)
197             pw.println(tex);
198     }
199
200     // FIXME: merge with BitMask
201     public class Constant {
202         public long    setbits   = 0;
203         public long    clearbits = 0;
204         public boolean signExtend = false;
205         public int     numberOffset = 0;
206         public int     numberWidth = 0;
207         public Constant(String s) {
208             if (s.startsWith("0x")) {
209                 setbits = Long.parseLong(s.substring(2), 16);
210                 clearbits = ~setbits;
211             } else if (s.length() == 37) {
212                 for(int i=36; i>=0; i--) {
213                     char c = s.charAt(36-i);
214                     switch(c) {
215                         case '0': clearbits |= (1<<i); break;
216                         case '1': setbits   |= (1<<i); break;
217                         case '.': break;
218                         case 's': signExtend = true;  numberOffset = i; numberWidth++; break;
219                         case 'u': signExtend = false; numberOffset = i; numberWidth++; break;
220                     }
221                 }
222             } else {
223                 setbits = Long.parseLong(s);
224                 clearbits = ~setbits;
225             }
226         }
227     }
228
229 }