From: Adam Megacz Date: Mon, 18 Jan 2010 22:34:37 +0000 (-0800) Subject: ML509: use urjtag's fjmem block as the debug controller (JtagConnectedFpga). X-Git-Url: http://git.megacz.com/?p=fleet.git;a=commitdiff_plain;h=9ac0147c83d09ac097acdef331823b8edb9e649d ML509: use urjtag's fjmem block as the debug controller (JtagConnectedFpga). --- diff --git a/Makefile b/Makefile index 4b9fb4e..3f393ba 100644 --- 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 index 954f025..0000000 --- a/misc/jtag-commands +++ /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 diff --git a/ships/Debug.ship b/ships/Debug.ship index 3069a99..e696d1c 100644 --- a/ships/Debug.ship +++ b/ships/Debug.ship @@ -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 index 0000000..7d14117 --- /dev/null +++ b/src/edu/berkeley/fleet/fpga/JtagConnectedFpga.java @@ -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 queue = new LinkedBlockingQueue(); + 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); } + } +} + diff --git a/src/edu/berkeley/fleet/fpga/ML509.java b/src/edu/berkeley/fleet/fpga/ML509.java index 0c6fa5f..82c3049 100644 --- a/src/edu/berkeley/fleet/fpga/ML509.java +++ b/src/edu/berkeley/fleet/fpga/ML509.java @@ -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");