ML509: use urjtag's fjmem block as the debug controller (JtagConnectedFpga).
authorAdam Megacz <megacz@cs.berkeley.edu>
Mon, 18 Jan 2010 22:34:37 +0000 (14:34 -0800)
committerAdam Megacz <megacz@cs.berkeley.edu>
Mon, 18 Jan 2010 22:36:03 +0000 (14:36 -0800)
Makefile
misc/jtag-commands [deleted file]
ships/Debug.ship
src/edu/berkeley/fleet/fpga/JtagConnectedFpga.java [new file with mode: 0644]
src/edu/berkeley/fleet/fpga/ML509.java

index 4b9fb4e..3f393ba 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -134,7 +134,6 @@ upload: fleet.jar build/${impl}/main.bit
        chmod +x misc/program.sh
 ifneq ($(impl),bee2)
        ${rsync} ./ root@${runhost}:fleet/
-       ssh -t root@${runhost} 'cd fleet; jtag < misc/jtag-commands'
 endif
 
 build/${impl}/main.bit: $(java_files) $(ship_files)
diff --git a/misc/jtag-commands b/misc/jtag-commands
deleted file mode 100644 (file)
index 954f025..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-##############################################################################
-#cable Signalyzer
-#bsdl path misc/bsdl
-#detect
-
-##############################################################################
-cable gnICE+
-frequency 15000000
-addpart 10
-addpart 8
-addpart 8
-addpart 16
-addpart 16
-part 1
-instruction BYPASS
-part 2
-instruction BYPASS
-part 3
-instruction BYPASS
-part 4
-instruction BYPASS
-
-##############################################################################
-# for both
-part 0
-svf build/ml509.small/main.svf stop progress
-
-
-# fjmem commands
-#register IR 10
-#initbus fjmem opcode=1111000010
index 3069a99..e696d1c 100644 (file)
@@ -209,7 +209,7 @@ end
        data_to_host_write_enable <= 0;
        if (force_reset == 1) begin
          force_reset <= 0;
-         data_to_host_write_enable <= 1;
+         //data_to_host_write_enable <= 1;
          credits = 0;
          count_in  <= 0;
          count_out <= 0;
@@ -330,11 +330,12 @@ NET CCLK                LOC = C14  | IOSTANDARD = LVCMOS25;
                 .SEL(sel), 
                 .DRCK(drck));
 
-  wire [9:0] din;
   wire [9:0] dout;
   reg  [9:0] dout_r;
+  reg  [9:0] din;
+  wire write_o;
+  wire read_o;
   wire strobe_o;
-  assign din = 10'h71;
   wire ack_i;
   assign ack_i = 1;
 
@@ -350,20 +351,23 @@ NET CCLK                LOC = C14  | IOSTANDARD = LVCMOS25;
       .res_i    (rst),
 
       .strobe_o (strobe_o),
-      .read_o   (),
+      .read_o   (read_o),
       .write_o  (write_o),
       .ack_i    (ack_i),
       .cs_o     (),
       .addr_o   (),
-      .din_i    (dout_r),
+      .din_i    (din),
       .dout_o   (dout)
     );
 
-  always @(posedge clk) begin
-    if (strobe_o)
-      dout_r <= dout;
-  end
+  wire strobe_write;
+  assign strobe_write = strobe_o & write_o;
 
+  wire strobe_read;
+  assign strobe_read = strobe_o & read_o;
+
+  reg strobe_write_was_high;
+  initial strobe_write_was_high = 0;
 
   wire break_i;
   reg send_k;
@@ -383,6 +387,8 @@ NET CCLK                LOC = C14  | IOSTANDARD = LVCMOS25;
   reg        data_to_fleet_read_enable;
   reg  [7:0] force_reset;
 
+  reg        data_to_host_full_bit;
+  
   assign clk_out = clk_pin;
 
   wire sio_ce;
@@ -427,11 +433,17 @@ NET CCLK                LOC = C14  | IOSTANDARD = LVCMOS25;
        count_out   <= 0;
        force_reset <= 0;
        credits      = 0;
+       data_to_host_full_bit <= 0;
        `reset
      end else begin
 
        `cleanup
 
