/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
//OPT_OperatorClass.java
package org.jikesrvm.compilers.opt;
import org.jikesrvm.*;
import org.jikesrvm.compilers.opt.ir.*;
import java.util.ArrayList;
/**
* Generated from a template.
* Consists of an operator class and information about resource usage
* There is only one instance of each OPT_OperatorClass, which is stored
* as a static final field in OPT_OperatorClass. You can compare
* OPT_OperatorClasses using ==.
* Every OPT_Operator contains one of these.
*
* @see OPT_Operator
* @see OPT_Operators
*/
public final class OPT_OperatorClass implements OPT_Operators {
// debug level (0 = no debug)
private static final int verbose = 0;
private static void debug(String s) {
System.err.println(s);
}
private static String SPACES = null;
private static void debug(int depth, String s) {
if (SPACES == null) SPACES = dup(7200, ' ');
debug(SPACES.substring(0,depth*2)+s);
}
// Padding
// For internal use only.
private static final String ZEROS = dup(32, '0');
private static String toBinaryPad32(int value) {
String s = Integer.toBinaryString(value);
return ZEROS.substring(s.length())+s;
}
// Returns a special resource type embodying all resources of a given class.
// For internal use only.
private static int all_units(int rclass) { return rclass | 0x80000000; }
/**
* Empty Resources Mask
*/
static int NONE = 0;
/**
* All Resources Mask
*/
static int ALL = 0; // will be filled in
// Generates an array of resource masks, and updating the static field
// ALL to contain all of the masks.
// For internal use only.
private static int M = 1; // current mask
private static int[] genMasks(int number) {
int[] rs = new int[number + 1];
int rall = 0;
for (int i = 0; i < number; i++) {
if (VM.VerifyAssertions && M == 0)
throw new InternalError("Exceeded 32 resources");
//System.err.println("Scheduler: Resource "+M);
rs[i] = M;
ALL |= M;
rall |= M;
M <<= 1;
}
rs[number] = rall;
return rs;
}
/**
* Resource Masks
*/
private static final int[][] resources = {
null
};
/**
* Total number of resources
*/
static final int N = resources.length - 1;
/**
* Resource Names
*/
private static final String[] resource_names = {
null
};
/**
* Resources
*/
/**
* Id of the operator class
*/
private int id = 0;
/**
* Maximum Latency of any instruction
*/
private int maxlat = 0;
/**
* Returns the maximum latency of any instruction in the class.
* Note: it is faster to simply check the field directly, if possible.
*/
public int maxLatency() { return maxlat; }
/**
* Latencies to other classes
*/
private final ArrayList<Integer> latencies;
// Returns latency lookup in the hashtable for a given operator class.
// For internal use only.
private Object latObj(OPT_OperatorClass opclass) {
int latsize = latencies.size();
Object latObj = null;
if (latsize > opclass.id) latObj = latencies.get(opclass.id);
// walk through backwards, since any_insn (most general) is first
ArrayList<OPT_OperatorClass> opcrc = opclass.rclasses;
for (int i = opcrc.size(); latObj == null && i > 0; i--) {
OPT_OperatorClass rc = opcrc.get(i - 1);
if (latsize > rc.id) latObj = latencies.get(rc.id);
}
for (int i = rclasses.size(); latObj == null && i > 0; i--) {
OPT_OperatorClass rc = rclasses.get(i - 1);
latObj = rc.latObj(opclass);
}
return latObj;
}
/**
* Sets the operator class (for hierarchy)
*
* @param opClass operator class
*/
public void setOpClass(OPT_OperatorClass opClass) {
rclasses.add(opClass);
}
/**
* Returns the latency between instructions in this class and given class
*
* @param opclass destination operator class
* @return latency to given operator class
*/
public int latency(OPT_OperatorClass opclass) {
return (Integer) latObj(opclass);
}
/**
* Sets the latency between instructions in this class and given class
*
* @param opclass destination operator class
* @param latency desired latency
*/
public void setLatency(OPT_OperatorClass opclass, int latency) {
int latencies_size = latencies.size();
if (opclass.id < latencies_size) {
latencies.set(opclass.id, latency);
}
else {
for(; latencies_size < opclass.id; latencies_size++) {
latencies.add(null);
}
latencies.add(latency);
}
}
/**
* Sets the latency between instructions in given class and this class
*
* @param opclass source operator class
* @param latency desired latency
*/
public void setRevLatency(OPT_OperatorClass opclass, int latency) {
opclass.setLatency(this, latency);
}
/*
* Operator Classes
*/
// Global class embodying all operator classes. For internal use only.
private static final OPT_OperatorClass any_insn = new OPT_OperatorClass(0);
/**
* Map from resource to operator class representing that resource
*/
private static OPT_OperatorClass[] res2class = {
null
};
private static final OPT_OperatorClass
pseudo_ops = new OPT_OperatorClass(
0+N+1,
new OPT_ResourceReservation[] {
}
);
static {
LABEL.setOpClass(pseudo_ops);
BBEND.setOpClass(pseudo_ops);
UNINT_BEGIN.setOpClass(pseudo_ops);
UNINT_END.setOpClass(pseudo_ops);
pseudo_ops.setLatency(any_insn, 0);
}
/**
* Resource Classes used by this Operator Class
*/
final ArrayList<OPT_OperatorClass> rclasses;
/**
* Resource Usage Masks
*/
int[][] masks;
// For internal use only.
private OPT_OperatorClass(int _id) {
id = _id;
rclasses = new ArrayList<OPT_OperatorClass>();
latencies = new ArrayList<Integer>();
}
// For internal use only.
private OPT_OperatorClass(int _id, OPT_ResourceReservation[] pat) {
this(_id);
allocateMasks(pat);
if (verbose >= 2) debug(masks.length+" masks allocated for "+pat.length+
" requests");
int[] assign = new int[pat.length];
int comb = fillMasks(pat, assign, 0, 0, 0);
if (false && comb != masks.length)
throw new InternalError("Insufficient Resources");
}
/**
* Returns the string representation of this operator class.
*/
public String toString() {
StringBuffer sb = new StringBuffer("Size=");
sb.append(masks.length).append('\n');
for (int[] mask : masks) {
for (int v : mask)
sb.append(toBinaryPad32(v)).append('\n');
sb.append('\n');
}
return sb.toString();
}
// For internal use only.
private void allocateMasks(OPT_ResourceReservation[] pat) {
OPT_ResourceReservation.sort(pat);
int maxlen = 0;
int size = 1;
OPT_ResourceReservation r = new OPT_ResourceReservation(-1, -1, -1000);
int len = -1;
OPT_OperatorClass[] rss = new OPT_OperatorClass[N];
for (OPT_ResourceReservation p : pat) {
rss[p.rclass()] = res2class[p.rclass()];
boolean same = p.equals(r);
if (!p.conflicts(r)) {
r = p;
if (r.isGlobal())
len = 1;
else
len = resources[r.rclass()].length - 1;
} else if (r.isGlobal()) {
throw new InternalError("Insufficient Resources");
} else {
len--;
}
size *= len;
if (same)
size /= 2;
if (p.start + p.duration > maxlen)
maxlen = p.start + p.duration;
}
rclasses.add(any_insn);
for (int i = 0; i < N; i++)
if (rss[i] != null)
rclasses.add(rss[i]);
masks = new int[size][];
for (int i = 0; i < size; i++)
masks[i] = new int[maxlen];
}
// For internal debug use only.
static int depth = 0;
// For internal use only.
private int fillMasks(OPT_ResourceReservation[] pat, int[] assign,
int all, int rrq, int comb) {
if (rrq == pat.length) {
for (int i = 0; i < masks[comb].length; i++)
masks[comb][i] = 0;
StringBuffer dbSB;
if (verbose >= 1) dbSB = new StringBuffer();
for (int i = 0; i < pat.length; i++) {
OPT_ResourceReservation pi = pat[i];
int rc = pi.rclass();
int mask = resources[rc][assign[i]];
if (verbose >= 1) dbSB.append(toBinaryPad32(mask)).append(" ");
for (int j = 0; j < pi.duration; j++)
masks[comb][pi.start + j] |= mask;
if (maxlat < pi.duration)
maxlat = pi.duration;
}
if (verbose >= 1) debug(dbSB.toString());
return comb + 1;
}
int rc = pat[rrq].rclass();
int start = 0;
int end = resources[rc].length - 1;
if (rrq != 0 && pat[rrq].equals(pat[rrq-1]))
start = assign[rrq-1] + 1;
boolean ignore = ((rrq != 0 && !pat[rrq].conflicts(pat[rrq-1])) ||
pat[rrq].isGlobal());
if (pat[rrq].isGlobal()) {
start = end;
end++;
}
for (int i = start; i < end; i++)
if (ignore || (resources[rc][i] & all) == 0) {
if (verbose >= 2) debug(depth, rrq+": Res#"+rc+"; Trying "+i+
"; reserved='"+toBinaryPad32(all)+"'");
depth++;
assign[rrq] = i;
comb = fillMasks(pat, assign, all | resources[rc][i], rrq+1, comb);
depth--;
}
return comb;
}
// Generates a string of a given length filled by a given character.
// For internal use only.
private static String dup(int len, char c) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < len; i++)
sb.append(c);
return sb.toString();
}
}