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 public String toString() {
266 StringBuffer sb = new StringBuffer("Size=");
267 sb.append(masks.length).append('\n');
268 for (int[] mask : masks) {
269 for (int v : mask)
270 sb.append(toBinaryPad32(v)).append('\n');
271 sb.append('\n');
272 }
273 return sb.toString();
274 }
275
276 // For internal use only.
277 private void allocateMasks(ResourceReservation[] pat) {
278 ResourceReservation.sort(pat);
279 int maxlen = 0;
280 int size = 1;
281 ResourceReservation r = new ResourceReservation(-1, -1, -1000);
282 int len = -1;
283 OperatorClass[] rss = new OperatorClass[N];
284 for (ResourceReservation p : pat) {
285 rss[p.rclass()] = res2class[p.rclass()];
286 boolean same = p.equals(r);
287 if (!p.conflicts(r)) {
288 r = p;
289 if (r.isGlobal())
290 len = 1;
291 else
292 len = resources[r.rclass()].length - 1;
293 } else if (r.isGlobal()) {
294 throw new InternalError("Insufficient Resources");
295 } else {
296 len--;
297 }
298 size *= len;
299 if (same)
300 size /= 2;
301 if (p.start + p.duration > maxlen)
302 maxlen = p.start + p.duration;
303 }
304 rclasses.add(any_insn);
305 for (int i = 0; i < N; i++)
306 if (rss[i] != null)
307 rclasses.add(rss[i]);
308 masks = new int[size][];
309 for (int i = 0; i < size; i++)
310 masks[i] = new int[maxlen];
311 }
312
313 // For internal debug use only.
314 static int depth = 0;
315
316 // For internal use only.
317 private int fillMasks(ResourceReservation[] pat, int[] assign,
318 int all, int rrq, int comb) {
319 if (rrq == pat.length) {
320 for (int i = 0; i < masks[comb].length; i++)
321 masks[comb][i] = 0;
322 StringBuffer dbSB;
323 if (verbose >= 1) dbSB = new StringBuffer();
324 for (int i = 0; i < pat.length; i++) {
325 ResourceReservation pi = pat[i];
326 int rc = pi.rclass();
327 int mask = resources[rc][assign[i]];
328 if (verbose >= 1) dbSB.append(toBinaryPad32(mask)).append(" ");
329 for (int j = 0; j < pi.duration; j++)
330 masks[comb][pi.start + j] |= mask;
331 if (maxlat < pi.duration)
332 maxlat = pi.duration;
333 }
334 if (verbose >= 1) debug(dbSB.toString());
335 return comb + 1;
336 }
337 int rc = pat[rrq].rclass();
338 int start = 0;
339 int end = resources[rc].length - 1;
340 if (rrq != 0 && pat[rrq].equals(pat[rrq-1]))
341 start = assign[rrq-1] + 1;
342 boolean ignore = ((rrq != 0 && !pat[rrq].conflicts(pat[rrq-1])) ||
343 pat[rrq].isGlobal());
344 if (pat[rrq].isGlobal()) {
345 start = end;
346 end++;
347 }
348
349 for (int i = start; i < end; i++)
350 if (ignore || (resources[rc][i] & all) == 0) {
351 if (verbose >= 2) debug(depth, rrq+": Res#"+rc+"; Trying "+i+
352 "; reserved='"+toBinaryPad32(all)+"'");
353
354 depth++;
355 assign[rrq] = i;
356 comb = fillMasks(pat, assign, all | resources[rc][i], rrq+1, comb);
357 depth--;
358 }
359
360 return comb;
361 }
362
363 // Generates a string of a given length filled by a given character.
364 // For internal use only.
365 private static String dup(int len, char c) {
366 StringBuffer sb = new StringBuffer();
367 for (int i = 0; i < len; i++)
368 sb.append(c);
369 return sb.toString();
370 }
371 }