2a315912e27be73d9ef154e0360a9e5a99760b39
[fleet.git] / src / edu / berkeley / fleet / ir / New.java
1 package edu.berkeley.fleet.ir;
2 import edu.berkeley.fleet.loops.*;
3 import edu.berkeley.fleet.api.*;
4 import edu.berkeley.fleet.api.Instruction.*;
5 import edu.berkeley.fleet.fpga.*;
6 import edu.berkeley.fleet.interpreter.*;
7 import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
8 import edu.berkeley.fleet.api.Instruction.Set;
9 import edu.berkeley.fleet.api.Instruction.Set.SetDest;
10 import edu.berkeley.fleet.api.Instruction.Set.FlagFunction;
11 import static edu.berkeley.fleet.api.Predicate.*;
12 import java.io.*;
13 import java.util.*;
14 import java.net.*;
15
16 public class New {
17
18     public final Fleet fleet;
19     private Context context;
20     public New(Fleet fleet) {
21         this.fleet = fleet;
22         this.context = new Context(fleet);
23     }
24
25     private HashSet<Segment> segments = new HashSet<Segment>();
26     private HashSet<Ship> allocated = new HashSet<Ship>();
27
28     private HashMap<Dock,LoopFactory> loops = new HashMap<Dock,LoopFactory>();
29     private HashSet<LoopFactory> emitLoops = new HashSet<LoopFactory>();
30
31     public LoopFactory getLoopFactory(Dock d) { return getLoopFactory(d, 0); }
32     public LoopFactory getNextLoopFactory(Dock d, int count) {
33         LoopFactory lf = loops.get(d);
34         if (lf!=null) loops.put(d, lf = lf.makeNext(count, d+""));
35         return getLoopFactory(d, count);
36     }
37     public LoopFactory getLoopFactory(Dock d, int count) {
38         LoopFactory lf = loops.get(d);
39         if (lf==null) {
40             loops.put(d, lf = new LoopFactory(context, d, count, d+""));
41             emitLoops.add(lf);
42         }
43         if (lf.count != count) throw new RuntimeException();
44         return lf;
45     }
46
47     Ship allocate(String shipType) {
48         for(Ship ship : fleet)
49             if (shipType.equals(ship.getType()) && !allocated.contains(ship)) {
50                 allocated.add(ship);
51                 return ship;
52             }
53         throw new RuntimeException("no more ships of type " + shipType);
54     }
55
56     public void emit(ArrayList<Instruction> al) {
57         for(Segment s : segments) s.emitPrologue(al);
58         for(Segment s : segments) s.emitInstructions(al);
59         for(LoopFactory lf : emitLoops) lf.emit(al);
60     }
61
62     public abstract class Segment {
63
64         public final int inputWidth;
65         public final int outputWidth;
66         protected Dock[] inputs;
67
68         public Segment(int inputWidth, int outputWidth) {
69             this.inputWidth = inputWidth;
70             this.outputWidth = outputWidth;
71             segments.add(this);
72         }
73
74         /** sets input docks, returns output docks */
75         public final Dock[] setInputs(Dock[] inputs) {
76             if (inputs.length != inputWidth) throw new RuntimeException();
77             this.inputs = inputs;
78             Dock[] ret = _setInputs();
79             if (ret.length != outputWidth) throw new RuntimeException();
80             return ret;
81         }
82
83         public abstract Dock[] _setInputs();
84         public void emitPrologue(ArrayList<Instruction> il) { }
85         public abstract void emitInstructions(ArrayList<Instruction> il);
86     }
87
88     public class Debug extends Segment {
89         Ship debugShip;
90         public Debug() {
91             super(1, 0);
92             debugShip = allocate("Debug");
93         }
94         public Dock[] _setInputs() { return new Dock[0]; }
95         public void emitPrologue(ArrayList<Instruction> il) { }
96         public void emitInstructions(ArrayList<Instruction> il) {
97             LoopFactory lf;
98             lf = new LoopFactory(context, debugShip.getDock("in"), 0, "debug.in");
99             lf.recvWord();
100             lf.deliver();
101         }
102     }
103
104     public class Constant extends Segment {
105         Ship fifoShip = null;
106         public final long constant;
107         public Constant(long constant) {
108             super(0, 1);
109             this.constant = constant;
110         }
111         public Dock[] _setInputs() {
112             if (fifoShip == null) fifoShip = allocate("Fifo");
113             return new Dock[] { fifoShip.getDock("out") };
114         }
115         public void emitPrologue(ArrayList<Instruction> il) {
116             LoopFactory lf;
117             lf = getLoopFactory(fifoShip.getDock("out"), 0);
118             lf.collectWord();
119         }
120         public void emitInstructions(ArrayList<Instruction> il) {
121             LoopFactory lf;
122             lf = getLoopFactory(fifoShip.getDock("in"), 1);
123             lf.literal(constant);
124             lf = getNextLoopFactory(fifoShip.getDock("in"), 0);
125             lf.deliver();
126         }
127     }
128
129     public class Alu extends Segment {
130         Ship alu = null;
131         public final int opcode;
132         public Alu(int opcode) {
133             super((opcode==-1) ? 3 : 2, 1);
134             this.opcode = opcode;
135         }
136         public Dock[] _setInputs() {
137             if (alu == null) alu = allocate("Alu");
138             return new Dock[] { alu.getDock("out") };
139         }
140         public void emitPrologue(ArrayList<Instruction> il) {
141             LoopFactory lf;
142             lf = getLoopFactory(alu.getDock("out"), 0);
143             lf.collectWord();
144         }
145         public void emitInstructions(ArrayList<Instruction> il) {
146             Dock inOp = alu.getDock("inOp");
147
148             if (opcode==-1) {
149                 recvSendTokenDeliver(alu.getDock("inOp"), inputs[2].getDataDestination());
150                 LoopFactory lf;
151                 lf = getLoopFactory(inputs[2], 0);
152                 lf.sendWord(alu.getDock("inOp").getDataDestination());
153                 lf.recvToken();
154             } else {
155                 LoopFactory lf;
156                 lf = getLoopFactory(alu.getDock("inOp"), 1);
157                 lf.literal(opcode);
158                 lf = getNextLoopFactory(alu.getDock("inOp"), 0);
159                 lf.deliver();
160             }
161
162             recvSendTokenDeliver(alu.getDock("in1"), inputs[0].getDataDestination());
163             LoopFactory lf;
164             lf = getLoopFactory(inputs[0], 0);
165             lf.sendWord(alu.getDock("in1").getDataDestination());
166             lf.recvToken();
167
168             recvSendTokenDeliver(alu.getDock("in2"), inputs[1].getDataDestination());
169             lf = getLoopFactory(inputs[1], 0);
170             lf.sendWord(alu.getDock("in2").getDataDestination());
171             lf.recvToken();
172         }
173     }
174
175     public class Counter extends Segment {
176         Ship alu = null;
177         public final long start;
178         public final long incr;
179         public Counter(long start, long incr) {
180             super(0, 1);
181             this.start = start;
182             this.incr = incr;
183         }
184         public Dock[] _setInputs() {
185             if (alu == null) alu = allocate("Alu");
186             return new Dock[] { alu.getDock("out") };
187         }
188         public void emitPrologue(ArrayList<Instruction> il) {
189             LoopFactory lf;
190             lf = getLoopFactory(alu.getDock("out"), 1);
191             lf.literal(start);
192             getNextLoopFactory(alu.getDock("out"), 0);
193         }
194         public void emitInstructions(ArrayList<Instruction> il) {
195             LoopFactory lf;
196             lf = getLoopFactory(alu.getDock("inOp"), 1);
197             lf.literal(2);
198             lf = getNextLoopFactory(alu.getDock("inOp"), 0);
199             lf.deliver();
200
201             lf = getLoopFactory(alu.getDock("in1"), 0);
202             lf.recvWord();
203             lf.deliver();
204
205             lf = getLoopFactory(alu.getDock("in2"), 1);
206             lf.literal(incr);
207             lf = getNextLoopFactory(alu.getDock("in2"), 0);
208             lf.deliver();
209
210             lf = getLoopFactory(alu.getDock("out"), 0);
211             lf.sendWord(alu.getDock("in1").getDataDestination());
212             lf.collectWord();
213         }
214     }
215
216     public class Between extends Segment {
217         Ship alu = null;
218         public final long min;
219         public final long max;
220         public Between(long min, long max) {
221             super(1, 1);
222             this.min = min;
223             this.max = max;
224         }
225         public Dock[] _setInputs() {
226             if (alu == null) alu = allocate("Alu");
227             return new Dock[] { alu.getDock("out") };
228         }
229         public void emitPrologue(ArrayList<Instruction> il) {
230             getLoopFactory(alu.getDock("in1"), 0);
231             getLoopFactory(alu.getDock("in2"), 0);
232
233             LoopFactory lf;
234             lf = getLoopFactory(alu.getDock("out"), 0);
235             lf.collectWord();
236             lf.setFlags(FlagFunction.ZERO.add(FlagC), FlagFunction.ZERO);
237             lf.collectWord();
238             lf.setFlags(FlagFunction.ZERO.add(FlagC).add(FlagA), FlagFunction.ZERO);
239             lf.setPredicate(Predicate.NotFlagA);
240             lf.literal(1);
241             lf.setPredicate(Predicate.FlagA);
242             lf.literal(0);
243             lf.setPredicate(null);
244         }
245
246         public void emitInstructions(ArrayList<Instruction> il) {
247             LoopFactory lf;
248             lf = getLoopFactory(alu.getDock("inOp"), 1);
249             lf.literal(4); // MAX
250             lf = getNextLoopFactory(alu.getDock("inOp"), 0);
251             lf.deliver();
252
253             lf = getLoopFactory(alu.getDock("in1"), 0);
254             lf.recvWord();
255             lf.sendToken(inputs[0].getDataDestination());
256             lf.deliver();
257             lf.literal(max);
258             lf.deliver();
259
260             lf = getLoopFactory(alu.getDock("in2"), 0);
261             lf.literal(min);
262             lf.deliver();
263             lf.recvWord();
264             lf.sendToken(inputs[0].getDataDestination());
265             lf.deliver();
266
267             lf = getLoopFactory(inputs[0], 0);
268             lf.sendWord(alu.getDock("in2").getDataDestination());
269             lf.sendWord(alu.getDock("in1").getDataDestination());
270             lf.recvToken();
271             lf.recvToken();
272         }
273     }
274
275     public class FifoWithInit extends Segment {
276         Ship fifoShip = null;
277         public final long init;
278         public FifoWithInit(long init) {
279             super(1, 1);
280             this.init = init;
281         }
282         public Dock[] _setInputs() {
283             if (fifoShip == null) fifoShip = allocate("Fifo");
284             return new Dock[] { fifoShip.getDock("out") };
285         }
286         public void emitPrologue(ArrayList<Instruction> il) {
287             LoopFactory lf;
288             lf = getLoopFactory(fifoShip.getDock("in"), 1);
289             lf.literal(init);
290             lf.deliver();
291             lf = getNextLoopFactory(fifoShip.getDock("in"), 0);
292
293             lf = getLoopFactory(fifoShip.getDock("out"), 0);
294             lf.collectWord();
295         }
296         public void emitInstructions(ArrayList<Instruction> il) {
297             LoopFactory lf;
298             lf = getLoopFactory(inputs[0], 0);
299             lf.sendWord(fifoShip.getDock("in").getDataDestination());
300             lf.recvToken();
301
302             recvSendTokenDeliver(fifoShip.getDock("in"), inputs[0].getDataDestination());
303         }
304     }
305
306     public class Video extends Segment {
307         Ship videoShip = null;
308         public Video() {
309             super(3, 0);
310         }
311         public Dock[] _setInputs() {
312             if (videoShip == null) videoShip = allocate("Video");
313             return new Dock[0];
314         }
315         public void emitPrologue(ArrayList<Instruction> il) { }
316         public void emitInstructions(ArrayList<Instruction> il) {
317             recvSendTokenDeliver(videoShip.getDock("inX"),    inputs[0].getDataDestination());
318             recvSendTokenDeliver(videoShip.getDock("inY"),    inputs[1].getDataDestination());
319             recvSendTokenDeliver(videoShip.getDock("inData"), inputs[2].getDataDestination());
320
321             LoopFactory lf;
322             lf = getLoopFactory(inputs[0]);
323             lf.sendWord(videoShip.getDock("inX").getDataDestination());
324             lf.recvToken();
325
326             lf = getLoopFactory(inputs[1]);
327             lf.sendWord(videoShip.getDock("inY").getDataDestination());
328             lf.recvToken();
329
330             lf = getLoopFactory(inputs[2]);
331             lf.sendWord(videoShip.getDock("inData").getDataDestination());
332             lf.recvToken();
333         }
334     }
335
336     public static Dock bouncer(New n, int delt, int start, int min, int max) throws Exception {
337         Constant zeroes      = n.new Constant(0);
338         FifoWithInit pos     = n.new FifoWithInit(start);
339         FifoWithInit delta   = n.new FifoWithInit(delt);
340
341         Dock pos_i   = pos._setInputs()[0];
342         Dock delta_i = delta._setInputs()[0];
343
344         Alu negator = n.new Alu(3);
345         Dock zero_minus_delta_i = negator.setInputs(new Dock[] { zeroes.setInputs(new Dock[0])[0], delta_i })[0];
346
347         Between bet = n.new Between(min, max);
348         Dock selector_input = bet.setInputs(new Dock[] { pos_i })[0];
349
350         Alu selector = n.new Alu(-1);
351         Dock selected = selector.setInputs(new Dock[] { zero_minus_delta_i, delta_i, selector_input })[0];
352
353         Alu sum_alu = n.new Alu(2);
354         Dock sum = sum_alu.setInputs(new Dock[] { selected, pos_i })[0];
355
356         Dock pos_out = pos.setInputs(new Dock[] { sum })[0];
357         Dock delta_out = delta.setInputs(new Dock[] { selected })[0];
358         return pos_out;
359     }
360
361     public static void main(String[] s) throws Exception {
362         New n = s[0].equals("fpga")
363             ? new New(new Fpga())
364             : new New(new Interpreter(new String[] {
365                         "Debug",
366                         "Fifo", "Fifo",
367                         "Fifo", "Fifo",
368                         "Fifo", "Fifo",
369                         "Fifo", "Fifo",
370                         "Fifo", "Fifo",
371                         "Fifo", "Fifo",
372                         "Alu", "Alu",
373                         "Alu", "Alu",
374                         "Alu", "Alu",
375                         "Alu", "Alu",
376                         "Alu", "Alu",
377                         "Alu", "Alu",
378                         "Video"
379                     }, false));
380
381         Dock x_pos = bouncer(n, 1, 6, 5, 634);
382         Dock y_pos = bouncer(n, 1, 6, 5, 474);
383         Dock color = n.new Constant(2).setInputs(new Dock[0])[0];
384         //Dock color = n.new Counter(0,1).setInputs(new Dock[0])[0];
385
386         //debug.setInputs(new Dock[] { x_pos });
387         Video vid = n.new Video();
388         vid.setInputs(new Dock[] { x_pos, y_pos, color });
389
390         ArrayList<Instruction> al = new ArrayList<Instruction>();
391         n.emit(al);
392         for(int i=0; i<al.size(); i++) System.out.println(al.get(i));
393         
394         FleetProcess fp = n.fleet.run((Instruction[])al.toArray(new Instruction[0]));
395         System.out.println("launching...");
396         while(true) System.out.println(fp.recvWord().toLong());
397     }
398
399     private void recvSendTokenDeliver(Dock dock, Destination dest) {
400         LoopFactory lf = getLoopFactory(dock);
401         lf.recvWord();
402         lf.sendToken(dest);
403         lf.deliver();
404     }
405 }