/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package wordlengthoptimization; import datapath.graph.Graph; import datapath.graph.OperationVisitor; import datapath.graph.operations.*; import datapath.graph.operations.Add; import datapath.graph.operations.ArcCos; import datapath.graph.operations.BinaryOperation; import datapath.graph.operations.BitwidthTransmogrify; import datapath.graph.operations.ConstantOperation; import datapath.graph.operations.ConstantShift; import datapath.graph.operations.Cos; import datapath.graph.operations.Divide; import datapath.graph.operations.FromOuterLoop; import datapath.graph.operations.HWInput; import datapath.graph.operations.HWOutput; import datapath.graph.operations.Less; import datapath.graph.operations.Loop; import datapath.graph.operations.LoopEnd; import datapath.graph.operations.LoopInit; import datapath.graph.operations.MemWrite; import datapath.graph.operations.Multiplication; import datapath.graph.operations.Mux; import datapath.graph.operations.Negation; import datapath.graph.operations.Nop; import datapath.graph.operations.Operation; import datapath.graph.operations.Predicate; import datapath.graph.operations.ShiftMode; import datapath.graph.operations.Sin; import datapath.graph.operations.SquareRoot; import datapath.graph.operations.Subtraction; import datapath.graph.operations.ToInnerLoop; import datapath.graph.operations.ToOuterLoop; import datapath.graph.operations.TopLevelInput; import datapath.graph.operations.TypeConversion; import datapath.graph.operations.UnaryOperation; import datapath.graph.operations.VariableShift; import datapath.graph.type.FixedPoint; import datapath.graph.type.Type; import java.util.logging.Level; import java.util.logging.Logger; /** * Inserts required type conversions between operations * * @author fs */ public class ShiftInserterNewTypeCast implements OperationVisitor { Graph g; /* inserts a node after op in to the Graph g the node toInsert is also added to the graph and set as visited */ protected void addToOutput(Operation op, UnaryOperation toInsert) { for (Operation ops : op.getUse().toArray(new Operation[0])) { ops.replace(op, toInsert); } toInsert.setData(op); g.addOperation(toInsert); toInsert.setVisited(); } /* inserts a node before op, after prev into the Graph g the node toInsert is also added to the graph and set as visited */ protected void addToInput(Operation op, Operation prev, UnaryOperation toInsert) { g.insertNode(toInsert, prev, op); toInsert.setVisited(); } public ShiftInserterNewTypeCast(Graph g) { this.g = g; } /** * Computes the necessary shift to convert from one type ton another * @param before Type before shift * @param after Result type after shift * @return A shifter which performs the necessary operation, or null if no shift * is necessary. */ private ConstantShift computeShift(Type before, Type after) { if ((!(before instanceof FixedPoint)) || (!(after instanceof FixedPoint))) { throw new UnsupportedOperationException("Only Fixed Point Types supported in Word length optimizations / ShiftInserter"); } FixedPoint beforeFp = (FixedPoint) before; FixedPoint afterFp = (FixedPoint) after; int predDiff = beforeFp.getFractionlength() - afterFp.getFractionlength(); ConstantShift shifter; if (predDiff == 0) return null; if (predDiff > 0) shifter = new ConstantShift(predDiff, beforeFp.isSigned() ? ShiftMode.SignedRight : ShiftMode.UnsignedRight); else shifter = new ConstantShift(-predDiff, ShiftMode.Left); // mark the node as visited, because new inserted must not be visited shifter.setVisited(); return shifter; } @Override public void visit(VariableShift op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(Negation op) { /* Negation must be always defined as signed, so the output has also to be fixed */ FixedPoint oldType = (FixedPoint) op.getType(); if (!oldType.isSigned()) { FixedPoint newType = new FixedPoint(oldType.getBitsize() + 1, oldType.getFractionlength(), true); TypeConversion typeCast = new TypeConversion(oldType); op.setType(newType); addToOutput(op, typeCast); oldType = newType; } /* now fix input */ FixedPoint inputType = (FixedPoint)oldType.clone(); TypeConversion typeCast = new TypeConversion(inputType); addToInput(op, op.getData(), typeCast); } @Override public void visit(Multiplication op) { /** multiplication contains desired target resolution, * but multiplier is always bitsize(a) + bitsize(b) */ FixedPoint oldType = (FixedPoint) op.getType(); FixedPoint fpl = (FixedPoint) op.getLhs().getType(); FixedPoint fpr = (FixedPoint) op.getRhs().getType(); /* if multiplier is signed, both inputs have to be signed */ if (op.isSigned()) { if (!fpl.isSigned()) { fpl = new FixedPoint(fpl.getBitsize() + 1, fpl.getFractionlength(), true); TypeConversion typeCast = new TypeConversion(fpl); addToInput(op, op.getLhs(), typeCast); } if (!fpr.isSigned()) { fpr = new FixedPoint(fpr.getBitsize() + 1, fpr.getFractionlength(), true); TypeConversion typeCast = new TypeConversion(fpr); addToInput(op, op.getRhs(), typeCast); } } int totalBitSize = fpl.getBitsize() + fpr.getBitsize(); if (op.isSigned()) totalBitSize--; FixedPoint newType = new FixedPoint(totalBitSize, fpl.getFractionlength() + fpr.getFractionlength(), oldType.isSigned()); TypeConversion typeCast = new TypeConversion(oldType); op.setType(newType); addToOutput(op, typeCast); } @Override public void visit(Add op) { /* if signed, we sign extend the inputs */ FixedPoint input = (FixedPoint) op.getType().clone(); input.setBitsize(input.getBitsize()); input.setSigned(op.isSigned()); TypeConversion typeCast = new TypeConversion(input.clone()); addToInput(op, op.getLhs(), typeCast); typeCast = new TypeConversion(input.clone()); addToInput(op, op.getRhs(), typeCast); } @Override public void visit(Subtraction op) { /* if signed, we sign extend the inputs */ FixedPoint input = (FixedPoint) op.getType().clone(); input.setBitsize(input.getBitsize()); input.setSigned(op.isSigned()); TypeConversion typeCast = new TypeConversion(input.clone()); addToInput(op, op.getLhs(), typeCast); typeCast = new TypeConversion(input.clone()); addToInput(op, op.getRhs(), typeCast); } /* in a divide it is tried to balance the left and right inputs for their * precision, in case the inputs must be adjusted to match the desired output * length */ private void increaseDivisionPrecision(FixedPoint left, FixedPoint right) { /* check which has lower precision */ } @Override public void visit(Divide op) { /** inputs must adjusted to 32 bits */ FixedPoint fpl = (FixedPoint) op.getLhs().getType().clone(); FixedPoint fpr = (FixedPoint) op.getRhs().getType().clone(); FixedPoint oldType = (FixedPoint) op.getType(); FixedPoint resultType = (FixedPoint)oldType.clone(); oldType.setBitsize(64); oldType.setFractionlength(32); /* in case they are bigger, reduce them */ //fpl.restrictBitwidth(32); fpr.restrictBitwidth(32); /* in case they are are smaller than 32 bit, set them to 32 bit */ fpl.setBitsize(32); fpr.setBitsize(32); /* divs are always signed */ fpl.setSigned(true); fpr.setSigned(true); /* left is always 1 */ fpl.setFractionlength(30); if (fpl.getFractionlength() > fpr.getFractionlength()) { oldType.setFractionlength(32 + (fpl.getFractionlength() - fpr.getFractionlength())); } else { fpr.setFractionlength(fpl.getFractionlength()); } //resultType = new FixedPoint(1+ oldType.getFractionlength() + resultType.getIntBits(), oldType.getFractionlength(), true); /* cheat, TODO: program a sophisticated algorithm, or a lookuptable for all 32 x 32 values if (fpl.getFractionlength() == 14 && fpr.getFractionlength() == 14) { fpl.setFractionlength(22); fpr.setFractionlength(8); } else if (fpr.getFractionlength() >= 22) { fpl.setFractionlength(22); fpr.setFractionlength(8); }else if (fpr.getFractionlength() >= 20) { fpl.setFractionlength(20); fpr.setFractionlength(6); } else { System.out.println("DIV bitwdith determination not finished"); System.out.println("Missing parameter for combination: " + fpl + " and " +fpr); assert(false); } */ /* int dividePrecision = fpl.getFractionlength() - fpr.getFractionlength(); int missingPrecision = oldType.getFractionlength() - dividePrecision; int fixright = missingPrecision; int fixleft = missingPrecision/2; fixright -=fixleft; fpr.setFractionlength(fpr.getFractionlength() + fixright); fpl.setFractionlength(fpl.getFractionlength() - fixleft); if (fpl.getFractionlength() < 0) { fpr.setFractionlength(-fpl.getFractionlength()); fpl.setFractionlength(0); } if (fpr.getFractionlength() < 0) { fpl.setFractionlength(-fpr.getFractionlength()); fpr.setFractionlength(0); } */ TypeConversion typeCast = new TypeConversion(fpl); addToInput(op, op.getLhs(), typeCast); typeCast = new TypeConversion(fpr); addToInput(op, op.getRhs(), typeCast); /* fix output */ typeCast = new TypeConversion(resultType); addToOutput(op, typeCast); } @Override public void visit(Operation op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(BinaryOperation op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(Mux op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(ConstantOperation op) { // Nothing to do } @Override public void visit(MemWrite op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(Less op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(FromOuterLoop op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(ToInnerLoop op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(HWInput op) { // Nothing to do } @Override public void visit(Loop op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(Nop op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(ToOuterLoop op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(LoopEnd op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(LoopInit op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(HWOutput op) { // Nothing to do } @Override public void visit(TopLevelInput op) { // Nothing to do } @Override public void visit(ConstantShift op) { FixedPoint input = (FixedPoint) op.getType().clone(); FixedPoint prev = (FixedPoint) op.getData().getType(); input.setFractionlength(prev.getFractionlength()); if (op.getMode() == ShiftMode.ZeroShiftRight && input.getIntBits() == 0) { input.setFractionlength(input.getFractionlength() - op.getShiftAmount()); } TypeConversion typeCast = new TypeConversion(input); addToInput(op, op.getData(), typeCast); } @Override public void visit(Absolut op) { FixedPoint input = (FixedPoint) op.getType().clone(); input.setSigned(true); TypeConversion typeCast = new TypeConversion(input); addToInput(op, op.getData(), typeCast); } @Override public void visit(Sin op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(Cos op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(ArcCos op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(SquareRoot op) { /** input must be adjusted to 32 bits, and prec of input must be a multiple of 2 */ FixedPoint oldType = (FixedPoint) op.getType(); FixedPoint input = (FixedPoint) op.getData().getType().clone(); input.setToBitwidth(32); if (input.getFractionlength() % 2 == 1) { input.setFractionlength(input.getFractionlength() - 1); } TypeConversion typeCast = new TypeConversion(input); addToInput(op, op.getData(), typeCast); /* now fix the output */ typeCast = new TypeConversion(oldType.clone()); addToOutput(op, typeCast); oldType.setFractionlength(input.getFractionlength() / 2); oldType.setBitsize(32); assert(input.getFractionlength() <= 32); } @Override public void visit(BitwidthTransmogrify op) { } @Override public void visit(Predicate op) { // do nothing } @Override public void visit(TypeConversion op) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(ConstantMultiplication op) { visit((Multiplication)op); } }