001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 //OperatorClass.java 014 package org.jikesrvm.compilers.opt.instrsched; 015 016 import org.jikesrvm.*; 017 import org.jikesrvm.compilers.opt.ir.*; 018 import java.util.ArrayList; 019 020 /** 021 * Generated from a template. 022 * Consists of an operator class and information about resource usage 023 * There is only one instance of each OperatorClass, which is stored 024 * as a static final field in OperatorClass. You can compare 025 * OperatorClasses using ==. 026 * Every Operator contains one of these. 027 * 028 * @see Operator 029 * @see Operators 030 */ 031 public final class OperatorClass implements Operators { 032 033 // debug level (0 = no debug) 034 private static final int verbose = 0; 035 036 private static void debug(String s) { 037 System.err.println(s); 038 } 039 private static String SPACES = null; 040 private static void debug(int depth, String s) { 041 if (SPACES == null) SPACES = dup(7200, ' '); 042 debug(SPACES.substring(0,depth*2)+s); 043 } 044 045 // Padding 046 // For internal use only. 047 private static final String ZEROS = dup(32, '0'); 048 private static String toBinaryPad32(int value) { 049 String s = Integer.toBinaryString(value); 050 return ZEROS.substring(s.length())+s; 051 } 052 053 // Returns a special resource type embodying all resources of a given class. 054 // For internal use only. 055 private static int all_units(int rclass) { return rclass | 0x80000000; } 056 057 /** 058 * Empty Resources Mask 059 */ 060 static int NONE = 0; 061 062 /** 063 * All Resources Mask 064 */ 065 static int ALL = 0; // will be filled in 066 067 // Generates an array of resource masks, and updating the static field 068 // ALL to contain all of the masks. 069 // For internal use only. 070 private static int M = 1; // current mask 071 private static int[] genMasks(int number) { 072 int[] rs = new int[number + 1]; 073 int rall = 0; 074 for (int i = 0; i < number; i++) { 075 if (VM.VerifyAssertions && M == 0) 076 throw new InternalError("Exceeded 32 resources"); 077 //System.err.println("Scheduler: Resource "+M); 078 rs[i] = M; 079 ALL |= M; 080 rall |= M; 081 M <<= 1; 082 } 083 rs[number] = rall; 084 return rs; 085 } 086 087 /** 088 * Resource Masks 089 */ 090 private static final int[][] resources = { 091 null 092 }; 093 094 /** 095 * Total number of resources 096 */ 097 static final int N = resources.length - 1; 098 099 /** 100 * Resource Names 101 */ 102 private static final String[] resource_names = { 103 null 104 }; 105 106 /** 107 * Resources 108 */ 109 110 111 /** 112 * Id of the operator class 113 */ 114 private int id = 0; 115 116 /** 117 * Maximum Latency of any instruction 118 */ 119 private int maxlat = 0; 120 121 /** 122 * Returns the maximum latency of any instruction in the class. 123 * Note: it is faster to simply check the field directly, if possible. 124 */ 125 public int maxLatency() { return maxlat; } 126 127 /** 128 * Latencies to other classes 129 */ 130 private final ArrayList<Integer> latencies; 131 132 // Returns latency lookup in the hashtable for a given operator class. 133 // For internal use only. 134 private Object latObj(OperatorClass opclass) { 135 int latsize = latencies.size(); 136 Object latObj = null; 137 if (latsize > opclass.id) latObj = latencies.get(opclass.id); 138 139 // walk through backwards, since any_insn (most general) is first 140 ArrayList<OperatorClass> opcrc = opclass.rclasses; 141 for (int i = opcrc.size(); latObj == null && i > 0; i--) { 142 OperatorClass rc = opcrc.get(i - 1); 143 if (latsize > rc.id) latObj = latencies.get(rc.id); 144 } 145 146 for (int i = rclasses.size(); latObj == null && i > 0; i--) { 147 OperatorClass rc = rclasses.get(i - 1); 148 latObj = rc.latObj(opclass); 149 } 150 151 return latObj; 152 } 153 154 /** 155 * Sets the operator class (for hierarchy) 156 * 157 * @param opClass operator class 158 */ 159 public void setOpClass(OperatorClass opClass) { 160 rclasses.add(opClass); 161 } 162 163 /** 164 * Returns the latency between instructions in this class and given class 165 * 166 * @param opclass destination operator class 167 * @return latency to given operator class 168 */ 169 public int latency(OperatorClass opclass) { 170 return (Integer) latObj(opclass); 171 } 172 173 /** 174 * Sets the latency between instructions in this class and given class 175 * 176 * @param opclass destination operator class 177 * @param latency desired latency 178 */ 179 public void setLatency(OperatorClass opclass, int latency) { 180 int latencies_size = latencies.size(); 181 if (opclass.id < latencies_size) { 182 latencies.set(opclass.id, latency); 183 } 184 else { 185 for(; latencies_size < opclass.id; latencies_size++) { 186 latencies.add(null); 187 } 188 latencies.add(latency); 189 } 190 } 191 /** 192 * Sets the latency between instructions in given class and this class 193 * 194 * @param opclass source operator class 195 * @param latency desired latency 196 */ 197 public void setRevLatency(OperatorClass opclass, int latency) { 198 opclass.setLatency(this, latency); 199 } 200 201 /* 202 * Operator Classes 203 */ 204 205 // Global class embodying all operator classes. For internal use only. 206 private static final OperatorClass any_insn = new OperatorClass(0); 207 208 209 /** 210 * Map from resource to operator class representing that resource 211 */ 212 private static OperatorClass[] res2class = { 213 null 214 }; 215 216 private static final OperatorClass 217 pseudo_ops = new OperatorClass( 218 0+N+1, 219 new ResourceReservation[] { 220 } 221 ); 222 static { 223 LABEL.setOpClass(pseudo_ops); 224 BBEND.setOpClass(pseudo_ops); 225 UNINT_BEGIN.setOpClass(pseudo_ops); 226 UNINT_END.setOpClass(pseudo_ops); 227 228 229 pseudo_ops.setLatency(any_insn, 0); 230 231 } 232 233 /** 234 * Resource Classes used by this Operator Class 235 */ 236 final ArrayList<OperatorClass> rclasses; 237 238 /** 239 * Resource Usage Masks 240 */ 241 int[][] masks; 242 243 // For internal use only. 244 private OperatorClass(int _id) { 245 id = _id; 246 rclasses = new ArrayList<OperatorClass>(); 247 latencies = new ArrayList<Integer>(); 248 } 249 250 // For internal use only. 251 private OperatorClass(int _id, ResourceReservation[] pat) { 252 this(_id); 253 allocateMasks(pat); 254 if (verbose >= 2) debug(masks.length+" masks allocated for "+pat.length+ 255 " requests"); 256 int[] assign = new int[pat.length]; 257 int comb = fillMasks(pat, assign, 0, 0, 0); 258 if (false && comb != masks.length) 259 throw new InternalError("Insufficient Resources"); 260 } 261 262 /** 263 * Returns the string representation of this operator class. 264 */ 265 @Override 266 public String toString() { 267 StringBuffer sb = new StringBuffer("Size="); 268 sb.append(masks.length).append('\n'); 269 for (int[] mask : masks) { 270 for (int v : mask) 271 sb.append(toBinaryPad32(v)).append('\n'); 272 sb.append('\n'); 273 } 274 return sb.toString(); 275 } 276 277 // For internal use only. 278 private void allocateMasks(ResourceReservation[] pat) { 279 ResourceReservation.sort(pat); 280 int maxlen = 0; 281 int size = 1; 282 ResourceReservation r = new ResourceReservation(-1, -1, -1000); 283 int len = -1; 284 OperatorClass[] rss = new OperatorClass[N]; 285 for (ResourceReservation p : pat) { 286 rss[p.rclass()] = res2class[p.rclass()]; 287 boolean same = p.equals(r); 288 if (!p.conflicts(r)) { 289 r = p; 290 if (r.isGlobal()) 291 len = 1; 292 else 293 len = resources[r.rclass()].length - 1; 294 } else if (r.isGlobal()) { 295 throw new InternalError("Insufficient Resources"); 296 } else { 297 len--; 298 } 299 size *= len; 300 if (same) 301 size /= 2; 302 if (p.start + p.duration > maxlen) 303 maxlen = p.start + p.duration; 304 } 305 rclasses.add(any_insn); 306 for (int i = 0; i < N; i++) 307 if (rss[i] != null) 308 rclasses.add(rss[i]); 309 masks = new int[size][]; 310 for (int i = 0; i < size; i++) 311 masks[i] = new int[maxlen]; 312 } 313 314 // For internal debug use only. 315 static int depth = 0; 316 317 // For internal use only. 318 private int fillMasks(ResourceReservation[] pat, int[] assign, 319 int all, int rrq, int comb) { 320 if (rrq == pat.length) { 321 for (int i = 0; i < masks[comb].length; i++) 322 masks[comb][i] = 0; 323 StringBuffer dbSB; 324 if (verbose >= 1) dbSB = new StringBuffer(); 325 for (int i = 0; i < pat.length; i++) { 326 ResourceReservation pi = pat[i]; 327 int rc = pi.rclass(); 328 int mask = resources[rc][assign[i]]; 329 if (verbose >= 1) dbSB.append(toBinaryPad32(mask)).append(" "); 330 for (int j = 0; j < pi.duration; j++) 331 masks[comb][pi.start + j] |= mask; 332 if (maxlat < pi.duration) 333 maxlat = pi.duration; 334 } 335 if (verbose >= 1) debug(dbSB.toString()); 336 return comb + 1; 337 } 338 int rc = pat[rrq].rclass(); 339 int start = 0; 340 int end = resources[rc].length - 1; 341 if (rrq != 0 && pat[rrq].equals(pat[rrq-1])) 342 start = assign[rrq-1] + 1; 343 boolean ignore = ((rrq != 0 && !pat[rrq].conflicts(pat[rrq-1])) || 344 pat[rrq].isGlobal()); 345 if (pat[rrq].isGlobal()) { 346 start = end; 347 end++; 348 } 349 350 for (int i = start; i < end; i++) 351 if (ignore || (resources[rc][i] & all) == 0) { 352 if (verbose >= 2) debug(depth, rrq+": Res#"+rc+"; Trying "+i+ 353 "; reserved='"+toBinaryPad32(all)+"'"); 354 355 depth++; 356 assign[rrq] = i; 357 comb = fillMasks(pat, assign, all | resources[rc][i], rrq+1, comb); 358 depth--; 359 } 360 361 return comb; 362 } 363 364 // Generates a string of a given length filled by a given character. 365 // For internal use only. 366 private static String dup(int len, char c) { 367 StringBuffer sb = new StringBuffer(); 368 for (int i = 0; i < len; i++) 369 sb.append(c); 370 return sb.toString(); 371 } 372 }