+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); }
+ }
+}
+