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