added visualizer
[slipway.git] / src / edu / berkeley / obits / Visual.java
1 package edu.berkeley.obits;
2
3 import static edu.berkeley.obits.device.atmel.AtmelDevice.Constants.*;
4 import static edu.berkeley.obits.device.atmel.AtmelDevice.Util.*;
5 import edu.berkeley.obits.device.atmel.*;
6 import java.awt.*;
7 import java.awt.geom.*;
8 import java.awt.event.*;
9 import java.awt.color.*;
10 import org.ibex.util.*;
11 import java.io.*;
12 import java.util.*;
13 import javax.swing.*;
14
15 public class Visual extends JFrame implements KeyListener {
16
17     public static int SIZE = 92;
18     public static int RINGS = 3;
19     public static int BEVEL = 5;
20     public static int CORE_SIZE = 64;
21     public static int CORE_OFFSET = 10;
22
23     public static int HOFF = 52;
24
25     /*
26     public static void main(String[] s) {
27         Visual v = new Visual();
28         v.show();
29         v.setSize(400, 400);
30     }
31     */
32
33     At40k at40k;
34
35     public Visual(At40k at40k) {
36         this.at40k = at40k;
37         for(int x=0; x<7; x++)
38             for(int y=0; y<7; y++)
39                 new Cell(x,y, at40k.cell(x+7, y+7));
40         addKeyListener(this);
41     }
42
43     private HashSet<Cell> cells = new HashSet<Cell>();
44
45     public class Cell {
46         Graphics2D g;
47         At40k.Cell cell;
48         int _x, _y;
49         public Cell(int x, int y, At40k.Cell cell) {
50             _x = x;
51             _y = y;
52             this.cell = cell;
53             cells.add(this);
54         }
55         public void draw() {
56             drawHwires();
57             drawVwires();
58             drawInternalRouting();
59             drawLocal();
60             drawGates();
61             drawMux();
62             drawRegister();
63             drawBorder();
64         }
65         public void drawHwires() {
66             g.setColor(Color.magenta);
67             for(int i=0; i<5; i++)
68                 if (cell.hwire(i).isDriven())
69                     g.drawLine(0, SIZE-(2*(1+RINGS)+2*i), SIZE, SIZE-(2*(1+RINGS)+2*i));
70         }
71         public void drawVwires() {
72             g.setColor(Color.magenta);
73             for(int i=0; i<5; i++)
74                 if (cell.vwire(i).isDriven())
75                     g.drawLine(2*(1+RINGS)+2*i, 0, 2*(1+RINGS)+2*i, SIZE);
76         }
77         public void drawInternalRouting() {
78         }
79
80         public void drawLocal() {
81             if (!cell.ylut_relevant() && !cell.ylut_relevant()) return;
82             Point2D in   = new Point2D.Double(HOFF, 0);
83             Point2D join = new Point2D.Double(HOFF, CORE_OFFSET);
84             rotateOuter(in);
85             rotateInner(join);
86             int rot = rot();
87             switch(rot) {
88                 case 0: case 2:
89                     join.setLocation(in.getX(), join.getY());
90                     break;
91                 case 1: case 3:
92                     join.setLocation(join.getX(), in.getY());
93                     break;
94             }
95
96             Point2D xi = null;
97             g.setColor(new Color(0xff, 0x00, 0x00));
98             int xring = 4;
99             switch(cell.xi()) {
100                 case NW:
101                     xi = new Point2D.Double(0+2*xring, SIZE-2*xring);
102                     g.draw(new Line2D.Double(new Point2D.Double(0, SIZE), xi));
103                     break;
104
105                 case SW:
106                     xi = new Point2D.Double(0+2*xring, 0+2*xring);
107                     g.draw(new Line2D.Double(new Point2D.Double(0, 0), xi));
108                     break;
109
110                 case NE:
111                     xi = new Point2D.Double(SIZE-2*xring, SIZE-2*xring);
112                     g.draw(new Line2D.Double(new Point2D.Double(SIZE, SIZE), xi));
113                     break;
114
115                 case SE:
116                     xi = new Point2D.Double(SIZE-2*xring, 0+2*xring);
117                     g.draw(new Line2D.Double(new Point2D.Double(SIZE, 0), xi));
118                     break;
119
120             }
121
122             if (cell.xlut_relevant()) {
123                 g.setColor(new Color(0x00, 0x00, 0xff));
124                 Point2D c   = new Point2D.Double(SIZE - CORE_OFFSET - CORE_SIZE/2 - CORE_SIZE / 6, 20);
125                 rotateInner(c);
126                 route(in, c, 5);
127
128                 g.setColor(new Color(0xff, 0x00, 0x00));
129                 c   = new Point2D.Double(SIZE - CORE_OFFSET - CORE_SIZE/2 - CORE_SIZE / 3, 20);
130                 rotateInner(c);
131                 if (xi != null)
132                     route(xi, c, 4);
133
134                 Point2D xo   = new Point2D.Double(SIZE-CORE_OFFSET-CORE_SIZE+17 - 2, CORE_OFFSET + 41 - 3);
135                 Point2D xout = new Point2D.Double(SIZE-CORE_OFFSET-CORE_SIZE+17 - 2, CORE_OFFSET + CORE_SIZE - 3);
136                 rotateInner(xo);
137                 rotateInner(xout);
138                 g.setColor(new Color(0xff, 0xcc, 0xcc));
139                 g.draw(new Line2D.Double(xo, xout));
140                 if (cell.ne() != null && cell.ne().xi()==SW) {
141                     Point2D xoo = new Point2D.Double(SIZE-2*xring, SIZE-2*xring);
142                     g.draw(new Line2D.Double(new Point2D.Double(SIZE, SIZE), xoo));
143                     route(xout, xoo, xring);
144                 }
145                 if (cell.nw() != null && cell.nw().xi()==SE) {
146                     Point2D xoo = new Point2D.Double(0+2*xring, SIZE-2*xring);
147                     g.draw(new Line2D.Double(new Point2D.Double(0, SIZE), xoo));
148                     route(xout, xoo, xring);
149                 }
150                 if (cell.se() != null && cell.se().xi()==NW) {
151                     Point2D xoo = new Point2D.Double(SIZE-2*xring, 0+2*xring);
152                     g.draw(new Line2D.Double(new Point2D.Double(SIZE, 0), xoo));
153                     route(xout, xoo, xring);
154                 }
155                 if (cell.sw() != null && cell.sw().xi()==NE) {
156                     Point2D xoo = new Point2D.Double(0+2*xring, 0+2*xring);
157                     g.draw(new Line2D.Double(new Point2D.Double(0, 0), xoo));
158                     route(xout, xoo, xring);
159                 }
160             }
161
162             if (cell.ylut_relevant()) {
163                 g.setColor(new Color(0x00, 0x00, 0xff));
164                 Point2D c   = new Point2D.Double(SIZE - CORE_OFFSET - CORE_SIZE/2 + CORE_SIZE / 6, 20);
165                 rotateInner(c);
166                 route(in, c, 5);
167
168                 g.setColor(new Color(0xff, 0x00, 0x00));
169                 c   = new Point2D.Double(SIZE - CORE_OFFSET - CORE_SIZE/2 + CORE_SIZE / 3, 20);
170                 rotateInner(c);
171                 if (xi != null)
172                     route(xi, c, 4);
173
174                 Point2D yo   = new Point2D.Double(SIZE-CORE_OFFSET-CORE_SIZE+51 - 2, CORE_OFFSET + 41 - 3);
175                 Point2D yout = new Point2D.Double(SIZE-CORE_OFFSET-CORE_SIZE+51 - 2, CORE_OFFSET + CORE_SIZE - 3);
176                 rotateInner(yo);
177                 rotateInner(yout);
178                 g.setColor(new Color(0xbb, 0xbb, 0xff));
179                 //g.setColor(new Color(0x00, 0x00, 0xff));
180                 g.draw(new Line2D.Double(yo, yout));
181                 if (cell.north() != null && cell.north().yi()==SOUTH) route(yout, new Point2D.Double(SIZE-40, SIZE+ 0), 2);
182                 if (cell.east() != null  && cell.east().yi()==WEST)   route(yout, new Point2D.Double(SIZE+ 0,      40), 2);
183                 if (cell.south() != null && cell.south().yi()==NORTH) route(yout, new Point2D.Double(     40,       0), 2);
184                 if (cell.west() != null  && cell.west().yi()==EAST)   route(yout, new Point2D.Double(      0, SIZE-40), 2);
185             }
186
187         }
188
189         private void rotateOuter(Point2D p) {
190             int rot = rot();
191             AffineTransform a = new AffineTransform();
192             a.rotate((Math.PI/2) * rot);
193             switch(rot) {
194                 case 0: break;
195                 case 1: a.translate(0,  -SIZE); break;
196                 case 2: a.translate(-SIZE, -SIZE); break;
197                 case 3: a.translate(-SIZE, 0); break;
198             }
199             a.transform(p, p);
200         }
201
202         private void rotateInner(Point2D p) {
203             int rot = rot();
204             AffineTransform a = new AffineTransform();
205             a.translate(SIZE-CORE_SIZE-CORE_OFFSET, CORE_OFFSET);
206             a.rotate((Math.PI/2) * rot);
207             switch(rot) {
208                 case 0: break;
209                 case 1: a.translate(0,  -CORE_SIZE); break;
210                 case 2: a.translate(-CORE_SIZE, -CORE_SIZE); break;
211                 case 3: a.translate(-CORE_SIZE, 0); break;
212             }
213             a.translate(-1 * (SIZE-CORE_SIZE-CORE_OFFSET), -CORE_OFFSET);
214             a.transform(p, p);
215         }
216
217         private Point2D project(Point2D p1, int ring) {
218             double north = Math.abs( (SIZE-(ring*2)) - p1.getY() );
219             double south = Math.abs( (     (ring*2)) - p1.getY() );
220             double east  = Math.abs( (SIZE-(ring*2)) - p1.getX() );
221             double west  = Math.abs( (     (ring*2)) - p1.getX() );
222             if (north < south && north < east && north < west) {
223                 return new Point2D.Double(p1.getX(), SIZE-ring*2);
224             } else if (south < east && south < west) {
225                 return new Point2D.Double(p1.getX(), ring*2);
226             } else if (east < west) {
227                 return new Point2D.Double(SIZE-ring*2, p1.getY());
228             } else {
229                 return new Point2D.Double(ring*2, p1.getY());
230             }
231         }
232
233         private void route(Point2D p1, Point2D p2, int ring) {
234             int ringpos = ring * 2;
235             Point2D projected = project(p1, ring);
236             g.draw(new Line2D.Double(p1, projected));
237             p1 = projected;
238
239             projected = project(p2, ring);
240             g.draw(new Line2D.Double(p2, projected));
241             p2 = projected;
242
243             double x1 = p1.getX();
244             double y1 = p1.getY();
245             double x2 = p2.getX();
246             double y2 = p2.getY();
247
248             if (x1==x2 || y1==y2) {
249                 g.draw(new Line2D.Double(p1, p2));
250                 return;
251             }
252
253             if ((x1==SIZE-ring*2 || x1==ring*2) && !(y1==SIZE-ring*2 || y1==ring*2)) {
254                 Point2D p3 = new Point2D.Double(x1, y2 > SIZE/2 ? SIZE-ring*2 : ring*2);
255                 g.draw(new Line2D.Double(p1, p3));
256                 route(p3, p2, ring);
257             }
258
259             if (y1==SIZE-ring*2 || y1==ring*2) {
260                 Point2D p3 = new Point2D.Double(x2 > SIZE/2 ? SIZE-ring*2 : ring*2, y1);
261                 g.draw(new Line2D.Double(p1, p3));
262                 route(p3, p2, ring);
263             }
264
265         }
266         
267         private int rot() {
268             int rot = 0;
269             switch(cell.yi()) {
270                 case SOUTH: rot = 0; break;
271                 case NORTH: rot = 2; break;
272                 case EAST: rot = 1; break;
273                 case WEST: rot = 3; break;
274                 default: {
275                     // FIXME: choose based on xin
276                     if (cell.north() != null && cell.north().yi()==SOUTH) { rot = 0; break; }
277                     if (cell.south() != null && cell.south().yi()==NORTH) { rot = 2; break; }
278                     if (cell.east()  != null && cell.east().yi()==WEST) { rot = 3; break; }
279                     if (cell.west()  != null && cell.west().yi()==EAST) { rot = 1; break; }
280                 }
281             }
282             return rot;
283         }
284         
285         public void drawGates() {
286             AffineTransform t = g.getTransform();
287             try {
288                 g.translate(SIZE-CORE_SIZE-CORE_OFFSET, CORE_OFFSET);
289                 
290                 int rot = rot();
291                 g.rotate((Math.PI/2) * rot);
292                 switch(rot) {
293                     case 0: break;
294                     case 1: g.translate(0,  -CORE_SIZE); break;
295                     case 2: g.translate(-CORE_SIZE, -CORE_SIZE); break;
296                     case 3: g.translate(-CORE_SIZE, 0); break;
297                 }
298
299                 //g.setColor(Color.gray);
300                 //g.drawRect(0, 0, CORE_SIZE, CORE_SIZE);
301                 g.scale(1, -1);
302
303                 GeneralPath p = new GeneralPath();
304                 p.moveTo(29.141f, 36.301f);
305                 p.lineTo(29.141f, 36.301f-7.161f);
306                 p.curveTo(27.71f, 11.24f, 23.413f, 9.45f, 14.82f, 0.5f);
307                 p.curveTo(6.229f, 9.45f, 1.932f, 11.24f, 0.5f, 29.141f);
308                 p.lineTo(0.5f, 29.141f+7.161f);
309                 float x = 0.5f;
310                 float y = 29.141f+7.161f;
311                 p.curveTo(5.729f+x, -1.789f+y,
312                           6.444f+x, -2.686f+y,
313                           14.32f+x, -3.58f+y);
314                 p.curveTo(22.697f, 33.616f, 23.413f, 34.512f, 29.141f, 36.301f);
315                 g.translate(0,   -40f);
316                 if (cell.xlut_relevant()) {
317                     g.setColor(Color.white);
318                     g.fill(p);
319                     g.setColor(Color.red);
320                     g.draw(p);
321                 }
322                 g.translate(34f, 0f);
323                 if (cell.ylut_relevant()) {
324                     g.setColor(Color.white);
325                     g.fill(p);
326                     g.setColor(Color.blue);
327                     g.draw(p);
328                 }
329             } finally {
330                 g.setTransform(t);
331             }
332         }
333         public void drawMux() {
334             if (cell.c() != ZMUX) return;
335             g.setColor(Color.black);
336             g.drawLine(46, 54,     46+2, 54+5);
337             g.drawLine(46+2, 54+5, 60-2, 54+5);
338             g.drawLine(60-2, 54+5, 60,   54);
339             g.drawLine(60,   54,   46, 54);
340         }
341         public void drawRegister() {
342         }
343         public void drawBorder() {
344             g.setColor(Color.gray);
345             //g.drawLine(0, BEVEL, BEVEL,    0);
346             g.drawLine(BEVEL, 0, SIZE-BEVEL, 0);
347             //g.drawLine(SIZE-BEVEL, 0, SIZE, BEVEL);
348             g.drawLine(SIZE, BEVEL, SIZE, SIZE-BEVEL);
349             //g.drawLine(SIZE, SIZE-BEVEL, SIZE-BEVEL, SIZE);
350             g.drawLine(SIZE-BEVEL, SIZE, BEVEL, SIZE);
351             //g.drawLine(BEVEL, SIZE, 0, SIZE-BEVEL);
352             g.drawLine(0, SIZE-BEVEL, 0, BEVEL);
353         }
354     }
355
356     public void paint(Graphics _g) {
357         Graphics2D g = (Graphics2D)_g;
358         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
359         g.setRenderingHint(RenderingHints.KEY_RENDERING,    RenderingHints.VALUE_RENDER_QUALITY);
360         g.setStroke(new BasicStroke((float)0.5));
361         g.translate(10, 0);
362         g.scale(1, -1);
363         g.translate(5, -1 * getHeight() + 10);
364         g.scale(scale,scale);
365         for(Cell c : cells) {
366             AffineTransform t = g.getTransform();
367             g.translate(     c._x * SIZE/* + (10 * (c._x/4))*/,      c._y * SIZE/* + (10 * (c._y/4))*/);
368             c.g = g;
369             c.draw();
370             c.g = null;
371             g.setTransform(t);
372         }
373     }
374
375     double scale = 1.0;
376
377     public void clear() {
378         Graphics2D g = (Graphics2D)getGraphics();
379         //g.setColor(Color.black);
380         //g.setColor(Color.lightGray);
381         g.clearRect(0, 0, getWidth(), getHeight());
382     }
383
384     public void keyTyped(KeyEvent k) {
385     }
386     public void keyReleased(KeyEvent k) {
387     }
388     public void keyPressed(KeyEvent keyevent) {
389         char c = keyevent.getKeyChar();
390         switch(c) {
391             case '+': scale += 0.1; clear(); paint(getGraphics()); return;
392             case '-': scale -= 0.1; clear(); paint(getGraphics()); return;
393         }
394     }
395
396 }