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