c9787e32f336b4ba2bce217d4072d78009a7a9de
[IRC.git] / Robust / src / Analysis / TaskStateAnalysis / FlagState.java
1 package Analysis.TaskStateAnalysis;
2
3 import Analysis.Scheduling.ScheduleEdge;
4 import Analysis.TaskStateAnalysis.*;
5 import IR.*;
6 import IR.Tree.*;
7 import IR.Flat.*;
8 import java.util.*;
9 import java.io.*;
10 import Util.GraphNode;
11
12 /** This class is used to hold the flag states that a class in the Bristlecone 
13  *  program can exist in, during runtime.
14  */
15 public class FlagState extends GraphNode implements Cloneable {
16     public static final int ONETAG=1;
17     public static final int NOTAGS=0;
18     public static final int MULTITAGS=-1;
19     
20     private int uid;
21     private static int nodeid=0;
22
23     private final HashSet flagstate;
24     private final ClassDescriptor cd;
25     private final Hashtable<TagDescriptor,Integer> tags;
26     private boolean issourcenode;
27     private Vector tasks;
28     public static final int KLIMIT=2;
29     
30     // jzhou
31     // for static scheduling
32     private int executeTime;
33     private int invokeNum;
34     // for building multicore codes
35     private int andmask;
36     private int checkmask;
37     private boolean setmask;
38     private int iuid;
39     //private boolean isolate;
40     //private Vector<ScheduleEdge> allys;
41
42     /** Class constructor
43      *  Creates a new flagstate with all flags set to false.
44      *  @param cd ClassDescriptor
45      */
46     public FlagState(ClassDescriptor cd) {
47         this.flagstate=new HashSet();
48         this.cd=cd;
49         this.tags=new Hashtable<TagDescriptor,Integer>();
50         this.uid=FlagState.nodeid++;
51         this.issourcenode=false;
52         this.executeTime = -1;
53         this.invokeNum = 0;
54         this.andmask = 0;
55         this.checkmask = 0;
56         this.setmask = false;
57         this.iuid = 0;
58         //this.isolate = true;
59         //this.allys = null;
60     }
61
62     /** Class constructor
63      *  Creates a new flagstate with flags set according to the HashSet.
64      *  If the flag exists in the hashset, it's set to true else set to false.
65      *  @param cd ClassDescriptor
66      *  @param flagstate a <CODE>HashSet</CODE> containing FlagDescriptors
67      */
68     private FlagState(HashSet flagstate, ClassDescriptor cd,Hashtable<TagDescriptor,Integer> tags) {
69         this.flagstate=flagstate;
70         this.cd=cd;
71         this.tags=tags;
72         this.uid=FlagState.nodeid++;
73         this.issourcenode=false;
74         this.executeTime = -1;
75         this.invokeNum = 0;
76     }
77    
78     public int getuid() {
79         return uid;
80     }
81     
82     public int getiuid() {
83         return iuid++;
84     }
85
86     public boolean isSetmask() {
87         return setmask;
88     }
89
90     public void setSetmask(boolean setmask) {
91         this.setmask = setmask;
92     }
93
94     /** Accessor method
95       *  @param fd FlagDescriptor
96       *  @return true if the flagstate contains fd else false.
97       */
98     public boolean get(FlagDescriptor fd) {
99         return flagstate.contains(fd);
100     }
101     
102     /** Checks if the flagstate is a source node. 
103      *  @return true if the flagstate is a sourcenode(i.e. Is the product of an allocation site).
104      */
105       
106     public boolean isSourceNode(){
107         return issourcenode;
108     }
109     
110     /**  Sets the flagstate as a source node. 
111      */
112     public void setAsSourceNode(){
113         if(!issourcenode){
114             issourcenode=true;
115             this.tasks=new Vector();
116         }
117     }
118     
119     public void addAllocatingTask(TaskDescriptor task){
120         tasks.add(task);
121     }
122     
123     public Vector getAllocatingTasks(){
124         return tasks;
125     }
126     
127     
128     public String toString() {
129         return cd.toString()+getTextLabel();
130     }
131
132     /** @return Iterator over the flags in the flagstate.
133      */
134      
135     public Iterator getFlags() {
136         return flagstate.iterator();
137     }
138
139     public int numFlags(){
140         return flagstate.size();
141     }
142     
143     public FlagState[] setTag(TagDescriptor tag, boolean set){
144         HashSet newset1=(HashSet)flagstate.clone();
145         Hashtable<TagDescriptor,Integer> newtags1=(Hashtable<TagDescriptor,Integer>)tags.clone();
146             
147         if (set) {
148             int count=0;
149             if (tags.containsKey(tag))
150                 count=tags.get(tag).intValue();
151             if (count<KLIMIT)
152                 count++;
153             newtags1.put(tag, new Integer(count));
154             return new FlagState[] {new FlagState(newset1, cd, newtags1)};
155         } else {
156             int count=1;
157             if (tags.containsKey(tag))
158                 count=tags.get(tag).intValue();
159             newtags1.put(tag, new Integer(count));
160             if ((count+1)==KLIMIT)
161                 return new FlagState[] {this, new FlagState(newset1, cd, newtags1)};
162             else
163                 return new FlagState[] {new FlagState(newset1, cd, newtags1)};
164         }
165     }
166
167     public FlagState[] setTag(TagDescriptor tag){
168         HashSet newset1=(HashSet)flagstate.clone();
169         Hashtable<TagDescriptor,Integer> newtags1=(Hashtable<TagDescriptor,Integer>)tags.clone();
170             
171         if (tags.containsKey(tag)){
172             //Code could try to remove flag that doesn't exist
173             
174             switch (tags.get(tag).intValue()){
175             case ONETAG:
176                 newtags1.put(tag,new Integer(MULTITAGS));
177                 return new FlagState[] {this, new FlagState(newset1, cd, newtags1)};
178             case MULTITAGS:
179                 return new FlagState[] {this};
180             default:
181                 throw new Error();
182             }
183         } else {
184             newtags1.put(tag,new Integer(ONETAG));
185             return new FlagState[] {new FlagState(newset1,cd,newtags1)};
186         }
187     }
188
189     public int getTagCount(TagDescriptor tag) {
190         if (tags.containsKey(tag))
191             return tags.get(tag).intValue();
192         else return 0;
193     }
194
195     public int getTagCount(String tagtype){
196         return getTagCount(new TagDescriptor(tagtype));
197     }
198     
199     public FlagState[] clearTag(TagDescriptor tag){
200         if (tags.containsKey(tag)){
201             switch(tags.get(tag).intValue()){
202             case ONETAG:
203                 HashSet newset=(HashSet)flagstate.clone();
204                 Hashtable<TagDescriptor,Integer> newtags=(Hashtable<TagDescriptor,Integer>)tags.clone();
205                 newtags.remove(tag);
206                 return new FlagState[]{new FlagState(newset,cd,newtags)};
207                 
208             case MULTITAGS:
209                 //two possibilities - count remains 2 or becomes 1
210                 //2 case
211                 HashSet newset1=(HashSet)flagstate.clone();
212                 Hashtable<TagDescriptor,Integer> newtags1=(Hashtable<TagDescriptor,Integer>)tags.clone();
213                 
214                 //1 case
215                 HashSet newset2=(HashSet)flagstate.clone();
216                 Hashtable<TagDescriptor,Integer> newtags2=(Hashtable<TagDescriptor,Integer>)tags.clone();
217                 newtags1.put(tag,new Integer(ONETAG));
218                 return new FlagState[] {new FlagState(newset1, cd, newtags2),
219                                         new FlagState(newset2, cd, newtags2)};
220             default:
221                 throw new Error();
222             }
223         } else {
224             throw new Error("Invalid Operation: Can not clear a tag that doesn't exist.");
225         }
226     }
227     
228     /** Creates a string description of the flagstate
229      *  e.g.  a flagstate with five flags could look like 01001
230      *  @param flags an array of flagdescriptors.
231      *  @return string representation of the flagstate.
232      */
233     public String toString(FlagDescriptor[] flags)
234     {
235         StringBuffer sb = new StringBuffer(flagstate.size());
236         for(int i=0;i < flags.length; i++)
237             {
238                 if (get(flags[i]))
239                     sb.append(1);
240                 else
241                     sb.append(0);
242             }
243         
244         return new String(sb);
245     }
246     
247         /** Accessor method
248          *  @return returns the classdescriptor of the flagstate.
249          */
250          
251     public ClassDescriptor getClassDescriptor(){
252         return cd;
253     }
254
255         /** Sets the status of a specific flag in a flagstate after cloning it.
256          *  @param      fd FlagDescriptor of the flag whose status is being set.
257          *  @param  status boolean value
258          *  @return the new flagstate with <CODE>fd</CODE> set to <CODE>status</CODE>.
259          */
260          
261     public FlagState setFlag(FlagDescriptor fd, boolean status) {
262         HashSet newset=(HashSet) flagstate.clone();
263         Hashtable<TagDescriptor,Integer> newtags=(Hashtable<TagDescriptor,Integer>)tags.clone();
264         if (status)
265             newset.add(fd);
266         else if (newset.contains(fd)){
267             newset.remove(fd);
268         }
269         
270         return new FlagState(newset, cd, newtags);
271     }
272     
273     /** Tests for equality of two flagstate objects.
274     */
275     
276     public boolean equals(Object o) {
277         if (o instanceof FlagState) {
278             FlagState fs=(FlagState)o;
279             if (fs.cd!=cd)
280                 return false;
281             return (fs.flagstate.equals(flagstate) & fs.tags.equals(tags));
282         }
283         return false;
284     }
285
286     public int hashCode() {
287         return cd.hashCode()^flagstate.hashCode()^tags.hashCode();
288     }
289
290     public String getLabel() {
291         return "N"+uid;
292     }
293     
294     public String getTextLabel() {
295         String label=null;
296         for(Iterator it=getFlags();it.hasNext();) {
297             FlagDescriptor fd=(FlagDescriptor) it.next();
298             if (label==null)
299                 label=fd.toString();
300             else
301                 label+=", "+fd.toString();
302         }
303         for (Enumeration en_tags=getTags();en_tags.hasMoreElements();){
304             TagDescriptor td=(TagDescriptor)en_tags.nextElement();
305             switch (tags.get(td).intValue()){
306             case ONETAG:
307                 if (label==null)
308                     label=td.toString()+"(1)";
309                 else
310                     label+=", "+td.toString()+"(1)";
311                 break;
312             case MULTITAGS:
313                 if (label==null)
314                     label=td.toString()+"(n)";
315                 else
316                     label+=", "+td.toString()+"(n)";
317                 break;
318             default:
319                 break;
320             }
321         }
322         if (label==null)
323             return " ";
324         return label;
325     }
326     
327     public Enumeration getTags(){
328         return tags.keys();
329     }
330     
331     public int getExeTime() {
332         try {
333             if(this.executeTime == -1) {
334                 calExeTime();
335             }
336         } catch (Exception e) {
337             e.printStackTrace();
338             System.exit(0);
339         }
340         return this.executeTime;
341     }
342     
343     public void setExeTime(int exeTime) {
344         this.executeTime = exeTime;
345     }
346     
347     public int getAndmask() {
348         return andmask;
349     }
350
351     public void setAndmask(int andmask) {
352         this.andmask = andmask;
353     }
354
355     public int getCheckmask() {
356         return checkmask;
357     }
358
359     public void setCheckmask(int checkmask) {
360         this.checkmask = checkmask;
361     }
362
363     public void calExeTime() throws Exception {
364         Iterator it = this.edges();
365         if(it.hasNext()) {
366             FEdge fe = (FEdge)it.next();
367             while((fe != null) && (fe.getTarget().equals(this))) {
368                 if(it.hasNext()) {
369                     fe = (FEdge)it.next();
370                 } else {
371                     fe = null;
372                 }
373             }
374             if(fe == null) {
375                 this.executeTime = 0;
376             } else {
377                 if(fe.getExeTime() == -1) {
378                     throw new Exception("Error: Uninitiate FEdge!");
379                 }
380                 this.executeTime = fe.getExeTime() + ((FlagState)fe.getTarget()).getExeTime();
381             }
382         } else {
383             this.executeTime = 0;
384         }
385         while(it.hasNext()) {
386             FEdge fe = (FEdge)it.next();
387             int temp = fe.getExeTime() + ((FlagState)fe.getTarget()).getExeTime();
388             if(temp < this.executeTime) {
389                 this.executeTime = temp;
390             }
391         }
392     }
393     
394     public Object clone() {
395         FlagState o = null;
396         try {
397             o = (FlagState)super.clone();
398         } catch(CloneNotSupportedException e){
399             e.printStackTrace();
400         }
401         o.uid = FlagState.nodeid++;
402         o.edges = new Vector();
403         for(int i = 0; i < this.edges.size(); i++) {
404             o.edges.addElement(this.edges.elementAt(i));
405         }
406         o.inedges = new Vector();
407         for(int i = 0; i < this.inedges.size(); i++) {
408             o.inedges.addElement(this.inedges.elementAt(i));
409         }
410         return o;
411     }
412     
413     public void init4Simulate() {
414         this.invokeNum = 0;
415     }
416     
417     public FEdge process(TaskDescriptor td) {
418         FEdge next = null;
419         this.invokeNum++;
420         // refresh all the expInvokeNum of each edge
421         for(int i = 0; i < this.edges.size(); i++) {
422             next = (FEdge)this.edges.elementAt(i);
423             next.setExpInvokeNum((int)Math.round(this.invokeNum * (next.getProbability() / 100)));
424         }
425         
426         // find the one with the biggest gap between its actual invoke time and the expected invoke time
427         // and associated with task td
428         int index = 0;
429         int gap = 0;
430         for(int i = 0; i < this.edges.size(); i++) {
431             int temp = ((FEdge)this.edges.elementAt(index)).getInvokeNumGap();
432             if((temp > gap) && (next.getTask().equals(td))){
433                 index = i;
434                 gap = temp;
435             }
436         }
437         next = (FEdge)this.edges.elementAt(index);
438         next.process();
439         
440         return next;
441     }
442
443     /*public Vector<ScheduleEdge> getAllys() {
444         return allys;
445     }
446
447     public void addAlly(ScheduleEdge se) {
448         if(this.allys == null) {
449             assert(this.isolate == true);
450             this.isolate = false;
451             this.allys = new Vector<ScheduleEdge>();
452         }
453         this.allys.addElement(se);
454     }
455
456     public boolean isIsolate() {
457         return isolate;
458     }*/
459     
460 }