package synthesijer.scheduler;
import synthesijer.ast.Type;
import synthesijer.ast.type.PrimitiveTypeKind;
public enum Op {
METHOD_ENTRY(true),
METHOD_EXIT,
ASSIGN,
NOP,
ADD,
SUB,
MUL32(1),
MUL64(1),
DIV32(1),
DIV64(1),
MOD32(1),
MOD64(1),
LT(PrimitiveTypeKind.BOOLEAN),
LEQ(PrimitiveTypeKind.BOOLEAN),
GT(PrimitiveTypeKind.BOOLEAN),
GEQ(PrimitiveTypeKind.BOOLEAN),
COMPEQ(PrimitiveTypeKind.BOOLEAN),
NEQ(PrimitiveTypeKind.BOOLEAN),
SIMPLE_LSHIFT32(PrimitiveTypeKind.INT),
SIMPLE_LOGIC_RSHIFT32(PrimitiveTypeKind.INT),
SIMPLE_ARITH_RSHIFT32(PrimitiveTypeKind.INT),
SIMPLE_LSHIFT64(PrimitiveTypeKind.LONG),
SIMPLE_LOGIC_RSHIFT64(PrimitiveTypeKind.LONG),
SIMPLE_ARITH_RSHIFT64(PrimitiveTypeKind.LONG),
LSHIFT32(false, 1, PrimitiveTypeKind.INT),
LOGIC_RSHIFT32(false, 1, PrimitiveTypeKind.INT),
ARITH_RSHIFT32(false, 1, PrimitiveTypeKind.INT),
LSHIFT64(false, 1, PrimitiveTypeKind.LONG),
LOGIC_RSHIFT64(false, 1, PrimitiveTypeKind.LONG),
ARITH_RSHIFT64(false, 1, PrimitiveTypeKind.LONG),
JP(true),
JT(true),
RETURN(true),
MULTI_RETURN(true),
SELECT(true), // switch selector
AND,
NOT,
MSB_FLAP,
LAND,
LOR,
OR,
XOR,
LNOT,
ARRAY_ACCESS(1),
ARRAY_ACCESS_WAIT,
ARRAY_ACCESS0,
ARRAY_INDEX,
FIFO_WRITE,
CALL(true),
EXT_CALL(true),
FIELD_ACCESS,
BREAK,
CONTINUE,
CAST,
COND,
FADD32(1),
FSUB32(1),
FMUL32(1),
FDIV32(1),
FADD64(1),
FSUB64(1),
FMUL64(1),
FDIV64(1),
CONV_F2I(1),
CONV_I2F(1),
CONV_D2L(1),
CONV_L2D(1),
CONV_F2D(1),
CONV_D2F(1),
FLT32(false, 1, PrimitiveTypeKind.BOOLEAN),
FLEQ32(false, 1, PrimitiveTypeKind.BOOLEAN),
FGT32(false, 1, PrimitiveTypeKind.BOOLEAN),
FGEQ32(false, 1, PrimitiveTypeKind.BOOLEAN),
FCOMPEQ32(false, 1, PrimitiveTypeKind.BOOLEAN),
FNEQ32(false, 1, PrimitiveTypeKind.BOOLEAN),
FLT64(false, 1, PrimitiveTypeKind.BOOLEAN),
FLEQ64(false, 1, PrimitiveTypeKind.BOOLEAN),
FGT64(false, 1, PrimitiveTypeKind.BOOLEAN),
FGEQ64(false, 1, PrimitiveTypeKind.BOOLEAN),
FCOMPEQ64(false, 1, PrimitiveTypeKind.BOOLEAN),
FNEQ64(false, 1, PrimitiveTypeKind.BOOLEAN),
UNDEFINED;
public final boolean isBranch;
public final int latency;
public final Type type;
/**
*
* @param flag branch instruction or not
* @param latency fixed clock latency
* @param type result type
*/
private Op(boolean flag, int latency, Type type){
this.isBranch = flag;
this.latency = latency;
this.type = type;
}
/**
*
* @param latency fixed clock latency
*/
private Op(int latency){
this(false, latency, PrimitiveTypeKind.UNDEFINED);
}
/**
*
* @param flag branch instruction or not
*/
private Op(boolean flag){
this(flag, 0, PrimitiveTypeKind.UNDEFINED);
}
/**
*
* @param type return type
*/
private Op(Type type){
this(false, 0, type);
}
/**
* Default constructor: not branch, latency=0, type=UNDEFINED
*/
private Op(){
this(false, 0, PrimitiveTypeKind.UNDEFINED);
}
private static boolean isFloat(Operand operand){
Type t = operand.getType();
if(t instanceof PrimitiveTypeKind == false) return false;
return t == PrimitiveTypeKind.FLOAT;
}
private static boolean isDouble(Operand operand){
Type t = operand.getType();
if(t instanceof PrimitiveTypeKind == false) return false;
return t == PrimitiveTypeKind.DOUBLE;
}
private static boolean isLong(Operand operand){
Type t = operand.getType();
if(t instanceof PrimitiveTypeKind == false) return false;
return t == PrimitiveTypeKind.LONG;
}
private static boolean isInt(Operand operand){
Type t = operand.getType();
if(t instanceof PrimitiveTypeKind == false) return false;
return t == PrimitiveTypeKind.INT;
}
public static Op get(synthesijer.ast.Op o, Operand lhs, Operand rhs){
switch(o){
case PLUS: {
if(isDouble(lhs) || isDouble(rhs)) return FADD64;
else if(isFloat(lhs) || isFloat(rhs)) return FADD32;
else return ADD;
}
case MINUS: {
if(isDouble(lhs) || isDouble(rhs)) return FSUB64;
else if(isFloat(lhs) || isFloat(rhs)) return FSUB32;
else return SUB;
}
case MUL: {
if(isDouble(lhs) || isDouble(rhs)) return FMUL64;
else if(isFloat(lhs) || isFloat(rhs)) return FMUL32;
if(isLong(lhs) || isLong(rhs)) return MUL64;
else return MUL32;
}
case DIV: {
if(isDouble(lhs) || isDouble(rhs)) return FDIV64;
if(isFloat(lhs) || isFloat(rhs)) return FDIV32;
if(isLong(lhs) || isLong(rhs)) return DIV64;
else return DIV32;
}
case MOD: {
if(isLong(lhs) || isLong(rhs)) return MOD64;
else return MOD32;
}
case LSHIFT: {
if(rhs instanceof ConstantOperand){
if(isLong(lhs) || isDouble(lhs)){
return SIMPLE_LSHIFT64;
}else{
return SIMPLE_LSHIFT32;
}
}
if(isLong(lhs)) return LSHIFT64;
else return LSHIFT32;
}
case LOGIC_RSHIFT: {
if(rhs instanceof ConstantOperand){
if(isLong(lhs) || isDouble(lhs)){
return SIMPLE_LOGIC_RSHIFT64;
}else{
return SIMPLE_LOGIC_RSHIFT32;
}
}
if(isLong(lhs)) return LOGIC_RSHIFT64;
else return LOGIC_RSHIFT32;
}
case ARITH_RSHIFT: {
if(rhs instanceof ConstantOperand){
if(isLong(lhs) || isDouble(lhs)){
return SIMPLE_ARITH_RSHIFT64;
}else{
return SIMPLE_ARITH_RSHIFT32;
}
}
if(isLong(lhs)) return ARITH_RSHIFT64;
else return ARITH_RSHIFT32;
}
case COMPEQ:{
if(isDouble(lhs) || isDouble(rhs)) return FCOMPEQ64;
else if(isFloat(lhs) || isFloat(rhs)) return FCOMPEQ32;
else return COMPEQ;
}
case NEQ:{
if(isDouble(lhs) || isDouble(rhs)) return FNEQ64;
else if(isFloat(lhs) || isFloat(rhs)) return FNEQ32;
else return NEQ;
}
case GT:{
if(isDouble(lhs) || isDouble(rhs)) return FGT64;
else if(isFloat(lhs) || isFloat(rhs)) return FGT32;
else return GT;
}
case LT:{
if(isDouble(lhs) || isDouble(rhs)) return FLT64;
else if(isFloat(lhs) || isFloat(rhs)) return FLT32;
else return LT;
}
case GEQ:{
if(isDouble(lhs) || isDouble(rhs)) return FGEQ64;
else if(isFloat(lhs) || isFloat(rhs)) return FGEQ32;
else return GEQ;
}
case LEQ:{
if(isDouble(lhs) || isDouble(rhs)) return FLEQ64;
else if(isFloat(lhs) || isFloat(rhs)) return FLEQ32;
else return LEQ;
}
default:
return get(o);
}
}
public static Op get(synthesijer.ast.Op o){
switch(o){
case ASSIGN:
case PLUS: return ADD;
case MINUS: return SUB;
case MUL: return MUL32;
case DIV: return DIV32;
case MOD: return MOD32;
case COMPEQ: return COMPEQ;
case NEQ: return NEQ;
case GT: return GT;
case LT: return LT;
case GEQ: return GEQ;
case LEQ: return LEQ;
case LSHIFT: return LSHIFT32;
case LOGIC_RSHIFT: return LOGIC_RSHIFT32;
case ARITH_RSHIFT: return ARITH_RSHIFT32;
case AND: return AND;
case NOT: return NOT;
case LAND: return LAND;
case LOR: return LOR;
case OR: return OR;
case XOR: return XOR;
case LNOT: return LNOT;
default:
System.out.println("undefiend:" + o);
return UNDEFINED;
}
}
public boolean isForcedType(){
return (type != PrimitiveTypeKind.UNDEFINED);
}
public Type getType(){
return type;
}
public static Op parseOp(String k) throws Exception{
switch(k){
case "METHOD_ENTRY": return METHOD_ENTRY;
case "METHOD_EXIT" : return METHOD_EXIT;
case "ASSIGN" : return ASSIGN;
case "NOP" : return NOP;
case "ADD" : return ADD;
case "SUB" : return SUB;
case "MUL32" : return MUL32;
case "MUL64" : return MUL64;
case "DIV32" : return DIV32;
case "DIV64" : return DIV64;
case "MOD32" : return MOD32;
case "MOD64" : return MOD64;
case "LT" : return LT;
case "LEQ" : return LEQ;
case "GT" : return GT;
case "GEQ" : return GEQ;
case "COMPEQ" : return COMPEQ;
case "NEQ" : return NEQ;
case "SIMPLE_LSHIFT32" : return SIMPLE_LSHIFT32;
case "SIMPLE_LOGIC_RSHIFT32" : return SIMPLE_LOGIC_RSHIFT32;
case "SIMPLE_ARITH_RSHIFT32" : return SIMPLE_ARITH_RSHIFT32;
case "SIMPLE_LSHIFT64" : return SIMPLE_LSHIFT64;
case "SIMPLE_LOGIC_RSHIFT64" : return SIMPLE_LOGIC_RSHIFT64;
case "SIMPLE_ARITH_RSHIFT64" : return SIMPLE_ARITH_RSHIFT64;
case "LSHIFT32" : return LSHIFT32;
case "LOGIC_RSHIFT32": return LOGIC_RSHIFT32;
case "ARITH_RSHIFT32" : return ARITH_RSHIFT32;
case "LSHIFT64" : return LSHIFT64;
case "LOGIC_RSHIFT64" : return LOGIC_RSHIFT64;
case "ARITH_RSHIFT64" : return ARITH_RSHIFT64;
case "JP" : return JP;
case "JT" : return JT;
case "RETURN" : return RETURN;
case "MULTI_RETURN" : return MULTI_RETURN;
case "SELECT" : return SELECT;
case "AND" : return AND;
case "NOT" : return NOT;
case "MSB_FLAP": return MSB_FLAP;
case "LAND" : return LAND;
case "LOR" : return LOR;
case "OR" : return OR;
case "XOR" : return XOR;
case "LNOT" : return LNOT;
case "ARRAY_ACCESS" : return ARRAY_ACCESS;
case "ARRAY_INDEX" : return ARRAY_INDEX;
case "CALL" : return CALL;
case "EXT_CALL" : return EXT_CALL;
case "FIELD_ACCESS" : return FIELD_ACCESS;
case "BREAK" : return BREAK;
case "CONTINUE" : return CONTINUE;
case "CAST" : return CAST;
case "COND" : return COND;
case "FADD32" : return FADD32;
case "FSUB32" : return FSUB32;
case "FMUL32" : return FMUL32;
case "FDIV32" : return FDIV32;
case "FADD64" : return FADD64;
case "FSUB64" : return FSUB64;
case "FMUL64" : return FMUL64;
case "FDIV64" : return FDIV64;
case "CONV_F2I" : return CONV_F2I;
case "CONV_I2F" : return CONV_I2F;
case "CONV_D2L" : return CONV_D2L;
case "CONV_L2D" : return CONV_L2D;
case "CONV_F2D" : return CONV_F2D;
case "CONV_D2F" : return CONV_D2F;
case "FLT32" : return FLT32;
case "FLEQ32" : return FLEQ32;
case "FGT32" : return FGT32;
case "FGEQ32" : return FGEQ32;
case "FCOMPEQ32" : return FCOMPEQ32;
case "FNEQ32" : return FNEQ32;
case "FLT64" : return FLT64;
case "FLEQ64" : return FLEQ64;
case "FGT64" : return FGT64;
case "FGEQ64" : return FGEQ64;
case "FCOMPEQ64" : return FCOMPEQ64;
case "FNEQ64" : return FNEQ64;
case "FIFO_WRITE" : return FIFO_WRITE;
case "UNDEFINED" : return UNDEFINED;
default:
throw new Exception("Undefined operation : " + k);
}
}
}