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