major overhaul of FPGA code to support both ML509 and Bee2 at the same time
[fleet.git] / src / edu / berkeley / fleet / fpga / Client.java
1 package edu.berkeley.fleet.fpga;
2
3 import static edu.berkeley.fleet.util.BitManipulations.*;
4 import edu.berkeley.fleet.api.*;
5 import java.io.*;
6 import java.net.*;
7 import edu.berkeley.fleet.util.*;
8 import java.util.*;
9 import java.util.concurrent.*;
10 import static edu.berkeley.fleet.two.FleetTwoFleet.*;
11 import static edu.berkeley.fleet.api.Instruction.Set.*;
12 import static edu.berkeley.fleet.api.Predicate.*;
13 import static edu.berkeley.fleet.api.Instruction.*;
14
15
16 public class Client extends FleetProcess {
17
18     private Socket s;
19     private BlockingQueue<BitVector> queue = new LinkedBlockingQueue<BitVector>();
20     private Fpga fpga;
21     private OutputStream os = null;
22
23     public Fleet getFleet() { return fpga; }
24     public Dock getDebugInputDock() {
25         return fpga.getShip("Debug",0).getDock("in");
26     }
27     public BitVector recvWord() {
28         if (isTerminated())
29             throw new RuntimeException("this fleet has been terminated");
30         try {
31             return queue.take();
32         } catch (InterruptedException e) { throw new RuntimeException(e); }
33     }
34
35     protected void _terminate() {
36         try {
37             if (s!=null) s.close();
38         } catch (Exception e) { e.printStackTrace(); }
39     }
40
41     public void flush() {
42         try {
43             os.flush();
44         } catch (Exception e) {
45             throw new RuntimeException(e);
46         }
47     }
48
49     private static class Gobbler extends Thread {
50         private final BufferedReader br;
51         public Gobbler(InputStream is) {
52             this.br = new BufferedReader(new InputStreamReader(is));
53         }
54         public void run() {
55             try {
56                 for(String s = br.readLine(); s!=null; s=br.readLine())
57                     System.err.println("  > " + s);
58             } catch (Exception e) { throw new RuntimeException(e); }
59         }
60     }
61
62     private boolean needmc = false;
63     public void masterClear() {
64         queue.clear();
65
66         needmc = true;
67         // goofy reset sequence
68         new Thread() {
69             public void run() {
70                 try {
71                     for(int i=0; i<255; i++) os.write( (3<<6) | 0);
72                     for(int i=0; i<60; i++) os.write( (3<<6) | i);
73                     os.flush();
74                 } catch (Exception e) { throw new RuntimeException(e); }
75             }
76         }.start();
77         try {
78             while(needmc) Thread.sleep(100);
79         } catch (Exception e) { throw new RuntimeException(e); }
80     }
81
82     public Client(Fpga fpga, String bitfile, Instruction[] instructions) throws Exception {
83         this.fpga = fpga;
84
85         final InputStream xis;
86
87         if (fpga instanceof Bee2) {
88             int idx = 1;
89             String host = "bee2";
90             Process proc;
91             int res;
92             
93             System.err.println("== rsyncing");
94             proc = Runtime.getRuntime().exec("rsync -are ssh --progress --verbose build/bee2/main.bit misc/bicat.c "+host+":");
95             new Gobbler(proc.getInputStream()).start();
96             res = proc.waitFor();
97             if (res != 0) throw new RuntimeException("nonzero exit code");
98
99             System.err.println("== (un)programming fpga " + idx);
100             proc = Runtime.getRuntime().exec("ssh -t "+host+" -- (user_unprogram "+idx+" && gcc -o bicat bicat.c && user_program "+idx+" main.bit &>/dev/null) && ./bicat /dev/selectmap"+idx);
101             this.os = proc.getOutputStream();
102             xis = new BufferedInputStream(proc.getInputStream());
103         } else {
104             s = new Socket(InetAddress.getByName("goliath.megacz.com"), 3133);
105             this.os = new BufferedOutputStream(s.getOutputStream());
106             xis = new BufferedInputStream(s.getInputStream());
107             PrintWriter pw = new PrintWriter(new OutputStreamWriter(os));
108             pw.print(Server.pass_string+" "+bitfile+"\n");
109             pw.flush();
110         }
111         final InputStream is = xis;
112
113         needmc = true;
114         Thread t = new Thread() {
115                 public void run() {
116                     try {
117                         while(needmc) {
118                             int k = 1;
119                             while(k<60) {
120                                 int i = is.read();
121                                 if ( (i & (3<<6)) != (3<<6) ) { k=1; continue; }
122                                 i = i & ~((-1)<<6);
123                                 if (i==k) k++; else k = 1;
124                             }
125         
126                             // initial flow-control credits
127                             os.write( (1<<6) | 15);
128                             os.flush();
129                             needmc = false;
130                             OUTER: while(true) {
131                                 long result = 0;
132                                 if (needmc) break;
133                                 for(int i=0; i<8; i++) {
134                                     int val = is.read();
135                                     if (needmc) break OUTER;
136                                     if (val==-1) break OUTER;
137                                     result |= ((val & 0xffL) << (i * 6L));
138                                 }
139                                 BitVector bs = new BitVector(37);
140                                 for(int i=0; i<37; i++)
141                                     bs.set(i, ((result >> i) & 1L)!=0);
142                                 queue.put(bs);
143                             }
144                         }
145                     } catch (SocketException e) {
146                     } catch (Exception e) { throw new RuntimeException(e);
147                     } finally { terminate(); }
148                 }
149             };
150         t.setDaemon(true);
151         t.start();
152         masterClear();
153
154         if (instructions!=null) {
155             for(Instruction inst : instructions) sendInstruction(inst);
156             flush();
157         }
158     }
159
160     public void sendToken(Destination d) { sendWord(d, new BitVector(fpga.getWordWidth()), null, true); }
161     public void sendWord(Destination d, BitVector word) { sendWord(d, word, null, false); }
162     public void sendWord(Destination d, BitVector word, BitVector signal) { sendWord(d, word, signal, false); }
163     private void sendWord(Destination d, BitVector word, BitVector signal, boolean token) {
164         try {
165             Dock dispatchFrom = fpga.debugShip.getDock("in");
166             long out = 0;
167             out = fpga.PACKET_DATA.setval(out, word);
168             out = fpga.PACKET_TOKEN.setval(out, token ? 1 : 0);
169             if (signal==null)
170                 out = fpga.PACKET_SIGNAL.setval(out, 0);
171             else 
172                 out = fpga.PACKET_SIGNAL.setval(out, signal);
173             out = fpga.PACKET_DEST.setval(out, ((FpgaPath)dispatchFrom.getPath(d, null)).toLong());
174             synchronized(this) {
175                 for(int i=9; i>=0; i--)
176                     os.write(BitManipulations.getIntField(i*6+5, i*6, out));
177                 os.flush();
178             }
179         } catch (Exception e) {
180             throw new RuntimeException(e);
181         }
182     }
183     public void sendInstruction(Instruction inst) {
184         Dock dispatchFrom = fpga.debugShip.getDock("in");
185         sendWord(inst.dock.getInstructionDestination(),
186                  new BitVector(fpga.getWordWidth()).set(fpga.writeInstruction(inst, dispatchFrom)));
187     }
188
189     private static Move discard(Dock dock)           { return new Move(dock, IgnoreFlagD, false, null, false, true,  false, false, false, false); }
190     private static Move deliver(Dock dock)           { return new Move(dock, IgnoreFlagD, false, null, false, false, false, false, true,  false); }
191     private static Move wait(Dock dock)              { return new Move(dock, IgnoreFlagD, false, null, true,  false, false, false, false, false); }
192     private static Move sendto(Dock dock, Path path) { return new Move(dock, IgnoreFlagD, false, path, false, false, false, false, true,  false); }
193 }