add codes for generating multi-core version binary. Also add options -multicore ...
[IRC.git] / Robust / src / Analysis / Scheduling / ScheduleNode.java
1 package Analysis.Scheduling;
2
3 import java.util.*;
4
5 import Analysis.TaskStateAnalysis.FEdge;
6 import Analysis.TaskStateAnalysis.FlagState;
7 import Util.GraphNode;
8
9 /** This class holds flag transition diagram(s) can be put on one core.
10  */
11 public class ScheduleNode extends GraphNode implements Cloneable{
12     
13     private int uid;
14     private int gid;
15     private static int nodeID=0;
16
17     private Vector<ClassNode> classNodes;
18     Vector<ScheduleEdge> scheduleEdges;
19     
20     private int executionTime;
21
22     /** Class constructor
23      *  @param cd ClassDescriptor
24      *  @param fStates
25      */
26     public ScheduleNode(int gid) {
27         this.uid = ScheduleNode.nodeID++;
28         this.gid = gid;
29         this.executionTime = -1;
30         this.classNodes = null;
31         this.scheduleEdges = null;
32     }
33     
34     public ScheduleNode(ClassNode cn, int gid) {
35         this.uid = ScheduleNode.nodeID++;
36         this.gid = gid;
37         this.classNodes = new Vector<ClassNode>();
38         this.scheduleEdges = new Vector<ScheduleEdge>();
39         this.classNodes.add(cn);
40         this.addEdge(cn.getEdgeVector());
41         this.executionTime = -1;
42     }
43    
44     public int getuid() {
45         return uid;
46     }
47     
48     public String toString() {
49         String temp = new String("");
50         for(int i = 0; i < classNodes.size(); i++) {
51             temp += classNodes.elementAt(i).getClassDescriptor().toString() + ", ";
52         }
53         temp += getTextLabel();
54         return temp;
55     }
56     
57     public Vector getClassNodes() {
58         return classNodes;
59     }
60     
61     public Iterator getClassNodesIterator() {
62         if(classNodes == null) {
63             return null;
64         }
65         return classNodes.iterator();
66     }
67     
68     public void resetClassNodes() {
69         classNodes = null;
70     }
71     
72     public Vector getScheduleEdges() {
73         return scheduleEdges;
74     }
75     
76     public Iterator getScheduleEdgesIterator() {
77         if(scheduleEdges == null) {
78             return null;
79         }
80         return scheduleEdges.iterator();
81     }
82     
83     public void resetScheduleEdges() {
84         scheduleEdges = null;
85     }
86     
87     public int getExeTime() {
88         if(this.executionTime == -1) {
89             try {
90                 calExeTime();
91             } catch (Exception e) {
92                 e.printStackTrace();
93             }
94         }
95         return this.executionTime;
96     }
97     
98     public void calExeTime() throws Exception {
99         if(this.classNodes.size() != 1) {
100             throw new Exception("Error: there are multiple ClassNodes inside the ScheduleNode when calculating executionTime");
101         }
102         ClassNode cn = this.classNodes.elementAt(0);
103         if(!cn.isSorted()) {
104             throw new Error("Error: Non-sorted ClassNode!");
105         }
106         this.executionTime = cn.getFlagStates().elementAt(0).getExeTime();
107     }
108     
109     /** Tests for equality of two flagstate objects.
110     */
111     
112     public boolean equals(Object o) {
113         if (o instanceof ScheduleNode) {
114             ScheduleNode fs=(ScheduleNode)o;
115             if(fs.gid == this.gid) {
116                 if(fs.uid != this.uid) {
117                     return false;
118                 }
119             }
120             if ((fs.executionTime != this.executionTime)){ 
121                 return false;
122             }
123             if(fs.classNodes != null) {
124                 if(!fs.classNodes.equals(classNodes)) {
125                     return false;
126                 }
127             } else if(classNodes != null) {
128                 return false;
129             }
130             return true;
131         }
132         return false;
133     }
134
135     public int hashCode() {
136         int hashcode = gid^uid^executionTime;
137         if(this.classNodes != null) {
138             hashcode ^= classNodes.hashCode();
139         }
140         return hashcode;
141     }
142
143     public String getLabel() {
144         return "cluster" + uid;
145     }   
146
147     public String getTextLabel() {
148         String label=null;
149         
150         if (label==null)
151             return " ";
152         return label;
153     }
154     
155     public Object clone(Hashtable<ClassNode, ClassNode> cn2cn, int gid) {
156         ScheduleNode o = null;
157         try {
158             o = (ScheduleNode)super.clone();
159         } catch(CloneNotSupportedException e){
160             e.printStackTrace();
161         }
162         o.uid = ScheduleNode.nodeID++;
163         o.gid = gid;
164         // Clone all the internal ClassNodes and ScheduleEdges
165         Vector<ClassNode> tcns = new Vector<ClassNode>();
166         Vector<ScheduleEdge> tses = new Vector<ScheduleEdge>();
167         int i = 0;
168         for(i = 0; i < this.classNodes.size(); i++) {
169             ClassNode tcn = this.classNodes.elementAt(i);
170             ClassNode cn = (ClassNode)tcn.clone();
171             cn.setScheduleNode(o);
172             tcns.add(cn);
173             cn2cn.put(tcn, cn);
174         }
175         for(i = 0; i < this.scheduleEdges.size(); i++) {
176             ScheduleEdge temp = this.scheduleEdges.elementAt(i);
177             ScheduleEdge se = null;
178             if(!temp.getIsNew()) {
179                 se = new ScheduleEdge(o, "transmit",temp.getFstate(), false, gid);//new ScheduleEdge(o, "transmit",temp.getClassDescriptor(), false, gid);
180             } else {
181                 se = new ScheduleEdge(o, "new",temp.getFstate(), gid);//new ScheduleEdge(o, "new",temp.getClassDescriptor(), gid);
182             }
183             se.setSourceCNode(cn2cn.get(temp.getSourceCNode()));
184             se.setTargetCNode(cn2cn.get(temp.getTargetCNode()));
185             se.setProbability(temp.getProbability());
186             se.setNewRate(temp.getNewRate());
187             se.setTransTime(temp.getTransTime());
188             se.setFEdge(temp.getFEdge());
189             se.setTargetFState(temp.getTargetFState());
190             se.setIsclone(true);
191             tses.add(se);
192         }
193         o.classNodes = tcns;
194         o.scheduleEdges = tses;
195         tcns = null;
196         tses = null;
197         o.inedges = new Vector();
198         o.edges = new Vector();
199
200         return o;
201     }
202     
203     public void mergeSEdge(ScheduleEdge se) {
204         assert(se.getIsNew());
205         
206         Vector<ClassNode> targetCNodes = (Vector<ClassNode>)((ScheduleNode)se.getTarget()).getClassNodes();
207         Vector<ScheduleEdge> targetSEdges = (Vector<ScheduleEdge>)((ScheduleNode)se.getTarget()).getScheduleEdges();
208         
209         for(int i = 0; i <  targetCNodes.size(); i++) {
210             targetCNodes.elementAt(i).setScheduleNode(this);
211         }
212         
213         if(classNodes == null) {
214             classNodes = targetCNodes;
215             scheduleEdges = targetSEdges;
216         } else {
217             if(targetCNodes.size() != 0) {
218                 classNodes.addAll(targetCNodes);
219             }
220             if(targetSEdges.size() != 0) {
221                 scheduleEdges.addAll(targetSEdges);
222             }
223         }
224         targetCNodes = null;
225         targetSEdges = null;
226         
227         scheduleEdges.add(se);
228         se.resetListExeTime();
229         se.getTarget().removeInedge(se);
230         this.removeEdge(se);
231         Iterator it_edges = se.getTarget().edges();
232         while(it_edges.hasNext()) {
233             ScheduleEdge tse = (ScheduleEdge)it_edges.next();
234             tse.setSource(this);
235             this.edges.addElement(tse);
236         }
237         
238         // As all tasks inside one ScheduleNode are executed sequentially,
239         // simply add the execution time of all the ClassNodes inside one ScheduleNode. 
240         if(this.executionTime == -1) {
241             this.executionTime = 0;
242         }
243         this.executionTime += ((ScheduleNode)se.getTarget()).getExeTime();
244     }
245     
246     public void mergeTransEdge(ScheduleEdge se) throws Exception {
247         ScheduleNode sn = (ScheduleNode)se.getTarget();
248         Vector<ClassNode> targetCNodes = (Vector<ClassNode>)sn.getClassNodes();
249         Vector<ScheduleEdge> targetSEdges = (Vector<ScheduleEdge>)sn.getScheduleEdges();
250         
251         for(int i = 0; i <  targetCNodes.size(); i++) {
252             targetCNodes.elementAt(i).setScheduleNode(this);
253         }
254         
255         if(classNodes == null) {
256             classNodes = targetCNodes;
257             scheduleEdges = targetSEdges;
258         } else {
259             if(targetCNodes.size() != 0) {
260                 classNodes.addAll(targetCNodes);
261             }
262             if(targetSEdges.size() != 0) {
263                 scheduleEdges.addAll(targetSEdges);
264             }
265         }
266         targetCNodes = null;
267
268         sn.removeInedge(se);
269         this.removeEdge(se);
270         Iterator it_edges = sn.edges();
271         while(it_edges.hasNext()) {
272             ScheduleEdge tse = (ScheduleEdge)it_edges.next();
273             tse.setSource(this);
274             this.edges.addElement(tse);
275         }
276         
277         // merge the split ClassNode of same class
278         FlagState sfs = se.getFstate();
279         FlagState tfs = se.getTargetFState();
280         ClassNode scn = se.getSourceCNode();
281         ClassNode tcn = se.getTargetCNode();
282         sfs.getEdgeVector().addAll(tfs.getEdgeVector());
283         // merge the subtree whose root is nfs from the whole flag transition tree
284         Vector<FlagState> sfss = scn.getFlagStates();
285         sfss.addAll(tcn.getFlagStates());
286         sfss.removeElement(tfs);
287         classNodes.removeElement(tcn);
288         
289         // flush the exeTime of fs and its ancestors
290         sfs.setExeTime(0);
291         Queue<FlagState> toiterate = new LinkedList<FlagState>();
292         toiterate.add(sfs);
293         while(!toiterate.isEmpty()) {
294             FlagState tmpfs = toiterate.poll();
295             int ttime = tmpfs.getExeTime();
296             Iterator it_inedges = tmpfs.inedges();
297             while(it_inedges.hasNext()) {
298                 FEdge fEdge = (FEdge)it_inedges.next();
299                 FlagState temp = (FlagState)fEdge.getSource();
300                 int time = fEdge.getExeTime() + ttime;
301                 if(temp.getExeTime() > time) {
302                     temp.setExeTime(time);
303                     toiterate.add(temp);
304                 }
305             }
306         }
307         toiterate = null;
308         
309         // redirct internal ScheduleEdge from tcn to scn
310         for(int i = 0; i < targetSEdges.size(); ++i) {
311             ScheduleEdge tmpse = targetSEdges.elementAt(i);
312             if(tmpse.getSourceCNode().equals(tcn)) {
313                 tmpse.setSourceCNode(scn);
314             }
315         }
316         targetSEdges = null;
317         
318         // As all tasks inside one ScheduleNode are executed sequentially,
319         // simply add the execution time of all the ClassNodes inside one ScheduleNode. 
320         if(this.executionTime == -1) {
321             throw new Exception("Error: ScheduleNode without initiate execution time when analysising.");
322         }
323         if(this.executionTime < sn.getExeTime()) {
324             this.executionTime = sn.getExeTime();
325         }
326     }
327 }