+       if (strobe_read) begin
+         din <= { 1'b0, data_to_host_full_bit, data_to_host };
+         data_to_host_full_bit <= 0;
+       end
+
        // fpga -> host
        data_to_host_write_enable <= 0;
        if (force_reset == 1) begin
@@ -443,20 +455,49 @@ NET CCLK                LOC = C14  | IOSTANDARD = LVCMOS25;
          `reset
        end else if (force_reset != 0) begin
          force_reset <= force_reset-1;
-       end else if (count_out==0 && `in_full) begin
+       end else if (count_out==0 && `in_full && data_to_host_full_bit==0) begin
          `drain_in
          data_to_host_full_word <= in_d;
          count_out <= 8;
-       end else if (count_out!=0 && !data_to_host_full && !data_to_host_write_enable && credits!=0) begin
+       end else if (count_out!=0 && !data_to_host_full && !data_to_host_write_enable && credits!=0 && data_to_host_full_bit==0) begin
          data_to_host <= { 2'b0, data_to_host_full_word[5:0] };
          data_to_host_full_word <= (data_to_host_full_word >> 6);
-         data_to_host_write_enable <= 1;
+         data_to_host_full_bit <= 1;
          count_out <= count_out-1;
          credits = credits - 1;
        end
 
        // host -> fpga
        data_to_fleet_read_enable <= 0;
+
+       if (!strobe_write && strobe_write_was_high) begin
+          strobe_write_was_high <= 0;
+
+       end else if (strobe_write && !strobe_write_was_high && (force_reset == 0)) begin
+         strobe_write_was_high <= 1;
+           // command 0: data
+         if (dout[7:6] == 2'b00 && `out_empty) begin
+           out_d <= { out_d[43:0], dout[5:0] };
+           if (count_in==9) begin
+             count_in <= 0;
+             `fill_out
+           end else begin
+             count_in <= count_in+1;
+           end
+
+           // command 1: flow control credit
+         end else if (dout[7:6] == 2'b01) begin
+           credits = credits + dout[5:0];
+
+           // command 3: reset (and echo back reset code)
+         end else if (dout[7:6] == 2'b11) begin
+           data_to_host <= dout[7:0];
+           data_to_host_full_bit <= 1;
+           force_reset <= 255;
+
+         end 
+
+       end else
        if (!data_to_fleet_empty && !data_to_fleet_read_enable) begin
 
          // Note: if the switch fabric refuses to accept a new item,
diff --git a/src/edu/berkeley/fleet/fpga/JtagConnectedFpga.java b/src/edu/berkeley/fleet/fpga/JtagConnectedFpga.java
new file mode 100644 (file)
index 0000000..7d14117
--- /dev/null
@@ -0,0 +1,240 @@
+package edu.berkeley.fleet.fpga;
+import edu.berkeley.fleet.fpga.*;
+import edu.berkeley.fleet.api.*;
+import java.io.*;
+import static edu.berkeley.fleet.util.BitManipulations.*;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.sbp.util.ANSI;
+import java.io.*;
+import java.net.*;
+import edu.berkeley.fleet.util.*;
+import java.util.*;
+import java.util.concurrent.*;
+import static edu.berkeley.fleet.two.FleetTwoFleet.*;
+import static edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.api.Predicate.*;
+import static edu.berkeley.fleet.api.Instruction.*;
+import com.sun.electric.tool.io.ExecProcess;
+
+public abstract class JtagConnectedFpga extends Fpga {
+
+    protected JtagConnectedFpga() throws IOException {
+    }
+
+    public FleetProcess run(Instruction[] instructions) {
+        try {
+            return new JtagConnectedFpgaClient(this, "none", instructions);
+        } catch (Exception e) { throw new RuntimeException(e); }
+    }
+
+    public static class JtagConnectedFpgaClient extends FleetProcess {
+
+        private Fpga fpga;
+        private BlockingQueue<BitVector> queue = new LinkedBlockingQueue<BitVector>();
+        public PrintWriter pwjtag;
+        private Semaphore semaphore = new Semaphore(0);
+        private Semaphore peekSemaphore = new Semaphore(0);
+
+        public Fleet getFleet() { return fpga; }
+        public Dock getDebugInputDock() { return fpga.getShip("Debug",0).getDock("in"); }
+        public BitVector recvWord() {
+            if (isTerminated()) throw new RuntimeException("this fleet has been terminated");
+            try {
+                return queue.take();
+            } catch (InterruptedException e) { throw new RuntimeException(e); }
+        }
+        protected void _terminate() {
+            try {
+                PrintWriter pw = pwjtag;
+                if (pw==null) return;
+                synchronized(pw) {
+                    pw.close();
+                    pwjtag = null;
+                }
+            } catch (Exception e) { e.printStackTrace(); }
+        }
+
+        public void flush() {
+            try {
+                PrintWriter pw = pwjtag;
+                if (pw==null) return;
+                synchronized(pw) {
+                    pw.flush();
+                }
+            } catch (Exception e) { e.printStackTrace(); }
+        }
+
+        public void masterClear() {
+            try {
+                PrintWriter pw = pwjtag;
+                if (pw==null) return;
+                synchronized(pw) {
+                    pw.println("poke 0 "+((3<<6) | 27));
+                    pw.flush();
+                }
+
+                // it's important to acquire the semaphore first, then clear the queue
+                semaphore.acquire();
+                queue.clear();
+            } catch (Exception e) { throw new RuntimeException(); }
+        }
+
+
+        public JtagConnectedFpgaClient(Fpga fpga, String bitfile, Instruction[] instructions) throws Exception {
+            this.fpga = fpga;
+
+            ExecProcess jtag = new ExecProcess(new String[] { "ssh", "root@goliath.megacz.com", "cd ~/fleet; jtag" }, null);
+            jtag.redirectStderr(System.err);
+            jtag.start();
+
+            pwjtag = new PrintWriter(new OutputStreamWriter(jtag.getStdin()));
+            final BufferedReader pwjtagin = new BufferedReader(new InputStreamReader(jtag.getStdout()));
+            new Thread() {
+                public void run() {
+                    try {
+                        int i=0;
+                        long result = 0;
+                        while(true) {
+                            String sin = pwjtagin.readLine();
+                            if (sin==null) return;
+                            if (sin.indexOf("URJ_BUS_READ(")==-1) {
+                                if (sin.startsWith("Parsing  "))
+                                    System.err.print("\r"+sin+ANSI.clreol());
+                                else
+                                    System.err.println(sin);
+                                continue;
+                            }
+                            sin = sin.substring(sin.indexOf("URJ_BUS_READ("));
+                            sin = sin.substring(sin.indexOf(" = 0x"));
+                            sin = sin.substring(" = 0x".length());
+                            sin = sin.substring(0, sin.indexOf(' '));
+                            int val = Integer.parseInt(sin, 16);
+                            if (val < 256) continue;
+                            val = val & 0xff;
+                            //System.err.println("READ: 0x"+Integer.toString(val & 0xff, 16));
+                            if ((val & (3<<6)) == 0) {
+                                PrintWriter pw = pwjtag;
+                                if (pw==null) return;
+                                synchronized(pw) {
+                                    pw.println("poke 0 "+((1<<6) | 1));
+                                }
+                                peekSemaphore.release(3);
+                                result |= ((val & 0xffL) << (i * 6L));
+                                i++;
+                                if (i==8) {
+                                    BitVector bs = new BitVector(37);
+                                    for(int j=0; j<37; j++)
+                                        bs.set(j, ((result >> j) & 1L)!=0);
+                                    queue.put(bs);
+                                    i = 0;
+                                    result = 0;
+                                }
+                            } else {
+                                i = 0;
+                                PrintWriter pw = pwjtag;
+                                if (pw==null) return;
+                                synchronized(pw) {
+                                    pw.println("poke 0 "+((1<<6) | 15));
+                                    pw.flush();
+                                }
+                                peekSemaphore.release(3);
+                                semaphore.release();
+                            }
+
+                        }
+                    } catch (Exception e) { throw new RuntimeException(e); }
+                }
+            }.start();
+
+            PrintWriter pw = pwjtag;
+            //pw.println("cable Signalyzer");
+            pw.println("cable gnICE+");
+            pw.println("frequency 15000000");
+            
+            //pw.println("bsdl path misc/bsdl");
+            //pw.println("detect");
+            pw.println("addpart 10");
+            pw.println("addpart 8");
+            pw.println("addpart 8");
+            pw.println("addpart 16");
+            pw.println("addpart 16");
+            pw.println("part 1");
+            pw.println("instruction BYPASS");
+            pw.println("part 2");
+            pw.println("instruction BYPASS");
+            pw.println("part 3");
+            pw.println("instruction BYPASS");
+            pw.println("part 4");
+            pw.println("instruction BYPASS");
+            
+            pw.println("part 0");
+            pw.println("svf /root/fleet/build/ml509.small/main.svf stop progress");
+            pw.flush();
+            
+            //# fjmem commands
+            pw.println("register IR 10");
+            pw.println("initbus fjmem opcode=1111000010");
+            pw.flush();
+
+            System.err.println("done programming.");
+
+            // the thread that periodically sends a peek request
+            new Thread() {
+                public void run() {
+                    try {
+                        while(true) {
+                            peekSemaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
+                            int avail = peekSemaphore.availablePermits();
+                            PrintWriter pw = pwjtag;
+                            if (pw==null) return;
+                            synchronized(pw) {
+                                pw.println("peek 0");
+                                if (avail==0) pw.flush();
+                            }
+                        }
+                    } catch (Exception e) { throw new RuntimeException(e); }
+                }
+            }.start();
+
+            masterClear();
+            if (instructions!=null) {
+                for(Instruction inst : instructions) sendInstruction(inst);
+                flush();
+            }
+        }
+
+        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 = signal==null ? fpga.PACKET_SIGNAL.setval(out, 0) : fpga.PACKET_SIGNAL.setval(out, signal);
+                out = fpga.PACKET_DEST.setval(out, ((FpgaPath)dispatchFrom.getPath(d, null)).toLong());
+                synchronized(this) {
+                    for(int i=9; i>=0; i--)
+                        synchronized(pwjtag) {
+                            pwjtag.println("poke 0 "+(BitManipulations.getIntField(i*6+5, i*6, out)&0xff));
+                            //pwjtag.flush();
+                        }
+                }
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+        public void sendInstruction(Instruction inst) {
+            Dock dispatchFrom = fpga.debugShip.getDock("in");
+            sendWord(inst.dock.getInstructionDestination(),
+                     new BitVector(fpga.getWordWidth()).set(fpga.writeInstruction(inst, dispatchFrom)));
+        }
+
+        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); }
+    }
+}
+
index 0c6fa5f..82c3049 100644 (file)
@@ -3,7 +3,7 @@ import edu.berkeley.fleet.fpga.*;
 import edu.berkeley.fleet.api.*;
 import java.io.*;
 
-public abstract class ML509 extends Fpga {
+public abstract class ML509 extends JtagConnectedFpga {
 
     public ML509() throws IOException {
         createShip("Timer");