Fix a bug in scheduling search algorithm: it can not find the best scheduling for...
[IRC.git] / Robust / src / Analysis / Scheduling / SchedulingUtil.java
1 package Analysis.Scheduling;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.PrintWriter;
6 import java.util.Collection;
7 import java.util.Enumeration;
8 import java.util.HashSet;
9 import java.util.Hashtable;
10 import java.util.Iterator;
11 import java.util.Set;
12 import java.util.Vector;
13 import java.util.Map.Entry;
14
15 import Analysis.Scheduling.ScheduleSimulator.Action;
16 import Analysis.Scheduling.ScheduleSimulator.CheckPoint;
17 import Analysis.TaskStateAnalysis.Allocations;
18 import Analysis.TaskStateAnalysis.FEdge;
19 import Analysis.TaskStateAnalysis.FlagState;
20 import Analysis.TaskStateAnalysis.FEdge.NewObjInfo;
21 import IR.ClassDescriptor;
22 import IR.Operation;
23 import IR.State;
24 import IR.Tree.FlagExpressionNode;
25 import IR.Tree.FlagNode;
26 import IR.Tree.FlagOpNode;
27 import Util.Edge;
28 import Util.GraphNode;
29 import Util.Namer;
30
31 public class SchedulingUtil {
32     
33     public static Vector<ScheduleNode> generateScheduleGraph(State state, 
34                                                              Vector<ScheduleNode> scheduleNodes,
35                                                              Vector<ScheduleEdge> scheduleEdges,
36                                                              Vector<Vector<ScheduleNode>> rootnodes, 
37                                                              Vector<Vector<CombinationUtil.Combine>> combine, 
38                                                              int gid) {
39         Vector<ScheduleNode> result = new Vector<ScheduleNode>();
40
41         // clone the ScheduleNodes
42         Hashtable<ScheduleNode, Hashtable<ClassNode, ClassNode>> sn2hash = 
43             new Hashtable<ScheduleNode, Hashtable<ClassNode, ClassNode>>();
44         Hashtable<ScheduleNode, ScheduleNode> sn2sn = 
45             new Hashtable<ScheduleNode, ScheduleNode>();
46         cloneScheduleGraph(scheduleNodes,
47                            scheduleEdges,
48                            sn2hash,
49                            sn2sn,
50                            result,
51                            gid);
52
53         // combine those nodes in combine with corresponding rootnodes
54         for(int i = 0; i < combine.size(); i++) {
55             if(combine.elementAt(i) != null) {
56                 for(int j = 0; j < combine.elementAt(i).size(); j++) {
57                     CombinationUtil.Combine tmpcombine = combine.elementAt(i).elementAt(j);
58                     ScheduleNode tocombine = sn2sn.get(tmpcombine.node);
59                     ScheduleNode root = sn2sn.get(rootnodes.elementAt(tmpcombine.root).elementAt(tmpcombine.index));
60                     ScheduleEdge se = (ScheduleEdge)tocombine.inedges().next();
61                     try {
62                         if(root.equals(((ScheduleNode)se.getSource()))) {
63                             root.mergeSEdge(se);
64                             if(ScheduleEdge.NEWEDGE == se.getType()) {
65                                 // As se has been changed into an internal edge inside a ScheduleNode,
66                                 // change the source and target of se from original ScheduleNodes into ClassNodes.
67                                 se.setTarget(se.getTargetCNode());
68                                 //se.setSource(se.getSourceCNode());
69                                 //se.getTargetCNode().addEdge(se);
70                                 se.getSourceCNode().addEdge(se);
71                             }
72                         } else {
73                             root.mergeSNode(tocombine);
74                         }
75                     } catch(Exception e) {
76                         e.printStackTrace();
77                         System.exit(-1);
78                     }
79                     result.removeElement(tocombine);
80                 }
81             }
82         }
83         
84         assignCids(result);
85         
86         sn2hash.clear();
87         sn2hash = null;
88         sn2sn.clear();
89         sn2sn = null;
90
91         if(state.PRINTSCHEDULING) {
92             String path = state.outputdir + "scheduling_" + gid + ".dot";
93             SchedulingUtil.printScheduleGraph(path, result);
94         }
95
96         return result;
97     }
98     
99     public static void cloneScheduleGraph(Vector<ScheduleNode> scheduleNodes,
100                                           Vector<ScheduleEdge> scheduleEdges,
101                                           Hashtable<ScheduleNode, Hashtable<ClassNode, ClassNode>> sn2hash,
102                                           Hashtable<ScheduleNode, ScheduleNode> sn2sn,
103                                           Vector<ScheduleNode> result,
104                                           int gid) {
105         for(int i = 0; i < scheduleNodes.size(); i++) {
106             Hashtable<ClassNode, ClassNode> cn2cn = new Hashtable<ClassNode, ClassNode>();
107             ScheduleNode tocopy = scheduleNodes.elementAt(i);
108             ScheduleNode temp = (ScheduleNode)tocopy.clone(cn2cn, gid);
109             result.add(i, temp);
110             sn2hash.put(temp, cn2cn);
111             sn2sn.put(tocopy, temp);
112             cn2cn = null;
113         }
114         // clone the ScheduleEdges
115         for(int i = 0; i < scheduleEdges.size(); i++) {
116             ScheduleEdge sse = scheduleEdges.elementAt(i);
117             ScheduleNode csource = sn2sn.get(sse.getSource());
118             ScheduleNode ctarget = sn2sn.get(sse.getTarget());
119             Hashtable<ClassNode, ClassNode> sourcecn2cn = sn2hash.get(csource);
120             Hashtable<ClassNode, ClassNode> targetcn2cn = sn2hash.get(ctarget);
121             ScheduleEdge se =  null;
122             switch(sse.getType()) {
123             case ScheduleEdge.NEWEDGE: {
124                 se = new ScheduleEdge(ctarget, "new", sse.getFstate(), sse.getType(), gid);       //new ScheduleEdge(ctarget, "new", sse.getClassDescriptor(), sse.getIsNew(), gid);
125                 se.setProbability(sse.getProbability());
126                 se.setNewRate(sse.getNewRate());
127                 break;
128             }
129
130             case ScheduleEdge.TRANSEDGE: {
131                 se = new ScheduleEdge(ctarget, "transmit", sse.getFstate(), sse.getType(), gid);       //new ScheduleEdge(ctarget, "transmit", sse.getClassDescriptor(), false, gid);
132                 break;
133             }
134             }
135             se.setSourceCNode(sourcecn2cn.get(sse.getSourceCNode()));
136             se.setTargetCNode(targetcn2cn.get(sse.getTargetCNode()));
137             se.setFEdge(sse.getFEdge());
138             se.setTargetFState(sse.getTargetFState());
139             se.setIsclone(true);
140             csource.addEdge(se);
141             sourcecn2cn = null;
142             targetcn2cn = null;
143         }
144     }
145     
146     public static void assignCids(Vector<ScheduleNode> result) {
147         Hashtable<Integer, Integer> hcid2cid = new Hashtable<Integer, Integer>();
148         int ncid = 0;
149         for(int i = 0; i < result.size(); i++) {
150             ScheduleNode tmpnode = result.elementAt(i);
151             tmpnode.computeHashcid();
152             int hcid = tmpnode.getHashcid();
153             if(hcid2cid.containsKey(hcid)) {
154                 // already have a cid for this node
155                 tmpnode.setCid(hcid2cid.get(hcid));
156             } else {
157                 // generate a new cid for such node
158                 tmpnode.setCid(ncid);
159                 hcid2cid.put(hcid, ncid);
160                 ncid++;
161             }
162         }
163         hcid2cid.clear();
164         hcid2cid = null;
165     }
166     
167     //  Organize the scheduleNodes in order of their cid
168     public static Vector<Vector<ScheduleNode>> rangeScheduleNodes(Vector<ScheduleNode> scheduleNodes) {
169         Vector<Vector<ScheduleNode>> sNodeVecs = new Vector<Vector<ScheduleNode>>();
170         
171         for(int i = 0; i < scheduleNodes.size(); i++) {
172             ScheduleNode tmpn = scheduleNodes.elementAt(i);
173             int tmpcid = tmpn.getCid();
174             int index = 0;
175             for(index = 0; index < sNodeVecs.size(); index++) {
176                 if(sNodeVecs.elementAt(index).elementAt(0).getCid() > tmpcid) {
177                     // find the place to insert
178                     sNodeVecs.add(sNodeVecs.lastElement());
179                     for(int j = sNodeVecs.size() - 2; j > index; j--) {
180                         sNodeVecs.setElementAt(sNodeVecs.elementAt(j - 1), j);
181                     }
182                     sNodeVecs.setElementAt(new Vector<ScheduleNode>(), index);
183                 } else if(sNodeVecs.elementAt(index).elementAt(0).getCid() == tmpcid) {
184                     break;
185                 }
186             }
187             if(index == sNodeVecs.size()) {
188                 sNodeVecs.add(new Vector<ScheduleNode>());
189             }
190             
191             /*int index = tmpcid;
192             while(sNodeVecs.size() <= index) {
193                 sNodeVecs.add(null);
194             }
195             if(sNodeVecs.elementAt(index) == null) {
196                 sNodeVecs.setElementAt(new Vector<ScheduleNode>(), index);
197             }*/
198             sNodeVecs.elementAt(index).add(tmpn);
199         }
200         
201         return sNodeVecs;
202     }
203
204   /*public static int maxDivisor(int l, int r) {
205       int a = l;
206       int b = r;
207       int c = 0;
208
209       while(true) {
210           if(a == 0) {
211               return b << c;
212           } else if(b == 0) {
213               return a << c;
214           }
215
216           if(((a&1)==0) && ((b&1)==0)) {
217               // a and b are both even
218               a >>= 1;
219               b >>= 1;
220    ++c;
221           } else if(((a&1)==0) && ((b&1)!=0)) {
222               // a is even, b is odd
223               a >>= 1;
224           } else if (((a&1)!=0) && ((b&1)==0)) {
225               // a is odd, b is even
226               b >>= 1;
227           } else if (((a&1)!=0) && ((b&1)!=0)) {
228               // a and b are both odd
229               int tmp = a>b? b:a;
230               a = a>b ? (a-b):(b-a);
231               b = tmp;
232           }
233       }
234      }*/
235
236   public static boolean isTaskTrigger_flag(FlagExpressionNode fen,
237                                            FlagState fs) {
238     if (fen==null)
239       return true;
240     else if (fen instanceof FlagNode)
241       return fs.get(((FlagNode)fen).getFlag());
242     else
243       switch (((FlagOpNode)fen).getOp().getOp()) {
244       case Operation.LOGIC_AND:
245         return ((isTaskTrigger_flag(((FlagOpNode)fen).getLeft(),fs)) && (isTaskTrigger_flag(((FlagOpNode)fen).getRight(),fs)));
246
247       case Operation.LOGIC_OR:
248         return ((isTaskTrigger_flag(((FlagOpNode)fen).getLeft(),fs)) || (isTaskTrigger_flag(((FlagOpNode)fen).getRight(),fs)));
249
250       case Operation.LOGIC_NOT:
251         return !(isTaskTrigger_flag(((FlagOpNode)fen).getLeft(),fs));
252
253       default:
254         return false;
255       }
256   }
257
258   public static void printScheduleGraph(String path, 
259                                         Vector<ScheduleNode> sNodes) {
260     try {
261       File file=new File(path);
262       FileOutputStream dotstream=new FileOutputStream(file,false);
263       PrintWriter output = new java.io.PrintWriter(dotstream, true);
264       output.println("digraph G {");
265       output.println("\tcompound=true;\n");
266       traverseSNodes(output, sNodes);
267       output.println("}\n");
268       output.close();
269     } catch (Exception e) {
270       e.printStackTrace();
271       System.exit(-1);
272     }
273   }
274
275   private static void traverseSNodes(PrintWriter output, 
276                                      Vector<ScheduleNode> sNodes) {
277     //Draw clusters representing ScheduleNodes
278     Iterator it = sNodes.iterator();
279     while (it.hasNext()) {
280       ScheduleNode gn = (ScheduleNode) it.next();
281       Iterator edges = gn.edges();
282       output.println("\tsubgraph " + gn.getLabel() + "{");
283       output.println("\t\tlabel=\"" + gn.getTextLabel() + "\";");
284       Iterator it_cnodes = gn.getClassNodesIterator();
285       traverseCNodes(output, it_cnodes);
286       //Draw the internal 'new' edges
287       Iterator it_edges =gn.getScheduleEdgesIterator();
288       while(it_edges.hasNext()) {
289         ScheduleEdge se = (ScheduleEdge)it_edges.next();
290         output.print("\t");
291         if(se.getSourceCNode().isclone()) {
292           output.print(se.getSourceCNode().getLabel());
293         } else {
294           if(se.getSourceFState() == null) {
295             output.print(se.getSourceCNode().getClusterLabel());
296           } else {
297             output.print(se.getSourceFState().getLabel());
298           }
299         }
300
301         output.print(" -> ");
302         if(se.isclone()) {
303           if(se.getTargetCNode().isclone()) {
304             output.print(se.getTargetCNode().getLabel());
305           } else {
306             output.print(se.getTargetCNode().getClusterLabel());
307           }
308           output.println(" [label=\"" + se.getLabel() + "\", color=red];");
309         } else {
310           output.print(se.getTargetFState().getLabel() + " [label=\"" + se.getLabel() + "\", color=red, ltail=");
311           if(se.getSourceCNode().isclone()) {
312             output.println(se.getSourceCNode().getLabel() + "];");
313           } else {
314             output.println(se.getSourceCNode().getClusterLabel() + "];");
315           }
316         }
317       }
318       output.println("\t}\n");
319       //Draw 'new' edges of this ScheduleNode
320       while(edges.hasNext()) {
321         ScheduleEdge se = (ScheduleEdge)edges.next();
322         output.print("\t");
323         if(se.getSourceCNode().isclone()) {
324           output.print(se.getSourceCNode().getLabel());
325         } else {
326           if(se.getSourceFState() == null) {
327             output.print(se.getSourceCNode().getClusterLabel());
328           } else {
329             output.print(se.getSourceFState().getLabel());
330           }
331         }
332
333         output.print(" -> ");
334         if(se.isclone()) {
335           if(se.getTargetCNode().isclone()) {
336             output.print(se.getTargetCNode().getLabel());
337           } else {
338             output.print(se.getTargetCNode().getClusterLabel());
339           }
340           output.println(" [label=\"" + se.getLabel() + "\", color=red, style=dashed];");
341         } else {
342           output.println(se.getTargetFState().getLabel() + " [label=\"" + se.getLabel() + "\", color=red, style=dashed];");
343         }
344       }
345     }
346   }
347
348   private static void traverseCNodes(PrintWriter output, 
349                                      Iterator it) {
350     //Draw clusters representing ClassNodes
351     while (it.hasNext()) {
352       ClassNode gn = (ClassNode) it.next();
353       if(gn.isclone()) {
354         output.println("\t\t" + gn.getLabel() + " [style=dashed, label=\"" + gn.getTextLabel() + "\", shape=box];");
355       } else {
356         output.println("\tsubgraph " + gn.getClusterLabel() + "{");
357         output.println("\t\tstyle=dashed;");
358         output.println("\t\tlabel=\"" + gn.getTextLabel() + "\";");
359         traverseFlagStates(output, gn.getFlagStates());
360         output.println("\t}\n");
361       }
362     }
363   }
364
365   private static void traverseFlagStates(PrintWriter output, 
366                                          Collection nodes) {
367     Set cycleset=GraphNode.findcycles(nodes);
368     Vector namers=new Vector();
369     namers.add(new Namer());
370     namers.add(new Allocations());
371
372     Iterator it = nodes.iterator();
373     while (it.hasNext()) {
374       GraphNode gn = (GraphNode) it.next();
375       Iterator edges = gn.edges();
376       String label = "";
377       String dotnodeparams="";
378
379       for(int i=0; i<namers.size(); i++) {
380         Namer name=(Namer) namers.get(i);
381         String newlabel=name.nodeLabel(gn);
382         String newparams=name.nodeOption(gn);
383
384         if (!newlabel.equals("") && !label.equals("")) {
385           label+=", ";
386         }
387         if (!newparams.equals("")) {
388           dotnodeparams+=", " + name.nodeOption(gn);
389         }
390         label+=name.nodeLabel(gn);
391       }
392       label += ":[" + ((FlagState)gn).getExeTime() + "]";
393
394       if (!gn.merge)
395         output.println("\t" + gn.getLabel() + " [label=\"" + label + "\"" + dotnodeparams + "];");
396
397       if (!gn.merge)
398         while (edges.hasNext()) {
399           Edge edge = (Edge) edges.next();
400           GraphNode node = edge.getTarget();
401           if (nodes.contains(node)) {
402             for(Iterator nodeit=nonmerge(node, nodes).iterator(); nodeit.hasNext();) {
403               GraphNode node2=(GraphNode)nodeit.next();
404               String edgelabel = "";
405               String edgedotnodeparams="";
406
407               for(int i=0; i<namers.size(); i++) {
408                 Namer name=(Namer) namers.get(i);
409                 String newlabel=name.edgeLabel(edge);
410                 String newoption=name.edgeOption(edge);
411                 if (!newlabel.equals("")&& !edgelabel.equals(""))
412                   edgelabel+=", ";
413                 edgelabel+=newlabel;
414                 if (!newoption.equals(""))
415                   edgedotnodeparams+=", "+newoption;
416               }
417               edgelabel+=":[" + ((FEdge)edge).getExeTime() + "]";
418               edgelabel+=":(" + ((FEdge)edge).getProbability() + "%)";
419               Hashtable<ClassDescriptor, NewObjInfo> hashtable = ((FEdge)edge).getNewObjInfoHashtable();
420               if(hashtable != null) {
421                 Set<ClassDescriptor> keys = hashtable.keySet();
422                 Iterator it_keys = keys.iterator();
423                 while(it_keys.hasNext()) {
424                   ClassDescriptor cd = (ClassDescriptor)it_keys.next();
425                   NewObjInfo noi = hashtable.get(cd);
426                   edgelabel += ":{ class " + cd.getSymbol() + " | " + noi.getNewRate() + " | (" + noi.getProbability() + "%) }";
427                 }
428               }
429               output.println("\t" + gn.getLabel() + " -> " + node2.getLabel() + " [" + "label=\"" + edgelabel + "\"" + edgedotnodeparams + "];");
430             }
431           }
432         }
433     }
434   }
435
436   private static Set nonmerge(GraphNode gn, 
437                               Collection nodes) {
438     HashSet newset=new HashSet();
439     HashSet toprocess=new HashSet();
440     toprocess.add(gn);
441     while(!toprocess.isEmpty()) {
442       GraphNode gn2=(GraphNode)toprocess.iterator().next();
443       toprocess.remove(gn2);
444       if (!gn2.merge)
445         newset.add(gn2);
446       else {
447         Iterator edges = gn2.edges();
448         while (edges.hasNext()) {
449           Edge edge = (Edge) edges.next();
450           GraphNode node = edge.getTarget();
451           if (!newset.contains(node)&&nodes.contains(node))
452             toprocess.add(node);
453         }
454       }
455     }
456     return newset;
457   }
458
459   public static void printSimulationResult(String path, 
460                                            int time, 
461                                            int coreNum, 
462                                            Vector<CheckPoint> checkpoints) {
463     try {
464       File file=new File(path);
465       FileOutputStream dotstream=new FileOutputStream(file,false);
466       PrintWriter output = new java.io.PrintWriter(dotstream, true);
467       output.println("digraph simulation{");
468       output.print("\t");
469       output.println("node [shape=plaintext];");
470       output.print("\t");
471       output.println("edge [dir=none];");
472       output.print("\t");
473       output.println("ranksep=.05;");
474       output.println();
475       output.print("\t");
476       int j = 0;
477
478       // the capital line
479       output.print("{rank=source; \"Time\"; ");
480       for(j = 0; j < coreNum; j++) {
481         output.print("\"core " + j + "\"; ");
482       }
483       output.println("}");
484       // time coordinate nodes
485       Vector<String> timeNodes = new Vector<String>();
486       String[] lastTaskNodes = new String[coreNum];
487       String[] lastTasks = new String[coreNum];
488       boolean[] isTaskFinish = new boolean[coreNum];
489       for(j = 0; j < coreNum; j++) {
490         lastTaskNodes[j] = "first";
491         isTaskFinish[j] = true;
492         lastTasks[j] = "";
493       }
494       timeNodes.add("0");
495       for(j = 0; j < checkpoints.size(); j++) {
496         CheckPoint tcp = checkpoints.elementAt(j);
497         Hashtable<Integer, String> tmplastTasks = new Hashtable<Integer, String>();
498         Vector<Integer> tmpisTaskFinish = new Vector<Integer>();
499         Vector<Integer> tmpisset = new Vector<Integer>();
500         String tnode = String.valueOf(tcp.getTimepoint());
501         if(!timeNodes.contains(tnode)) {
502           timeNodes.add(tnode);
503         }
504         Vector<Action> actions = tcp.getActions();
505         Hashtable<String, StringBuffer> tmpTaskNodes = new Hashtable<String, StringBuffer>();
506         for(int i = 0; i < actions.size(); i++) {
507           Action taction = actions.elementAt(i);
508           int cNum = taction.getCoreNum();
509           if(!tmplastTasks.containsKey(cNum)) {
510             tmplastTasks.put(cNum, lastTasks[cNum]);
511           }
512           if(!(tmpisset.contains(cNum)) 
513                   && (isTaskFinish[cNum]) 
514                   && !(tmpisTaskFinish.contains(cNum))) {
515             tmpisTaskFinish.add(cNum);  // records those with task finished the first time visit it
516           }
517           String tmpTaskNode = "\"" + tnode + "core" + cNum + "\"";
518           StringBuffer tmpLabel = null;
519           boolean isfirst = false;
520           if(!tmpTaskNodes.containsKey(tmpTaskNode)) {
521             tmpTaskNodes.put(tmpTaskNode, new StringBuffer(tnode + ":"));
522             isfirst = true;
523           }
524           tmpLabel = tmpTaskNodes.get(tmpTaskNode);
525           switch(taction.getType()) {
526           case Action.ADDOBJ: {
527             if(!isfirst) {
528               tmpLabel.append("\\n");
529             }
530             tmpLabel.append("(" + taction.getTransObj().getSymbol() + ")arrives;");
531             if(!(lastTaskNodes[cNum].equals(tmpTaskNode))) {
532               output.print("\t");
533               if(lastTaskNodes[cNum].equals("first")) {
534                 output.print("\"core " + cNum + "\"->" + tmpTaskNode);
535               } else {
536                 output.print(lastTaskNodes[cNum] + "->" + tmpTaskNode);
537               }
538               if(tmpisTaskFinish.contains(cNum)) {
539                 output.print(" [style=invis]");
540               }
541               output.println(";");
542               lastTaskNodes[cNum] = tmpTaskNode;
543             }
544             break;
545           }
546
547           case Action.TASKFINISH: {
548             if(!isfirst) {
549               tmpLabel.append("\\n");
550             }
551             tmpLabel.append("<" + taction.getTd().getSymbol() + "(");
552             /*Vector<Integer> taskparams = taction.getTaskParams();
553             for(int ii = 0; ii < taskparams.size(); ii++) {
554                 tmpLabel.append(taskparams.elementAt(ii));
555                 if(ii < taskparams.size() - 1) {
556                     tmpLabel.append(",");
557                 }
558             }*/
559             tmpLabel.append(")>finishes;");
560             if(!(lastTaskNodes[cNum].equals("first"))) {
561               if(!(lastTaskNodes[cNum].equals(tmpTaskNode))) {
562                 output.print("\t");
563                 output.println(lastTaskNodes[cNum] + "->" + tmpTaskNode + ";");
564                 lastTaskNodes[cNum] = tmpTaskNode;
565               }
566               if(tmpisset.contains(cNum)) {
567                 isTaskFinish[cNum] &= true;
568               } else {
569                 isTaskFinish[cNum] = true;
570                 tmpisset.add(cNum);
571               }
572               lastTasks[cNum] = "";
573             } else {
574               throw new Exception("Error: unexpected task finish");
575             }
576             break;
577           }
578
579           case Action.TFWITHOBJ: {
580             if(!isfirst) {
581               tmpLabel.append("\\n");
582             }
583             tmpLabel.append("<" + taction.getTd().getSymbol() + "(");
584             /*Vector<Integer> taskparams = taction.getTaskParams();
585             for(int ii = 0; ii < taskparams.size(); ii++) {
586                 tmpLabel.append(taskparams.elementAt(ii));
587                 if(ii < taskparams.size() - 1) {
588                     tmpLabel.append(",");
589                 }
590             }*/
591             tmpLabel.append(")>finishes;");
592             Iterator<Entry<ClassDescriptor, Integer>> it_entry = (Iterator<Entry<ClassDescriptor, Integer>>)taction.getNObjs().entrySet().iterator();
593             while(it_entry.hasNext()) {
594               Entry<ClassDescriptor, Integer> entry = it_entry.next();
595               tmpLabel.append(entry.getValue() + "(" + entry.getKey().getSymbol() + ")");
596               if(it_entry.hasNext()) {
597                 tmpLabel.append(",");
598               } else {
599                 tmpLabel.append(";");
600               }
601             }
602             if(!(lastTaskNodes[cNum].equals("first"))) {
603               if (!(lastTaskNodes[cNum].equals(tmpTaskNode))) {
604                 output.print("\t");
605                 output.println(lastTaskNodes[cNum] + "->" + tmpTaskNode + ";");
606                 lastTaskNodes[cNum] = tmpTaskNode;
607               }
608               if(tmpisset.contains(cNum)) {
609                 isTaskFinish[cNum] &= true;
610               } else {
611                 isTaskFinish[cNum] = true;
612                 tmpisset.add(cNum);
613               }
614               lastTasks[cNum] = "";
615             } else {
616               throw new Exception("Error: unexpected task finish");
617             }
618             break;
619           }
620
621           case Action.TASKSTART: {
622             if(!isfirst) {
623               tmpLabel.append("\\n");
624             }
625             tmpLabel.append("<" + taction.getTd().getSymbol() + "(");
626             /*Vector<Integer> taskparams = taction.getTaskParams();
627             for(int ii = 0; ii < taskparams.size(); ii++) {
628                 tmpLabel.append(taskparams.elementAt(ii));
629                 if(ii < taskparams.size() - 1) {
630                     tmpLabel.append(",");
631                 }
632             }*/
633             tmpLabel.append(")>starts;");
634             lastTasks[cNum] = taction.getTd().getSymbol();
635
636             if (!(lastTaskNodes[cNum].equals(tmpTaskNode))) {
637               output.print("\t");
638               if(lastTaskNodes[cNum].equals("first")) {
639                 output.print("\"core " + cNum + "\"->" + tmpTaskNode);
640               } else {
641                 output.print(lastTaskNodes[cNum] + "->" + tmpTaskNode);
642               }
643               if(tmpisTaskFinish.contains(cNum)) {
644                 output.print(" [style=invis]");
645               }
646               output.println(";");
647               lastTaskNodes[cNum] = tmpTaskNode;
648             }
649             isTaskFinish[cNum] &= false;
650             break;
651           }
652
653           case Action.TASKABORT: {
654             if(!isfirst) {
655               tmpLabel.append("\\n");
656             }
657             tmpLabel.append("<" + taction.getTd().getSymbol() + "(");
658             /*Vector<Integer> taskparams = taction.getTaskParams();
659             for(int ii = 0; ii < taskparams.size(); ii++) {
660                 tmpLabel.append(taskparams.elementAt(ii));
661                 if(ii < taskparams.size() - 1) {
662                     tmpLabel.append(",");
663                 }
664             }*/
665             tmpLabel.append(")>aborts;");
666             if(!(lastTaskNodes[cNum].equals("first")) &&
667                (tmplastTasks.get(cNum).equals(taction.getTd().getSymbol()))) {
668               if(!(lastTaskNodes[cNum].equals(tmpTaskNode))) {
669                 output.print("\t");
670                 output.println(lastTaskNodes[cNum] + "->" + tmpTaskNode + ";");
671                 lastTaskNodes[cNum] = tmpTaskNode;
672               }
673               if(tmpisset.contains(cNum)) {
674                 isTaskFinish[cNum] &= true;
675               } else {
676                 isTaskFinish[cNum] = true;
677                 tmpisset.add(cNum);
678               }
679               lastTasks[cNum] = "";
680             } else {
681               throw new Exception("Error: unexpected task aborts");
682             }
683             break;
684           }
685
686           case Action.TASKREMOVE: {
687             if(!isfirst) {
688               tmpLabel.append("\\n");
689             }
690             tmpLabel.append("<" + taction.getTd().getSymbol() + "(");
691             /*Vector<Integer> taskparams = taction.getTaskParams();
692             for(int ii = 0; ii < taskparams.size(); ii++) {
693                 tmpLabel.append(taskparams.elementAt(ii));
694                 if(ii < taskparams.size() - 1) {
695                     tmpLabel.append(",");
696                 }
697             }*/
698             tmpLabel.append(")>removes;");
699             if(!(lastTaskNodes[cNum].equals("first")) &&
700                (tmplastTasks.get(cNum).equals(taction.getTd().getSymbol()))) {
701               if(!(lastTaskNodes[cNum].equals(tmpTaskNode))) {
702                 output.print("\t");
703                 output.println(lastTaskNodes[cNum] + "->" + tmpTaskNode + ";");
704                 lastTaskNodes[cNum] = tmpTaskNode;
705               }
706               if(tmpisset.contains(cNum)) {
707                 isTaskFinish[cNum] &= true;
708               } else {
709                 isTaskFinish[cNum] = true;
710                 tmpisset.add(cNum);
711               }
712               lastTasks[cNum] = "";
713             } else {
714               throw new Exception("Error: unexpected task remove");
715             }
716             break;
717           }
718           }
719         }
720         Enumeration<String> keys = tmpTaskNodes.keys();
721         while(keys.hasMoreElements()) {
722           String tmpTaskNode = keys.nextElement();
723           output.print("\t");
724           output.println(tmpTaskNode + "[label=\"" + tmpTaskNodes.get(tmpTaskNode).toString() + "\"]");
725         }
726         output.print("\t");
727         output.print("{rank=same; rankdir=LR; " + tnode + "; ");
728         keys = tmpTaskNodes.keys();
729         while(keys.hasMoreElements()) {
730           String tmpTaskNode = keys.nextElement();
731           output.print(tmpTaskNode);
732           output.print("; ");
733         }
734         keys = null;
735         output.println("}");
736         output.print("\t");
737         tmplastTasks = null;
738         tmpisTaskFinish = null;
739         tmpisset = null;
740         actions = null;
741         tmpTaskNodes = null;
742       }
743       output.print("\t");
744       output.print("\t");
745       int prev = Integer.parseInt(timeNodes.elementAt(0));
746       int next = 0;
747       int max = 0;
748       int max2 = 0;
749       for(j = 1; j < timeNodes.size(); j++) {
750         next = Integer.parseInt(timeNodes.elementAt(j));
751         int delta = next - prev;
752         if(max < delta) {
753           max2 = max;
754           max = delta;
755         } else if((max != delta) && (max2 < delta)) {
756           max2 = delta;
757         }
758         prev = next;
759       }
760       if(max2 == 0) {
761         max2 = 1;
762       } else if(max/max2 > 100) {
763         max2 = max/100;
764       }
765       output.println("\"Time\"->" + timeNodes.elementAt(0) + "[style=invis];");
766       prev = Integer.parseInt(timeNodes.elementAt(0));
767       next = 0;
768       for(j = 1; j < timeNodes.size(); j++) {
769         next = Integer.parseInt(timeNodes.elementAt(j));
770         if(next - prev > max2) {
771           do {
772             output.print(prev + "->");
773             prev += max2;
774           } while(next - prev > max2);
775           output.println(next + ";");
776         } else {
777           output.println("{rank=same; rankdir=LR; " + prev + "; " + next + "}");
778           output.println(prev + "->" + next + "[style=invis];");
779         }
780         prev = next;
781       }
782
783       /*for(j = 0; j < time; j++) {
784          output.print(j + "->");
785          }
786          output.println(timeNodes.lastElement() + ";");*/
787       output.println("}");
788       output.close();
789       timeNodes = null;
790       lastTaskNodes = null;
791       lastTasks = null;
792       isTaskFinish = null;
793     } catch (Exception e) {
794       e.printStackTrace();
795       System.exit(-1);
796     }
797   }
798   
799   public static void printCriticalPath(String path,
800                                        Vector<SimExecutionEdge> criticalPath) {
801       try {
802           File file=new File(path);
803           FileOutputStream dotstream=new FileOutputStream(file,false);
804           PrintWriter output = new java.io.PrintWriter(dotstream, true);
805           output.println("digraph simulation{");
806           output.print("\t");
807           output.println("node [shape=plaintext];");
808           output.print("\t");
809           output.println("edge [dir=none];");
810           output.print("\t");
811           output.println("ranksep=.05;");
812           output.println();
813           output.print("\t");
814           Vector<SimExecutionNode> nodes = new Vector<SimExecutionNode>();
815           String label = "";
816           String dotnodeparams="";
817
818           for(int i = 0; i < criticalPath.size(); i++) {
819               SimExecutionEdge seedge = criticalPath.elementAt(i);
820               SimExecutionNode startnode = (SimExecutionNode)seedge.getSource();
821               SimExecutionNode endnode = (SimExecutionNode)seedge.getTarget();
822               if(!nodes.contains(startnode)) {
823                   label = startnode.getCoreNum() + ":" + startnode.getTimepoint();
824                   output.println("\t" + startnode.getLabel() + " [label=\"" 
825                                  + label + "\" ];");
826               }
827               if(!nodes.contains(endnode)) {
828                   label = endnode.getCoreNum() + ":" + endnode.getTimepoint();
829                   output.println("\t" + endnode.getLabel() + " [label=\"" 
830                                  + label + "\" ];");
831               }
832               output.println("\t" + startnode.getLabel() + " -> " + endnode.getLabel() 
833                              + " [" + "label=\"" + seedge.getLabel() + "\"];");
834           }
835           output.println("}");
836           output.close();
837       } catch (Exception e) {
838           e.printStackTrace();
839           System.exit(-1);
840       }
841   }
842 }