package wordlengthoptimization;
import datapath.graph.Graph;
import datapath.graph.operations.BitwidthTransmogrify;
import datapath.graph.operations.ConstantShift;
import datapath.graph.operations.Operation;
import datapath.graph.operations.ShiftMode;
import datapath.graph.operations.TypeConversion;
import datapath.graph.operations.UnaryOperation;
import datapath.graph.type.FixedPoint;
import datapath.graph.type.Type;
import java.util.HashSet;
/**
*
* @author jh
*/
public class RemoveTypeConversion {
/**
* Replaces all type conversions from the given graph with the appropriate
* operations.
* @param graph
*/
public void removeTypeConversions(Graph graph){
for(Operation op : graph.getOperations().toArray(new Operation[0])){
if(op instanceof TypeConversion){
removeUselessTypeConversion((TypeConversion) op, graph);
}
}
for(Operation op : graph.getOperations().toArray(new Operation[0])){
if(op instanceof TypeConversion){
insertSignChange((TypeConversion)op, graph);
}
}
for(Operation op : graph.getOperations().toArray(new Operation[0])){
if(op instanceof TypeConversion){
TypeConversion tc = (TypeConversion)op;
FixedPoint fpi = (FixedPoint)tc.getInputType();
FixedPoint fpo = (FixedPoint)tc.getOutputType();
if(fpi.getBitsize() < fpo.getBitsize()) {
insertBitExtension((TypeConversion)op, graph);
insertFractionShift((TypeConversion)op, graph);
} else {
insertFractionShift((TypeConversion)op, graph);
insertBitExtension((TypeConversion)op, graph);
}
}
}
for(Operation op : graph.getOperations().toArray(new Operation[0])){
if(op instanceof TypeConversion){
}
}
for(Operation op : graph.getOperations().toArray(new Operation[0])){
if(op instanceof TypeConversion){
removeUselessTypeConversion((TypeConversion) op, graph);
}
}
assert !containsTypeConversion(graph);
}
private void insertTrans(UnaryOperation bt, TypeConversion op, Graph graph){
bt.setData(op.getData());
op.replace(op.getData(), bt);
graph.addOperation(bt);
}
private void insertSignChange(TypeConversion op, Graph graph) {
if(op.getInputType().isSigned() && !op.getOutputType().isSigned()) {
// signed -> unsigned
BitwidthTransmogrify bt = new BitwidthTransmogrify();
assert op.getInputType() instanceof FixedPoint;
FixedPoint fp = (FixedPoint)op.getInputType().clone();
fp.setBitsize(fp.getBitsize()-1);
fp.setSigned(false);
bt.setType(fp);
insertTrans(bt, op, graph);
} else if (!op.getInputType().isSigned() && op.getOutputType().isSigned()) {
// unsigned -> signed
BitwidthTransmogrify bt = new BitwidthTransmogrify();
assert op.getInputType() instanceof FixedPoint;
FixedPoint fp = (FixedPoint)op.getInputType().clone();
fp.setBitsize(fp.getBitsize()+1);
bt.setType(fp);
assert bt.getType().isSigned() == false;
insertTrans(bt, op, graph);
BitwidthTransmogrify bt2 = new BitwidthTransmogrify();
bt2.setType(bt.getType().clone());
bt2.getType().setSigned(true);
insertTrans(bt2, op, graph);
}
}
private void removeUselessTypeConversion(TypeConversion op, Graph graph) {
Type inputType = op.getInputType();
Type outputType = op.getOutputType();
Operation data = op.getData();
if(inputType.equals(outputType)) {
// just remove the type conversion
op.removeData();
for(Operation use : op.getUse().toArray(new Operation[0])){
use.replace(op, data);
}
graph.remove(op);
}
}
private void insertBitExtension(TypeConversion op, Graph graph) {
if(op.getInputType().getBitsize() != op.getOutputType().getBitsize()) {
BitwidthTransmogrify bt = new BitwidthTransmogrify();
bt.setType(op.getInputType().clone());
bt.getType().setBitsize(op.getOutputType().getBitsize());
insertTrans(bt, op, graph);
}
}
private void insertFractionShift(TypeConversion op, Graph graph) {
assert op.getInputType() instanceof FixedPoint;
assert op.getOutputType() instanceof FixedPoint;
FixedPoint inputType = (FixedPoint)op.getInputType();
FixedPoint outputType = (FixedPoint)op.getOutputType();
if(inputType.getFractionlength() != outputType.getFractionlength()) {
// insert shift
int shiftAmount = Math.abs(inputType.getFractionlength()-outputType.getFractionlength());
ConstantShift shift = null;
if(inputType.getFractionlength() > outputType.getFractionlength()){
// insert right shift
shift = new ConstantShift(shiftAmount, ShiftMode.Right);
} else {
// insert left shift
shift = new ConstantShift(shiftAmount, ShiftMode.Left);
}
shift.setType(outputType.clone());
shift.getType().setBitsize(inputType.getBitsize());
insertTrans(shift, op, graph);
}
}
private boolean containsTypeConversion(Graph graph) {
for(Operation op : graph.getOperations().toArray(new Operation[0])){
if(op instanceof TypeConversion){
return true;
}
}
return false;
}
}