ML509: use urjtag's fjmem block as the debug controller (JtagConnectedFpga).
[fleet.git] / src / edu / berkeley / fleet / fpga / JtagConnectedFpga.java
1 package edu.berkeley.fleet.fpga;
2 import edu.berkeley.fleet.fpga.*;
3 import edu.berkeley.fleet.api.*;
4 import java.io.*;
5 import static edu.berkeley.fleet.util.BitManipulations.*;
6 import edu.berkeley.fleet.api.*;
7 import edu.berkeley.sbp.util.ANSI;
8 import java.io.*;
9 import java.net.*;
10 import edu.berkeley.fleet.util.*;
11 import java.util.*;
12 import java.util.concurrent.*;
13 import static edu.berkeley.fleet.two.FleetTwoFleet.*;
14 import static edu.berkeley.fleet.api.Instruction.Set.*;
15 import static edu.berkeley.fleet.api.Predicate.*;
16 import static edu.berkeley.fleet.api.Instruction.*;
17 import com.sun.electric.tool.io.ExecProcess;
18
19 public abstract class JtagConnectedFpga extends Fpga {
20
21     protected JtagConnectedFpga() throws IOException {
22     }
23
24     public FleetProcess run(Instruction[] instructions) {
25         try {
26             return new JtagConnectedFpgaClient(this, "none", instructions);
27         } catch (Exception e) { throw new RuntimeException(e); }
28     }
29
30     public static class JtagConnectedFpgaClient extends FleetProcess {
31
32         private Fpga fpga;
33         private BlockingQueue<BitVector> queue = new LinkedBlockingQueue<BitVector>();
34         public PrintWriter pwjtag;
35         private Semaphore semaphore = new Semaphore(0);
36         private Semaphore peekSemaphore = new Semaphore(0);
37
38         public Fleet getFleet() { return fpga; }
39         public Dock getDebugInputDock() { return fpga.getShip("Debug",0).getDock("in"); }
40         public BitVector recvWord() {
41             if (isTerminated()) throw new RuntimeException("this fleet has been terminated");
42             try {
43                 return queue.take();
44             } catch (InterruptedException e) { throw new RuntimeException(e); }
45         }
46         protected void _terminate() {
47             try {
48                 PrintWriter pw = pwjtag;
49                 if (pw==null) return;
50                 synchronized(pw) {
51                     pw.close();
52                     pwjtag = null;
53                 }
54             } catch (Exception e) { e.printStackTrace(); }
55         }
56
57         public void flush() {
58             try {
59                 PrintWriter pw = pwjtag;
60                 if (pw==null) return;
61                 synchronized(pw) {
62                     pw.flush();
63                 }
64             } catch (Exception e) { e.printStackTrace(); }
65         }
66
67         public void masterClear() {
68             try {
69                 PrintWriter pw = pwjtag;
70                 if (pw==null) return;
71                 synchronized(pw) {
72                     pw.println("poke 0 "+((3<<6) | 27));
73                     pw.flush();
74                 }
75
76                 // it's important to acquire the semaphore first, then clear the queue
77                 semaphore.acquire();
78                 queue.clear();
79             } catch (Exception e) { throw new RuntimeException(); }
80         }
81
82
83         public JtagConnectedFpgaClient(Fpga fpga, String bitfile, Instruction[] instructions) throws Exception {
84             this.fpga = fpga;
85
86             ExecProcess jtag = new ExecProcess(new String[] { "ssh", "root@goliath.megacz.com", "cd ~/fleet; jtag" }, null);
87             jtag.redirectStderr(System.err);
88             jtag.start();
89
90             pwjtag = new PrintWriter(new OutputStreamWriter(jtag.getStdin()));
91             final BufferedReader pwjtagin = new BufferedReader(new InputStreamReader(jtag.getStdout()));
92             new Thread() {
93                 public void run() {
94                     try {
95                         int i=0;
96                         long result = 0;
97                         while(true) {
98                             String sin = pwjtagin.readLine();
99                             if (sin==null) return;
100                             if (sin.indexOf("URJ_BUS_READ(")==-1) {
101                                 if (sin.startsWith("Parsing  "))
102                                     System.err.print("\r"+sin+ANSI.clreol());
103                                 else
104                                     System.err.println(sin);
105                                 continue;
106                             }
107                             sin = sin.substring(sin.indexOf("URJ_BUS_READ("));
108                             sin = sin.substring(sin.indexOf(" = 0x"));
109                             sin = sin.substring(" = 0x".length());
110                             sin = sin.substring(0, sin.indexOf(' '));
111                             int val = Integer.parseInt(sin, 16);
112                             if (val < 256) continue;
113                             val = val & 0xff;
114                             //System.err.println("READ: 0x"+Integer.toString(val & 0xff, 16));
115                             if ((val & (3<<6)) == 0) {
116                                 PrintWriter pw = pwjtag;
117                                 if (pw==null) return;
118                                 synchronized(pw) {
119                                     pw.println("poke 0 "+((1<<6) | 1));
120                                 }
121                                 peekSemaphore.release(3);
122                                 result |= ((val & 0xffL) << (i * 6L));
123                                 i++;
124                                 if (i==8) {
125                                     BitVector bs = new BitVector(37);
126                                     for(int j=0; j<37; j++)
127                                         bs.set(j, ((result >> j) & 1L)!=0);
128                                     queue.put(bs);
129                                     i = 0;
130                                     result = 0;
131                                 }
132                             } else {
133                                 i = 0;
134                                 PrintWriter pw = pwjtag;
135                                 if (pw==null) return;
136                                 synchronized(pw) {
137                                     pw.println("poke 0 "+((1<<6) | 15));
138                                     pw.flush();
139                                 }
140                                 peekSemaphore.release(3);
141                                 semaphore.release();
142                             }
143
144                         }
145                     } catch (Exception e) { throw new RuntimeException(e); }
146                 }
147             }.start();
148
149             PrintWriter pw = pwjtag;
150             //pw.println("cable Signalyzer");
151             pw.println("cable gnICE+");
152             pw.println("frequency 15000000");
153             
154             //pw.println("bsdl path misc/bsdl");
155             //pw.println("detect");
156             pw.println("addpart 10");
157             pw.println("addpart 8");
158             pw.println("addpart 8");
159             pw.println("addpart 16");
160             pw.println("addpart 16");
161             pw.println("part 1");
162             pw.println("instruction BYPASS");
163             pw.println("part 2");
164             pw.println("instruction BYPASS");
165             pw.println("part 3");
166             pw.println("instruction BYPASS");
167             pw.println("part 4");
168             pw.println("instruction BYPASS");
169             
170             pw.println("part 0");
171             pw.println("svf /root/fleet/build/ml509.small/main.svf stop progress");
172             pw.flush();
173             
174             //# fjmem commands
175             pw.println("register IR 10");
176             pw.println("initbus fjmem opcode=1111000010");
177             pw.flush();
178
179             System.err.println("done programming.");
180
181             // the thread that periodically sends a peek request
182             new Thread() {
183                 public void run() {
184                     try {
185                         while(true) {
186                             peekSemaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
187                             int avail = peekSemaphore.availablePermits();
188                             PrintWriter pw = pwjtag;
189                             if (pw==null) return;
190                             synchronized(pw) {
191                                 pw.println("peek 0");
192                                 if (avail==0) pw.flush();
193                             }
194                         }
195                     } catch (Exception e) { throw new RuntimeException(e); }
196                 }
197             }.start();
198
199             masterClear();
200             if (instructions!=null) {
201                 for(Instruction inst : instructions) sendInstruction(inst);
202                 flush();
203             }
204         }
205
206         public void sendToken(Destination d) { sendWord(d, new BitVector(fpga.getWordWidth()), null, true); }
207         public void sendWord(Destination d, BitVector word) { sendWord(d, word, null, false); }
208         public void sendWord(Destination d, BitVector word, BitVector signal) { sendWord(d, word, signal, false); }
209         private void sendWord(Destination d, BitVector word, BitVector signal, boolean token) {
210             try {
211                 Dock dispatchFrom = fpga.debugShip.getDock("in");
212                 long out = 0;
213                 out = fpga.PACKET_DATA.setval(out, word);
214                 out = fpga.PACKET_TOKEN.setval(out, token ? 1 : 0);
215                 out = signal==null ? fpga.PACKET_SIGNAL.setval(out, 0) : fpga.PACKET_SIGNAL.setval(out, signal);
216                 out = fpga.PACKET_DEST.setval(out, ((FpgaPath)dispatchFrom.getPath(d, null)).toLong());
217                 synchronized(this) {
218                     for(int i=9; i>=0; i--)
219                         synchronized(pwjtag) {
220                             pwjtag.println("poke 0 "+(BitManipulations.getIntField(i*6+5, i*6, out)&0xff));
221                             //pwjtag.flush();
222                         }
223                 }
224             } catch (Exception e) {
225                 throw new RuntimeException(e);
226             }
227         }
228         public void sendInstruction(Instruction inst) {
229             Dock dispatchFrom = fpga.debugShip.getDock("in");
230             sendWord(inst.dock.getInstructionDestination(),
231                      new BitVector(fpga.getWordWidth()).set(fpga.writeInstruction(inst, dispatchFrom)));
232         }
233
234         private static Move discard(Dock dock)           { return new Move(dock, IgnoreFlagD, false, null, false, true,  false, false, false, false); }
235         private static Move deliver(Dock dock)           { return new Move(dock, IgnoreFlagD, false, null, false, false, false, false, true,  false); }
236         private static Move wait(Dock dock)              { return new Move(dock, IgnoreFlagD, false, null, true,  false, false, false, false, false); }
237         private static Move sendto(Dock dock, Path path) { return new Move(dock, IgnoreFlagD, false, path, false, false, false, false, true,  false); }
238     }
239 }
240