switch MemoryUtil to use MemoryStream
[fleet.git] / src / edu / berkeley / fleet / loops / MemoryUtils.java
1 package edu.berkeley.fleet.loops;
2 import edu.berkeley.fleet.loops.*;
3 import java.util.concurrent.Semaphore;
4 import java.util.*;
5 import java.io.*;
6 import java.net.*;
7 import edu.berkeley.fleet.two.*;
8 import edu.berkeley.fleet.fpga.*;
9 import edu.berkeley.fleet.api.*;
10 import edu.berkeley.fleet.api.Instruction.*;
11 import edu.berkeley.fleet.api.Instruction.Set;
12 import edu.berkeley.fleet.api.Instruction.Set.*;
13 import edu.berkeley.fleet.api.Instruction.Set.SetDest;
14 import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
15 import static edu.berkeley.fleet.api.Predicate.*;
16
17 public class MemoryUtils {
18
19     public static void readMem(FleetProcess fp,
20                                ShipPool pool,
21                                Ship memory,
22                                long offset,
23                                BitVector[] vals) throws RuntimeException {
24         doMem(true, fp, pool, memory, offset, vals);
25     }
26
27     public static void writeMem(FleetProcess fp,
28                                ShipPool pool,
29                                 Ship memory,
30                                 long offset,
31                                 long[] vals) throws RuntimeException {
32         doMem(false, fp, pool, memory, offset, long2bv(fp.getFleet(), vals));
33     }
34
35     public static void writeMem(FleetProcess fp,
36                                ShipPool pool,
37                                 Ship memory,
38                                 long offset,
39                                 BitVector[] vals) throws RuntimeException {
40         doMem(false, fp, pool, memory, offset, vals);
41     }
42
43     /*
44     public static void clearMem(FleetProcess fp,
45                                 Ship memory,
46                                 ShipPool pool,
47                                 long offset,
48                                 long count) throws RuntimeException {
49         if (fp.getFleet() != memory.getFleet())
50             throw new RuntimeException("Fleet mismatch");
51
52         Ship counter1 = pool.allocateShip("Counter");
53         Ship counter2 = pool.allocateShip("Counter");
54         //Ship alu      = pool.allocateShip("Alu");
55
56         final Dock debugIn     = fp.getDebugInputDock();
57
58         CodeBag ctx = new CodeBag(fp.getFleet());
59         LoopFactory lf;
60
61         lf = ctx.loopFactory(counter1.getDock("inOp"), 1);
62         lf.literal(counter1.getDock("inOp").getConstant("COUNT"));
63         lf.deliver();
64
65         lf = ctx.loopFactory(counter1.getDock("in1"), 1);
66         lf.literal(count);
67         lf.deliver();
68
69         lf = ctx.loopFactory(counter1.getDock("in2"), 1);
70         lf.literal(1);
71         lf.deliver();
72
73         lf = ctx.loopFactory(counter1.getDock("out"), 0);
74         lf.abortLoopIfTorpedoPresent();
75         lf.recvToken();
76         lf.collect();
77         lf.send(memory.getDock("inAddrWrite").getDataDestination());
78
79         lf = ctx.loopFactory(memory.getDock("inDataWrite"), 0);
80         lf.literal(0);
81         lf.abortLoopIfTorpedoPresent();
82         lf.deliver();
83
84         lf = ctx.loopFactory(memory.getDock("inAddrWrite"), 1);
85         lf.sendToken(counter1.getDock("out").getDataDestination());
86         lf = lf.makeNext(0);
87         lf.abortLoopIfTorpedoPresent();
88         lf.recvWord();
89         lf.deliver();
90         lf.sendToken(counter1.getDock("out").getDataDestination());
91
92         lf = ctx.loopFactory(memory.getDock("out"), 0);
93         lf.recvToken();
94         lf.recvWord();
95         lf.send(counter2.getDock("in2").getDataDestination());
96
97         lf = ctx.loopFactory(counter2.getDock("inOp"), 1);
98         lf.literal(counter2.getDock("inOp").getConstant("DROP_C1_V2"));
99         lf.deliver();
100         lf.literal(counter2.getDock("inOp").getConstant("PASS_C1_V2"));
101         lf.deliver();
102
103         lf = ctx.loopFactory(counter2.getDock("in2"), 0);
104         lf.recvWord();
105         lf.deliver();
106
107         fp.sendToken(counter1.getDock("out").getInstructionDestination());
108         fp.sendToken(memory.getDock("inDataWrite").getInstructionDestination());
109         fp.sendToken(memory.getDock("inAddrWrite").getInstructionDestination());
110         fp.sendToken(memory.getDock("out").getInstructionDestination());
111         fp.sendToken(counter2.getDock("in2").getInstructionDestination());
112         
113         lf = ctx.loopFactory(counter2.getDock("in1"), 1);
114         lf.literal(count-1);
115         lf.deliver();
116         lf.literal(1);
117         lf.deliver();
118         
119         lf = ctx.loopFactory(counter2.getDock("out"), 1);
120         lf.collect();
121         lf.send(debugIn.getDataDestination());
122
123         pool.releaseShip(counter1);
124         pool.releaseShip(counter2);
125         //pool.releaseShip(alu);
126     }
127     */
128
129     public static void doMem(final boolean read,
130                              final FleetProcess fp,
131                              final ShipPool pool,
132                              final Ship memory,
133                              final long offset,
134                              final BitVector[] vals) {
135
136         try {
137             MemoryOutputStream mos = new MemoryOutputStream(fp, pool, memory, offset, read);
138             for(int i=0; i<vals.length; i++) {
139                 if (read) vals[i] = mos.readWord();
140                 else      mos.writeWord(vals[i]);
141                 int pct = (int)Math.ceil(100.0*((double)(i)/((double)(vals.length-1))));
142                 String status = i + "/" + (vals.length-1) + "= " + pct + "%";
143                 if (read) System.out.print("\rread from address: " + status + ", got " + vals[i] + " = " + vals[i].toLong()+"           ");
144                 else      System.out.print("\rwrote to address: " + status +"           ");
145             }
146             mos.close();
147         } catch (IOException e) {
148             throw new RuntimeException(e);
149         }
150     }
151
152
153     public static class MemoryOutputStream {
154         private FleetProcess fp;
155         private ShipPool pool;
156         private Ship memory;
157         private Ship alu;
158         private long offset;
159         private int inflight;
160         private boolean read;
161
162         public MemoryOutputStream(FleetProcess fp,
163                                   ShipPool pool,
164                                   Ship memory,
165                                   long offset,
166                                   boolean read) throws IOException {
167             this(fp, pool, memory, offset, read, 1);
168         }
169
170         public MemoryOutputStream(FleetProcess fp,
171                                   ShipPool pool,
172                                   Ship memory,
173                                   long offset,
174                                   boolean read,
175                                   int inflight) throws IOException {
176
177             if (fp.getFleet() != memory.getFleet())
178                 throw new RuntimeException("Fleet mismatch");
179             this.fp = fp;
180             this.pool = pool;
181             this.memory = memory;
182             this.offset = offset;
183             this.inflight = inflight;
184             this.read = read;
185             this.alu = pool.allocateShip("Alu");
186             pool.allocateShip(fp.getDebugInputDock().getShip());
187
188             CodeBag ctx = new CodeBag(fp.getFleet());
189             LoopFactory lf;
190
191             // alu.in1: receive and deliver
192             lf = ctx.loopFactory(alu.getDock("in1"), 0);
193             lf.abortLoopIfTorpedoPresent();
194             lf.recvWord();
195             lf.deliver();
196             
197             // alu.in2: receive tokens, deliver 1's
198             lf = ctx.loopFactory(alu.getDock("in2"), 1);
199             lf.literal(1);
200             lf = lf.makeNext(0);
201             lf.abortLoopIfTorpedoPresent();
202             lf.recvToken();
203             lf.deliver();
204             
205             // alu.inOp: receive tokens, deliver ADD's
206             lf = ctx.loopFactory(alu.getDock("inOp"), 1);
207             lf.literal("ADD");
208             lf = lf.makeNext(0);
209             lf.abortLoopIfTorpedoPresent();
210             lf.recvToken();
211             lf.deliver();
212             
213             // alu.out: for each token, provide a word of count-data
214             lf = ctx.loopFactory(alu.getDock("out"), 1);
215             lf.literal(offset);
216             lf = lf.makeNext(0);
217             lf.abortLoopIfTorpedoPresent();
218             lf.recvToken();
219             lf.sendWord(read ? memory.getDock("inAddrRead") : memory.getDock("inAddrWrite"));
220             lf.sendWord(alu.getDock("in1"));
221             lf.sendToken(alu.getDock("in2"));
222             lf.sendToken(alu.getDock("inOp"));
223             lf.collectWord();
224
225             if (read) {
226                 // memory.inAddrRead: just recv and deliver
227                 lf = ctx.loopFactory(memory.getDock("inAddrRead"), 0);
228                 lf.abortLoopIfTorpedoPresent();
229                 lf.recvWord();
230                 lf.deliver();
231
232             } else {
233                 // memory.inDataWrite: recv a word, send a token to alu.out, deliver the word
234                 lf = ctx.loopFactory(memory.getDock("inDataWrite"), 0);
235                 lf.abortLoopIfTorpedoPresent();
236                 lf.recvWord();
237                 lf.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
238                 lf.setPredicate(Predicate.FlagA);
239                 lf.sendToken(fp.getDebugInputDock());
240                 lf.setPredicate(Predicate.NotFlagA);
241                 lf.sendToken(alu.getDock("out"));
242                 lf.deliver();
243                 lf.setPredicate(null);
244                 
245                 // memory.inAddrWrite: just recv and deliver
246                 lf = ctx.loopFactory(memory.getDock("inAddrWrite"), 0);
247                 lf.abortLoopIfTorpedoPresent();
248                 lf.recvWord();
249                 lf.deliver();
250             }
251
252             // memory.out: send a token to debug.in, recv a word, deliver it
253             lf = ctx.loopFactory(memory.getDock("out"), 0);
254             lf.abortLoopIfTorpedoPresent();
255             lf.collectWord();
256             if (read) lf.sendWord(fp.getDebugInputDock());
257             // FIXME: perhaps feed-through here if we get fancy
258
259             if (read) {
260                 lf = ctx.loopFactory(fp.getDebugInputDock(), inflight);
261                 lf.sendToken(alu.getDock("out"));
262                 lf = lf.makeNext(0);
263                 lf.abortLoopIfTorpedoPresent();
264                 lf.recvWord();
265                 lf.deliver();
266                 lf.sendToken(alu.getDock("out"));
267             }
268             ctx.dispatch(fp);
269             fp.flush();
270         }
271
272         public BitVector readWord() {
273             return fp.recvWord();
274         }
275
276         public void writeWord(BitVector bv) {
277             fp.sendWord(memory.getDock("inDataWrite").getDataDestination(), bv, new BitVector(1).set(0));
278         }
279
280         public void close() {
281             CodeBag ctx = new CodeBag(fp.getFleet());
282             LoopFactory lf;
283             lf = ctx.loopFactory(fp.getDebugInputDock(), 1);
284             if (read) {
285                 fp.sendTorpedo(fp.getDebugInputDock());
286                 fp.flush();
287                 for(int i=0; i<inflight; i++) // FIXME: use a loop counter here
288                     lf.recvWord();
289                 lf.deliver();
290             } else {
291                 lf.recvWord();
292                 lf.deliver();
293                 BitVector bv = new BitVector(fp.getFleet().getWordWidth());
294                 fp.sendWord(memory.getDock("inDataWrite").getDataDestination(), bv, new BitVector(1).set(1));
295             }
296             ctx.dispatch(fp);
297             fp.flush();
298             fp.recvWord();
299
300             if (read) {
301                 fp.sendTorpedo(memory.getDock("inAddrRead"));
302             } else {
303                 fp.sendTorpedo(memory.getDock("inAddrWrite"));
304                 fp.sendTorpedo(memory.getDock("inDataWrite"));
305             }
306
307             fp.sendTorpedo(memory.getDock("out"));
308             fp.sendTorpedo(alu.getDock("in1"));
309             fp.sendTorpedo(alu.getDock("in2"));
310             fp.sendTorpedo(alu.getDock("inOp"));
311             fp.sendTorpedo(alu.getDock("out"));
312             fp.flush();
313             
314             pool.releaseShip(alu);
315             pool.releaseShip(fp.getDebugInputDock().getShip());
316         }
317     }
318
319
320     private static BitVector[] long2bv(Fleet fleet, long[] initialValues) {
321         BitVector[] bv = new BitVector[initialValues.length];
322         for(int i=0; i<initialValues.length; i++)
323             bv[i] = new BitVector(fleet.getWordWidth()).set(initialValues[i]);
324         return bv;
325     }
326
327     public static void putMemoryShipInDispatchMode(FleetProcess fp, Ship memoryShip) {
328         CodeBag ctx = new CodeBag(fp.getFleet());
329         LoopFactory lf;
330
331         lf = ctx.loopFactory(memoryShip.getDock("out"), 0);
332         lf.abortLoopIfTorpedoPresent();
333         lf.collectPacket();
334         lf.sendPacket();
335
336         lf = ctx.loopFactory(memoryShip.getDock("inCBD"), 0);
337         lf.abortLoopIfTorpedoPresent();
338         lf.recvWord();
339         lf.deliver();
340
341         ctx.dispatch(fp);
342     }
343
344     public static void removeMemoryShipFromDispatchMode(FleetProcess fp, Ship memoryShip) {
345         fp.sendToken(memoryShip.getDock("out").getInstructionDestination());
346         fp.sendToken(memoryShip.getDock("inCBD").getInstructionDestination());
347     }
348
349     public static void main(String[] s) throws Exception {
350         Random random = new Random(System.currentTimeMillis());
351         Fleet fleet = new Fpga();
352         FleetProcess fp = fleet.run(new Instruction[0]);
353         Ship memory = fleet.getShip("DDR2",0);
354         //Ship memory = fleet.getShip("Dvi",0);
355         //Ship memory = fleet.getShip("Memory",0);
356
357         //int size = (548 * 478) / 2;
358         int size = 2048;
359
360         BitVector[] vals  = new BitVector[size];
361         BitVector[] vals2 = new BitVector[size];
362
363         for(int i=0; i<vals.length; i++) {
364             vals[i] = new BitVector(fleet.getWordWidth()).set(random.nextLong());
365             for(int j=36; j<vals[i].length(); j++)
366                 vals[i].set(j, false);
367             vals[i].set(1, false);
368         }
369
370         ShipPool pool = new ShipPool(fleet);
371         writeMem(fp, pool, memory, 0, vals);
372         readMem(fp, pool, memory, 0, vals2);
373         System.out.println();
374         int fails = 0;
375         for(int i=0; i<vals.length; i++)
376             if (!vals[i].equals(vals2[i])) {
377                 System.out.println("disagreement!  on index " + i + "\n  expected="+vals[i]+"\n       got="+vals2[i]);
378                 fails++;
379             }
380         System.out.println("done! ("+fails+" failures)");
381         if (fails>0) System.exit(-1);
382     }
383 }