/*
* 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.UseEdge;
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.VariableShift;
import datapath.graph.type.FixedPoint;
import datapath.graph.type.Type;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Inserts after the word length optimization the required shifts before
* the operations.
*
* @author fs
*/
public class ShiftInserter implements OperationVisitor {
Graph g;
public ShiftInserter(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) {
if (op.getType().getBitsize() != op.getData().getType().getBitsize()) {
BitwidthTransmogrify bt = new BitwidthTransmogrify();
bt.setType(op.getType().clone());
bt.setVisited();
g.insertNode(bt, op.getData(), op);
}
}
@Override
public void visit(Multiplication op) {
/** multiplication contains desired target resolution,
* but multiplier is always bitsize(a) + bitsize(b)
*/
/* save the old type, and reset the multtype to the expected result */
FixedPoint targetType = (FixedPoint) op.getType().clone();
FixedPoint multType = (FixedPoint) op.getType();
FixedPoint fpl = (FixedPoint) op.getLhs().getType();
FixedPoint fpr = (FixedPoint) op.getRhs().getType();
multType.setFractionlength(fpl.getFractionlength() + fpr.getFractionlength());
/* if multiplier is signed, both inputs have to be signed */
if (op.isSigned()) {
if (!fpl.isSigned()) {
BitwidthTransmogrify bt = new BitwidthTransmogrify();
/* insert two, one would do a signextension, which should not happen */
FixedPoint newType = new FixedPoint(fpl.getBitsize() + 1, fpl.getFractionlength(), false);
bt.setType(newType);
g.insertNode(bt, op.getLhs(), op);
bt.setVisited();
bt = new BitwidthTransmogrify();
g.insertNode(bt, op.getLhs(), op);
bt.setVisited();
newType = new FixedPoint(fpl.getBitsize() + 1, fpl.getFractionlength(), true);
bt.setType(newType);
fpl = newType;
}
if (!fpr.isSigned()) {
BitwidthTransmogrify bt = new BitwidthTransmogrify();
g.insertNode(bt, op.getRhs(), op);
bt.setVisited();
FixedPoint newType = new FixedPoint(fpr.getBitsize() + 1, fpr.getFractionlength(), false);
bt.setType(newType);
bt = new BitwidthTransmogrify();
g.insertNode(bt, op.getRhs(), op);
bt.setVisited();
newType = new FixedPoint(fpr.getBitsize() + 1, fpr.getFractionlength(), true);
bt.setType(newType);
fpr = newType;
}
}
int totalBitSize = fpl.getBitsize() + fpr.getBitsize();
if (op.isSigned())
totalBitSize--;
multType.setBitsize(totalBitSize);
/* insert shifter which removes lower bits then transmogrify to select lower bits */
ConstantShift shifter = new ConstantShift(multType.getFractionlength() - targetType.getFractionlength(), (targetType.isSigned()? ShiftMode.SignedRight: ShiftMode.UnsignedRight));
shifter.setType(targetType.clone());
shifter.isVisited();
BitwidthTransmogrify bt = new BitwidthTransmogrify();
bt.setType(targetType);
bt.isVisited();
for (Operation ops : op.getUse().toArray(new Operation[0])) {
ops.replace(op, bt);
}
g.addOperation(bt);
bt.setData(op);
g.insertNode(shifter, op, bt);
}
@Override
public void visit(Add op) {
Operation pred = op.getLhs();
ConstantShift shift = computeShift(pred.getType(), op.getType());
/* only insert shift if necessary */
if (shift != null)
g.insertNode(shift, pred, op);
pred = op.getRhs();
shift = computeShift(pred.getType(), op.getType());
/* only insert shift if necessary */
if (shift != null)
g.insertNode(shift, pred, op);
}
@Override
public void visit(Subtraction op) {
Operation pred = op.getLhs();
ConstantShift shift = computeShift(pred.getType(), op.getType());
/* only insert shift if necessary */
if (shift != null)
g.insertNode(shift, pred, op);
pred = op.getRhs();
shift = computeShift(pred.getType(), op.getType());
/* only insert shift if necessary */
if (shift != null)
g.insertNode(shift, pred, op);
}
@Override
public void visit(Divide op) {
FixedPoint fpl = (FixedPoint) op.getLhs().getType();
FixedPoint fpr = (FixedPoint) op.getRhs().getType();
FixedPoint fpdiv = (FixedPoint) op.getType();
BitwidthTransmogrify bt = new BitwidthTransmogrify();
/** inputs must adjusted to 32 bits */
bt.setType(new FixedPoint(32, fpl.getFractionlength(), op.isSigned()));
bt.setVisited();
g.insertNode(bt, op.getLhs(), op);
int dividePrecision = fpl.getFractionlength() - fpr.getFractionlength();
int necessaryShift = fpdiv.getFractionlength() - dividePrecision;
if (necessaryShift > 0) {
ConstantShift shifter = new ConstantShift(necessaryShift , ShiftMode.Left);
shifter.setVisited();
g.insertNode(shifter, bt, op);
}
bt = new BitwidthTransmogrify();
bt.setVisited();
bt.setType(new FixedPoint(32, 0, op.isSigned()));
g.insertNode(bt, op.getRhs(), op);
}
@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) {
}
@Override
public void visit(Absolut op) {
}
@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) {
BitwidthTransmogrify bt = new BitwidthTransmogrify();
/** input must be adjusted to 32 bits, and prec of input must be a multiple of 2 */
FixedPoint prev = (FixedPoint) op.getData().getType();
bt.setType(new FixedPoint(32, prev.getFractionlength(), op.isSigned()));
bt.setVisited();
g.insertNode(bt, op.getData(), op);
/* in case input is no multiple of 2 add shift */
if ((prev.getFractionlength() %2 ) == 1) {
ConstantShift shift = new ConstantShift(1, ShiftMode.Left);
g.insertNode(shift, bt, op);
shift.setVisited();
}
/* now fix the output */
FixedPoint fpsqrt = (FixedPoint) op.getType();
if (fpsqrt.getBitsize() < 32) {
bt = new BitwidthTransmogrify();
bt.setType(op.getType().clone());
bt.setVisited();
for (Operation ops : op.getUse().toArray(new Operation[0])) {
ops.replace(op, bt);
}
bt.setData(op);
g.addOperation(bt);
fpsqrt.setBitsize(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);
}
}