7f5263b03bdbb9c56bb7187a1b7de4f72d491c2d
[fleet.git] / src / edu / berkeley / fleet / loops / Program.java
1 package edu.berkeley.fleet.loops;
2 import edu.berkeley.fleet.api.*;
3 import java.util.*;
4 import java.net.*;
5 import java.io.*;
6
7 /**
8  *  A program is a collection of CodeBags resident in a particular Memory.
9  */
10 public class Program {
11
12     public final Fleet fleet;
13     public final Ship memoryShip;
14
15     private CodeBag end = null;
16
17     private long leastUnallocatedAddress;
18     private long startAddress;
19
20     private ArrayList<CodeBag> codeBags = new ArrayList<CodeBag>();
21     private ArrayList<Instruction> all_instructions = new ArrayList<Instruction>();
22     
23     public Program(Ship memoryShip) { this(memoryShip, 0); }
24     public Program(Ship memoryShip, long startAddress) {
25         this.fleet = memoryShip.getFleet();
26         this.memoryShip = memoryShip;
27         this.startAddress = startAddress;
28         this.leastUnallocatedAddress = startAddress;
29     }
30
31     public Destination getCBDDestination() {
32         return memoryShip.getDock("inCBD").getDataDestination();
33     }
34
35     public long run(FleetProcess fp, CodeBag run, ShipPool pool) {
36         Ship timer    = pool.allocateShip("Timer");
37         Ship debug    = pool.allocateShip("Debug");
38         Dock debugIn  = debug.getDock("in");
39         
40         LoopFactory lf;
41
42         CodeBag start = new CodeBag(fleet, this);
43         lf = start.loopFactory(timer.getDock("out"), 1);
44         lf.collectWord();
45         lf.sendWord(debugIn.getDataDestination());
46         lf = start.loopFactory(debugIn, 1);
47         lf.recvWord();
48         lf.deliver();
49         lf.recvWord();
50         lf.deliver();
51         start.sendWord(run.getDescriptor(), getCBDDestination());
52
53         CodeBag done  = end;
54         lf = done.loopFactory(timer.getDock("out"), 1);
55         lf.collectWord();
56         lf.sendWord(debugIn.getDataDestination());
57        
58         start.seal();
59         done.seal();
60         
61         install(fp, pool);
62         
63         MemoryUtils.putMemoryShipInDispatchMode(fp, memoryShip);
64         fp.sendWord(getCBDDestination(), start.getDescriptor().getBitVector());
65         fp.flush();
66         long now = System.currentTimeMillis();
67         System.out.println("waiting for timestamps to come back...");
68         BitVector bv1 = fp.recvWord();
69         System.out.println();
70         System.out.println("got start time (bv="+bv1+" = "+bv1.toLong()+")");
71         BitVector bv2 = fp.recvWord();
72         System.out.println("got end time (bv="+bv2+" = "+bv2.toLong()+")");
73         long ret = (bv2.toLong()-bv1.toLong());
74         long simtime = (System.currentTimeMillis()-now)/1000;
75         System.out.println("total run time = " + ret + " gate delays, " + (ret/40) + "ns (simulation time="+simtime+"sec)");
76         MemoryUtils.removeMemoryShipFromDispatchMode(fp, memoryShip);
77
78         return ret;
79     }
80
81     public void dump(String file) {
82         try {
83             FileOutputStream fos = new FileOutputStream(file);
84             PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos));
85             for(int i=0; i<codeBags.size(); i++)
86                 for(Instruction in : codeBags.get(i).emit())
87                     pw.println(in);
88             pw.flush();
89             pw.close();
90         } catch (Exception e) { throw new RuntimeException(e); }
91     }
92
93     public CodeBag getEndProgramCodeBag() {
94         if (end != null) return end;
95         end = new CodeBag(fleet, this);
96         return end;
97     }
98
99     /** the provided pool should be a sibling of the one which holds this Program's instructions */
100     public void install(FleetProcess fp, ShipPool pool) {
101         for(int i=0; i<codeBags.size(); i++)
102             codeBags.get(i).emit();
103         BitVector[] bvs = new BitVector[(int)(leastUnallocatedAddress-startAddress)];
104         for(int i=0; i<bvs.length; i++) {
105             bvs[i] = fleet.encodeInstruction(all_instructions.get(i), memoryShip.getDock("out"));
106         }
107         MemoryUtils.writeMem(fp, pool, memoryShip, startAddress, bvs);
108     }
109
110     BitVector addInstructions(Instruction[] instructions) {
111
112         // CodeBags are "daisy chained" to eliminate any possibility
113         // of cloggage at the inCBD port as a result of more CBD's
114         // being dispatched than the maximum number that fit in the
115         // data fifo at that dock.
116
117         int MAX_BAG_SIZE = (1<<6)-1;
118
119         // FUZZ is an estimate of the number of instructions required
120         // to dispatch a code bag descriptor
121         int FUZZ = 4;
122
123         if (instructions.length <= MAX_BAG_SIZE) {
124             BitVector descriptor = new BitVector(fleet.getWordWidth());
125             descriptor.set( (leastUnallocatedAddress<<6) | instructions.length );
126             leastUnallocatedAddress += instructions.length;
127             for(Instruction i : instructions)
128                 all_instructions.add(i);
129             return descriptor;
130         }
131
132         System.out.println("warning: code bag size is "+instructions.length+
133                            ", which exceeds maximum of "+MAX_BAG_SIZE+
134                            "; breaking into multiple bags");
135         
136         Instruction[] rest = new Instruction[instructions.length - (MAX_BAG_SIZE-FUZZ)];
137         System.arraycopy(instructions, MAX_BAG_SIZE-FUZZ, rest, 0, rest.length);
138         
139         DeferredBitVector restbag = addInstructions(rest);
140         CodeBag ctx = new CodeBag(fleet);
141         ctx.sendWord(restbag, getCBDDestination());
142         Instruction[] fuzz = ctx.emit();
143         if (fuzz.length > FUZZ) throw new RuntimeException("FUZZ="+FUZZ+", fuzz.length="+fuzz.length);
144         Instruction[] self = new Instruction[fuzz.length+MAX_BAG_SIZE-FUZZ];
145         System.arraycopy(instructions, 0, self, 0, MAX_BAG_SIZE-FUZZ);
146         System.arraycopy(fuzz, 0, self, MAX_BAG_SIZE-FUZZ, fuzz.length);
147         return addInstructions(self);
148     }
149
150 }