major overhaul of FPGA code to support both ML509 and Bee2 at the same time
[fleet.git] / src / edu / berkeley / fleet / fpga / Client.java
index fb65e43..e84b7c4 100644 (file)
@@ -17,13 +17,9 @@ public class Client extends FleetProcess {
 
     private Socket s;
     private BlockingQueue<BitVector> queue = new LinkedBlockingQueue<BitVector>();
+    private Fpga fpga;
+    private OutputStream os = null;
 
-    public static long signExtend(long val) {
-        if ((val & (1L << 36)) != 0)
-            val = val | (0xffffffffffffffffL << 36);
-        return val;
-    }
-                                    
     public Fleet getFleet() { return fpga; }
     public Dock getDebugInputDock() {
         return fpga.getShip("Debug",0).getDock("in");
@@ -38,78 +34,147 @@ public class Client extends FleetProcess {
 
     protected void _terminate() {
         try {
-            s.close();
+            if (s!=null) s.close();
         } catch (Exception e) { e.printStackTrace(); }
     }
 
-    private Fpga fpga;
-    private DataOutputStream dos = null;
-
     public void flush() {
         try {
-            dos.flush();
+            os.flush();
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
     }
 
+    private static class Gobbler extends Thread {
+        private final BufferedReader br;
+        public Gobbler(InputStream is) {
+            this.br = new BufferedReader(new InputStreamReader(is));
+        }
+        public void run() {
+            try {
+                for(String s = br.readLine(); s!=null; s=br.readLine())
+                    System.err.println("  > " + s);
+            } catch (Exception e) { throw new RuntimeException(e); }
+        }
+    }
+
+    private boolean needmc = false;
+    public void masterClear() {
+        queue.clear();
+
+        needmc = true;
+        // goofy reset sequence
+        new Thread() {
+            public void run() {
+                try {
+                    for(int i=0; i<255; i++) os.write( (3<<6) | 0);
+                    for(int i=0; i<60; i++) os.write( (3<<6) | i);
+                    os.flush();
+                } catch (Exception e) { throw new RuntimeException(e); }
+            }
+        }.start();
+        try {
+            while(needmc) Thread.sleep(100);
+        } catch (Exception e) { throw new RuntimeException(e); }
+    }
+
     public Client(Fpga fpga, String bitfile, Instruction[] instructions) throws Exception {
         this.fpga = fpga;
 
-        s = new Socket(InetAddress.getByName("goliath.megacz.com"), 3133);
-        //s = new Socket(InetAddress.getByName("localhost"), 3133);
-        OutputStream os = new BufferedOutputStream(s.getOutputStream());
-        PrintWriter pw = new PrintWriter(new OutputStreamWriter(os));
-        pw.print(Server.pass_string+" "+bitfile+"\n");
-        pw.flush();
+        final InputStream xis;
+
+        if (fpga instanceof Bee2) {
+            int idx = 1;
+            String host = "bee2";
+            Process proc;
+            int res;
+            
+            System.err.println("== rsyncing");
+            proc = Runtime.getRuntime().exec("rsync -are ssh --progress --verbose build/bee2/main.bit misc/bicat.c "+host+":");
+            new Gobbler(proc.getInputStream()).start();
+            res = proc.waitFor();
+            if (res != 0) throw new RuntimeException("nonzero exit code");
 
-        this.dos = new DataOutputStream(os);
-        for(Instruction inst : instructions)
-            sendInstruction(inst);
-        flush();
+            System.err.println("== (un)programming fpga " + idx);
+            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);
+            this.os = proc.getOutputStream();
+            xis = new BufferedInputStream(proc.getInputStream());
+        } else {
+            s = new Socket(InetAddress.getByName("goliath.megacz.com"), 3133);
+            this.os = new BufferedOutputStream(s.getOutputStream());
+            xis = new BufferedInputStream(s.getInputStream());
+            PrintWriter pw = new PrintWriter(new OutputStreamWriter(os));
+            pw.print(Server.pass_string+" "+bitfile+"\n");
+            pw.flush();
+        }
+        final InputStream is = xis;
 
-        final InputStream is = new BufferedInputStream(s.getInputStream());
+        needmc = true;
         Thread t = new Thread() {
-            public void run() {
-                try {
-                    while(true) {
-                        long result = 0;
-                        int val = 0;
-                        for(int i=0; i<8; i++) {
-                            val = is.read();
-                            if (val==-1) break;
-                            long val2 = (val & 0xffL);
-                            val2 = val2 << (i * 6);
-                            result |= val2;
+                public void run() {
+                    try {
+                        while(needmc) {
+                            int k = 1;
+                            while(k<60) {
+                                int i = is.read();
+                                if ( (i & (3<<6)) != (3<<6) ) { k=1; continue; }
+                                i = i & ~((-1)<<6);
+                                if (i==k) k++; else k = 1;
+                            }
+        
+                            // initial flow-control credits
+                            os.write( (1<<6) | 15);
+                            os.flush();
+                            needmc = false;
+                            OUTER: while(true) {
+                                long result = 0;
+                                if (needmc) break;
+                                for(int i=0; i<8; i++) {
+                                    int val = is.read();
+                                    if (needmc) break OUTER;
+                                    if (val==-1) break OUTER;
+                                    result |= ((val & 0xffL) << (i * 6L));
+                                }
+                                BitVector bs = new BitVector(37);
+                                for(int i=0; i<37; i++)
+                                    bs.set(i, ((result >> i) & 1L)!=0);
+                                queue.put(bs);
+                            }
                         }
-                        if (val==-1) break;
-                        BitVector bs = new BitVector(37);
-                        for(int i=0; i<37; i++)
-                            bs.set(i, ((result >> i) & 1L)!=0);
-                        queue.put(bs);
-                    }
-                } catch (SocketException e) {
-                } catch (Exception e) { throw new RuntimeException(e);
-                } finally { terminate(); }
-            }
+                    } catch (SocketException e) {
+                    } catch (Exception e) { throw new RuntimeException(e);
+                    } finally { terminate(); }
+                }
             };
         t.setDaemon(true);
         t.start();
+        masterClear();
+
+        if (instructions!=null) {
+            for(Instruction inst : instructions) sendInstruction(inst);
+            flush();
+        }
     }
 
-    public void sendToken(Destination d) { sendWord(d, new BitVector(fpga.getWordWidth()), true); }
-    public void sendWord(Destination d, BitVector word) { sendWord(d, word, false); }
-    private void sendWord(Destination d, BitVector word, boolean token) {
+    public void sendToken(Destination d) { sendWord(d, new BitVector(fpga.getWordWidth()), null, true); }
+    public void sendWord(Destination d, BitVector word) { sendWord(d, word, null, false); }
+    public void sendWord(Destination d, BitVector word, BitVector signal) { sendWord(d, word, signal, false); }
+    private void sendWord(Destination d, BitVector word, BitVector signal, boolean token) {
         try {
             Dock dispatchFrom = fpga.debugShip.getDock("in");
             long out = 0;
             out = fpga.PACKET_DATA.setval(out, word);
             out = fpga.PACKET_TOKEN.setval(out, token ? 1 : 0);
-            out = fpga.PACKET_SIGNAL.setval(out, 0);
+            if (signal==null)
+                out = fpga.PACKET_SIGNAL.setval(out, 0);
+            else 
+                out = fpga.PACKET_SIGNAL.setval(out, signal);
             out = fpga.PACKET_DEST.setval(out, ((FpgaPath)dispatchFrom.getPath(d, null)).toLong());
             synchronized(this) {
-                for(int i=7; i>=0; i--)
-                    dos.write(BitManipulations.getIntField(i*8+7, i*8, out));
+                for(int i=9; i>=0; i--)
+                    os.write(BitManipulations.getIntField(i*6+5, i*6, out));
+                os.flush();
             }
         } catch (Exception e) {
             throw new RuntimeException(e);
@@ -121,8 +186,8 @@ public class Client extends FleetProcess {
                  new BitVector(fpga.getWordWidth()).set(fpga.writeInstruction(inst, dispatchFrom)));
     }
 
-    private static Move discard(Dock dock)           { return new Move(dock, false, IgnoreFlagD, false, null, false, true,  false, false, false, false); }
-    private static Move deliver(Dock dock)           { return new Move(dock, false, IgnoreFlagD, false, null, false, false, false, false, true,  false); }
-    private static Move wait(Dock dock)              { return new Move(dock, false, IgnoreFlagD, false, null, true,  false, false, false, false, false); }
-    private static Move sendto(Dock dock, Path path) { return new Move(dock, false, IgnoreFlagD, false, path, false, false, false, false, true,  false); }
+    private static Move discard(Dock dock)           { return new Move(dock, IgnoreFlagD, false, null, false, true,  false, false, false, false); }
+    private static Move deliver(Dock dock)           { return new Move(dock, IgnoreFlagD, false, null, false, false, false, false, true,  false); }
+    private static Move wait(Dock dock)              { return new Move(dock, IgnoreFlagD, false, null, true,  false, false, false, false, false); }
+    private static Move sendto(Dock dock, Path path) { return new Move(dock, IgnoreFlagD, false, path, false, false, false, false, true,  false); }
 }