1 package dol.visitor.cell;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.OutputStream;
7 import java.io.PrintStream;
8 import java.util.ArrayList;
9 import java.util.StringTokenizer;
10 import java.util.Vector;
12 import dol.datamodel.pn.Channel;
13 import dol.datamodel.pn.Port;
14 import dol.datamodel.pn.Process;
15 import dol.datamodel.pn.ProcessNetwork;
16 import dol.visitor.PNVisitor;
17 import dol.util.CodePrintStream;
20 * This class is a class for a visitor that is used to generate the the OS for
23 * @author lschor, 2009-03-24 * Revision: 2009-03-24: Created
25 public class CellSPEVisitor extends PNVisitor {
33 public CellSPEVisitor(String dir, CellMapping mapping) {
39 * Visit process network.
42 * process network that needs to be rendered
44 public void visitComponent(ProcessNetwork x) {
46 // Create a directory where all SPU's are stored:
47 _spuDir = _dir + _delimiter + "spu";
48 File dir = new File(_spuDir);
51 // Copy the header file to this directory
52 // Some library files must be copied to the main directory
53 (new File(_dir + _delimiter + "lib" + _delimiter + "spu_os.h"))
54 .renameTo(new File(dir.getPath() + _delimiter
57 ArrayList<Vector<Process>> spuList = _mapping.getSPUList();
60 for (Vector<Process> spu : spuList) {
61 createOSLayer(x, spu, i++);
66 } catch (Exception e) {
67 System.out.println("CellSPEVisitor: exception occured: "
74 * Create the makefile for a SPU (so for the layer). Each SPU gets its own
78 * SPU for which the Makefile should be used
80 protected void createMakefileSPU() {
82 // Directory of the process
83 String spuDir = _dir + _delimiter + "spu";
85 // Create the filename for the new wrapper
86 String filename = spuDir + _delimiter + "Makefile";
88 OutputStream file = new FileOutputStream(filename);
90 PrintStream _makefilePS = new CodePrintStream(file);
92 _makefilePS.println("# Makefile for SPU OS");
93 _makefilePS.println("");
94 _makefilePS.println("src := $(wildcard ../lib/spu/*.cpp)");
95 _makefilePS.println("obj = $(src:.cpp=.o)");
96 _makefilePS.println("");
98 // The Makefile must include all o-Files of the processes needed
99 String dependency = "";
101 // Go through all possible processes
102 for (Process p : _mapping.getAllSpuBaseProcess()) {
103 dependency += " .." + _delimiter + "spu_"
104 + p.getBasename() + _delimiter + p.getBasename()
108 _makefilePS.println("all: ${obj}" + dependency);
109 for (int i = 0; i < _mapping.getNrSPE(); i++) {
110 _makefilePS.println("\tspu-g++ -Wall -I .. -I ../lib -o "
111 + "spu_os_" + i + " spu_os_" + i + ".cpp "
112 + "../lib/spu/Fifo.o ../lib/spu/WindowedFifo.o "
113 + "../lib/spu/dolSupport.o "
114 + "../lib/spu/proc_wrapper.o ../lib/spu/common.o "
115 + "../lib/spu/FastCommunication.o" + dependency
116 + " -ftree-vectorize -lm -mtune=cell -O3"
117 + " -fmodulo-sched -funroll-loops "
118 + " -ffast-math -fno-rtti -ffunction-sections"
119 + " -fdata-sections -Wl,--gc-sections");
121 _makefilePS.println();
122 _makefilePS.println("clean: ");
123 for (int i = 0; i < _mapping.getNrSPE(); i++) {
124 _makefilePS.println("\trm spu_os_" + i);
126 _makefilePS.println();
127 _makefilePS.println("%.o : ");
128 _makefilePS.println("\tspu-g++ -c -o $(*D)/$(*F).o "
129 + "$(*D)/$(*F).cpp -I .. -I"
130 + " ../lib -ftree-vectorize -mtune=cell -O3"
131 + " -fmodulo-sched -funroll-loops -ffast-math"
132 + " -fno-rtti -ffunction-sections -fdata-sections");
133 _makefilePS.println();
134 } catch (FileNotFoundException e) {
135 System.out.println("CbeProcessVisitor - Makefile: exception "
136 + "occured: " + e.getMessage());
142 * Creates the OS layer for one SPU
145 * List of all processes a SPU gets
147 * index of the SPU in the SPU list
149 protected void createOSLayer(ProcessNetwork x, Vector<Process> spu,
152 // Create the filename for the new layer
153 String filename = _spuDir + _delimiter + "spu_os_" + index
156 // PrintStream for writing to the file
157 OutputStream file = new FileOutputStream(filename);
158 CodePrintStream _code = new CodePrintStream(file);
160 _code.println("/****************************************************************");
161 _code.println(" * SPU OS file");
162 _code.println(" * Description: OS for one SPU");
163 _code.println(" */");
165 _code.println("#include \"spu_os.h\"");
167 // Must include all possible wrappers
168 Vector<String> pList = new Vector<String>();
169 // Go through all possible processes
170 for (Process p : spu) {
171 String basename = p.getBasename();
172 if (!pList.contains(basename)) {
174 _code.println("#include \".." + _delimiter + "spu_"
175 + p.getBasename() + _delimiter
176 + p.getBasename() + "Wrapper.h\"");
181 _code.println("// Main application");
182 _code.println("int main(int speid , uint64_t argp)");
184 _code.println(" // reserve DMA tag ID");
185 _code.println(" uint32_t tag_id;");
186 _code.println(" if((tag_id=mfc_tag_reserve())==MFC_TAG_INVALID){");
187 _code.println(" printf(\"SPE: ERROR - can't reserve a tag ID\"); return 1;");
190 _code.println(" // Get the context information for the whole system");
191 _code.println(" mfc_get((void*) &ctx_spu, argp, sizeof(ctx_spu), tag_id, 0, 0);");
192 _code.println(" mfc_write_tag_mask(1<<tag_id);");
193 _code.println(" mfc_read_tag_status_all();");
195 _code.println(" // This is the number of processes of this SPE");
196 _code.println(" uint64_t nr_proc = ctx_spu.procContentsLen;");
198 _code.println(" // Get the addresses of the contexts for the Processes");
199 _code.println(" uint64_t context_addr[nr_proc];");
200 _code.println(" mfc_get((void*)context_addr, ctx_spu.procContents, sizeof(uint64_t) * roundDMA(nr_proc), tag_id,0,0);");
202 _code.println(" mfc_write_tag_mask(1<<tag_id);");
203 _code.println(" mfc_read_tag_status_all();");
205 _code.println(" int32_t queueFromSPU[roundDMA(NUM_FIFO)] __attribute__ ((aligned(16)));");
206 _code.println(" int32_t queueOnSPU[roundDMA(NUM_FIFO)] __attribute__ ((aligned(16)));");
207 _code.println(" uint64_t tailAddresses[roundDMA(NUM_FIFO)] __attribute__ ((aligned(16)));");
209 _code.println(" mfc_get((void*)queueFromSPU, ctx_spu.queueFromSPU, sizeof(int32_t) * roundDMA(NUM_FIFO), tag_id,0,0);");
210 _code.println(" mfc_write_tag_mask(1<<tag_id);");
211 _code.println(" mfc_read_tag_status_all();");
213 _code.println(" mfc_get((void*)queueOnSPU, ctx_spu.queueOnSPU, sizeof(int32_t) * roundDMA(NUM_FIFO), tag_id,0,0);");
214 _code.println(" mfc_write_tag_mask(1<<tag_id);");
215 _code.println(" mfc_read_tag_status_all();");
217 _code.println(" // Get the base addresses");
218 _code.println(" uint64_t procContentsAll[roundDMA(NUM_SPES)] __attribute__ ((aligned(16)));");
220 _code.println(" mfc_get((void*)procContentsAll, ctx_spu.procContentsAll, sizeof(uint64_t) * roundDMA(NUM_SPES), tag_id,0,0);");
221 _code.println(" mfc_write_tag_mask(1<<tag_id);");
222 _code.println(" mfc_read_tag_status_all();");
224 _code.println(" // Read the base address");
225 _code.println(" uint64_t ea_base = ctx_spu.ea_base;");
228 Vector<Channel> channelList = new Vector<Channel>();
230 // instantiate channels
231 for (Channel c : x.getChannelList()) {
232 if (spu.contains(c.getOrigin())
233 || spu.contains(c.getTarget())) {
235 if (c.getType().equals("fifo")) {
236 _code.printPrefixln(" Fifo " + c.getName() + "("
237 + "FIFO_SIZE[" + indx + "]);");
238 } else if (c.getType().equals("wfifo")) {
239 _code.printPrefixln(" WindowedFifo "
240 + c.getName() + "(" + "FIFO_SIZE[" + indx
249 // Go through all processes
250 for (Process p : spu) {
251 // Create the process wrapper
252 _code.println(" " + p.getBasename() + "Wrapper *" + p.getName() +";");
253 _code.println(" try { "
254 + p.getName() + " = new " + p.getBasename()
255 + "Wrapper (context_addr[" + spu.indexOf(p)
257 _code.println(" catch(std::bad_alloc &e) {");
258 _code.println(" fprintf(stderr, \"[" + p.getBasename() +"Wrapper] Memory allocation failure\\n\");");
259 _code.println(" exit(1);");
262 // Create the port-mapping
263 for (Port port : p.getPortList()) {
264 if (port.getName().equals(port.getBasename())) {
265 _code.printPrefixln(" " + p.getName() + "->_port"
266 + port.getName() + "Fifo = &"
267 + port.getPeerResource().getName() + ";");
269 _code.printPrefix(" " + p.getName() + "->_port"
270 + port.getBasename() + "Fifo");
271 StringTokenizer tokenizer = new StringTokenizer(
272 port.getName().replaceFirst(
273 port.getBasename(), ""), "_");
274 while (tokenizer.hasMoreTokens()) {
275 _code.print("[" + tokenizer.nextToken() + "]");
278 + port.getPeerResource().getName() + ";");
284 // Count the effected channels
285 int countChannels = 0;
286 for (Channel c : channelList) {
287 if (spu.contains(c.getOrigin())
288 && spu.contains(c.getTarget())) {
290 } else if (spu.contains(c.getOrigin()))
292 else if (spu.contains(c.getTarget()))
295 System.out.println("ERROR! Channel Mapping is wrong.");
298 _code.println(" // inited all queues, now one has to know:");
299 _code.println(" // sends out the start addresses to the SPU (of all out channels)");
301 // Check all out queues on the SPU
302 _code.println(" uint32_t queuemessage;");
303 for (Channel c : channelList) {
304 if (spu.contains(c.getOrigin()) && !spu.contains(c.getTarget())) {
305 _code.println(" queuemessage = CREATEQUEUEMESSAGE(" + x.getChannelList().indexOf(c) + ", (uint32_t)" + c.getName() + ".getQueuePointer());");
306 _code.println(" spu_write_out_mbox(queuemessage);");
311 _code.println(" // Wait until we get the okey to read the tail pointers");
312 _code.println(" uint32_t messageIn = spu_read_in_mbox();");
314 _code.println(" mfc_get((void*)tailAddresses, ctx_spu.fifoTails, sizeof(uint64_t) * roundDMA(NUM_FIFO), tag_id,0,0);");
315 _code.println(" mfc_write_tag_mask(1<<tag_id);");
316 _code.println(" mfc_read_tag_status_all();");
317 _code.println(" FastCommunication * com;");
318 _code.println(" try { com = new FastCommunication("
319 + countChannels + ", ea_base, procContentsAll, queueFromSPU, queueOnSPU, tailAddresses); }");
320 _code.println(" catch(std::bad_alloc &e) {");
321 _code.println(" fprintf(stderr, \"[FastCommunication] Memory allocation failure\\n\");");
322 _code.println(" exit(1);");
325 String channelTyp = "";
327 for (Channel c : channelList) {
328 if (spu.contains(c.getOrigin())
329 && spu.contains(c.getTarget())) {
330 // Local channels have no influence on external
331 // communication (should be Windowed Fifos...)
332 channelTyp = "local";
334 } else if (spu.contains(c.getOrigin()))
336 else if (spu.contains(c.getTarget()))
339 System.out.println("ERROR! Channel Mapping is wrong.");
341 if (c.getType().equals("fifo")) {
342 _code.println(" com->addFifo(" + (i) + ", &"
343 + c.getName() + ", com->" + channelTyp + ", "
344 + x.getChannelList().indexOf(c) + ");");
346 else if (c.getType().equals("wfifo")) {
347 _code.println(" com->addWFifo(" + (i) + ", &"
348 + c.getName() + ", com->" + channelTyp + ", "
349 + x.getChannelList().indexOf(c) + ");");
354 // The scheduler (yes, this could be optimized...)
356 _code.println(" printf(\"SPU " + index + ": start to execute\\n\"); ");
358 _code.println(" bool allBlocked = false;");
359 _code.println(" while (!allBlocked)");
361 _code.println(" allBlocked = true;");
362 for (Process p : spu) {
363 _code.println(" if (!" + p.getName()
364 + "->isDetached())");
366 _code.println(" " + p.getName() + "->fire();");
367 _code.println(" allBlocked = false;");
370 // communication only if this process needs some communication
371 for (Channel c : channelList) {
372 // the channel may go away
373 if (!spu.contains(c.getOrigin()) || !spu.contains(c.getTarget())) {
374 if (c.getOrigin().equals(p) || c.getTarget().equals(p)) {
375 _code.println(" com->update();");
385 // End --> wait until all communications are finished
387 .println(" // Are there any open communication requests?");
388 _code.println(" while (!com->empty())");
390 _code.println(" com->update();");
393 for (Process p : spu) {
394 _code.println(" delete " + p.getName() + ";");
397 _code.println(" delete com;");
399 _code.println(" // release tag ID before exiting");
400 _code.println(" mfc_tag_release(tag_id);");
402 _code.println(" uint32_t message = CREATEFASTMESSAGE(SPE_COMPLETE, 0, 0);");
403 _code.println(" spu_write_out_mbox(message);");
405 _code.println(" messageIn = spu_read_in_mbox();");
407 } catch (FileNotFoundException e) {
412 protected String _spuDir = null;
413 protected CodePrintStream _mainPS = null;
414 protected String _dir = null;
415 protected CellMapping _mapping = null;