package de.gaalop.codegen_verilog.VerilogIR; import datapath.graph.DeadTreeElimination; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import java.util.HashMap; import datapath.graph.Graph; import datapath.graph.GreedySchedule; import datapath.graph.ModlibWriter; import datapath.graph.Schedule; import datapath.graph.TestbenchCreator; import datapath.graph.display.dot.DotDisplayFactory; import datapath.graph.operations.*; import datapath.graph.operations.UnaryOperation; import datapath.graph.type.FixedPoint; import de.gaalop.cfg.*; import de.gaalop.dfg.*; import de.gaalop.dfg.Subtraction; import de.gaalop.dfg.BinaryOperation; import de.gaalop.dfg.Multiplication; import de.gaalop.dfg.Negation; import java.util.Map.Entry; import wordlengthoptimization.*; import datapath.graph.operations.constValue.*; public class VerilogIRConverterVisitorCookies implements ExpressionVisitor, ControlFlowVisitor { private HashMap<AssignmentNode, Operation> assginmentToOperation = new HashMap<AssignmentNode, Operation>(); private HashMap<String, AssignmentNode> stringToAssignmentNode = new HashMap<String, AssignmentNode>(); private HashMap<Variable, TopLevelInput> variableToHWInput = new HashMap(); // private HashSet<VerilogNode> allnodes = new HashSet<VerilogNode>(); private Graph g = new Graph(); private ControlFlowGraph formerGraph; String result; String lastcomponent; Operation toappend; VerilogDFG dfg; boolean isVariable = true; private static final int ADDITION = 1; private static final int SUBTRACTION = 2; private static final int MULTIPLICATION = 3; private static final int MULTIPLICATION_const = 7; private static final int DIVISION = 4; private static final int EXPONENTIATION = 5; private static final int EXPONENTIATIONSquare = 6; private LoopInit l; public VerilogIRConverterVisitorCookies(VerilogDFG dfg) { super(); this.dfg = dfg; // dfg.getCfg().accept(this); System.out.println("Starting VerilogIR Converter"); } public String getResult() { return result; } @Override public void visit(Subtraction node) { System.out.println("MySubVisit"); visitbinary(node, SUBTRACTION); } public void visit(Relation rel) { System.err.println("Relation in VerilogIRConverterVisitorCookies not yet supported!"); } public void visit(Inequality inequal) { System.err.println("Inequality in VerilogIRConverterVisitorCookies not yet supported!"); } public void visit(Equality equal) { System.err.println("Equality in VerilogIRConverterVisitorCookies not yet supported!"); } public void visit(LogicalAnd logand) { System.err.println("LogicalAnd in VerilogIRConverterVisitorCookies not yet supported!"); } public void visit(LogicalOr logand) { System.err.println("LogicalOr in VerilogIRConverterVisitorCookies not yet supported!"); } public void visit(BlockEndNode node) { System.err.println("BlockEndNode in VerilogIRConverterVisitorCookies not yet supported!"); } public void visit(IfThenElseNode node) { System.err.println("IfThenElseNode in VerilogIRConverterVisitorCookies not yet supported!"); } public void visitbinary(BinaryOperation node, int operation) { System.out.println("MyBinaryVisit"); node.getLeft().accept(this); Operation lhs = toappend; node.getRight().accept(this); Operation rhs = toappend; switch (operation) { case ADDITION: toappend = new Add(); break; case SUBTRACTION: System.out.println("subtraction"); toappend = new datapath.graph.operations.Subtraction(); break; case MULTIPLICATION: toappend = new datapath.graph.operations.Multiplication(); break; case MULTIPLICATION_const: toappend = new datapath.graph.operations.ConstantMultiplication(); break; case DIVISION: toappend = new Divide(); /* detect normalisation, is a hack atm, better would be search for abs() function */ if (node.getRight() instanceof Variable) { Variable v = (Variable) node.getRight(); if (v.getName().toLowerCase().contains("norm")) { // ((Divide) toappend).setNormalization(true); System.out.println("Normalisation detected"); } } break; default: System.err.println("not supported Binary Operation: " + operation); assert false; break; } //cast Operation ( (datapath.graph.operations.BinaryOperation) toappend).setLHS(lhs); ((datapath.graph.operations.BinaryOperation) toappend).setRHS(rhs); addToGraph(toappend); } @Override public void visit(Addition node) { System.out.println("MyAddVisit"); visitbinary(node, ADDITION); } @Override public void visit(Division node) { System.out.println("MyDivVisit"); if (isPowerOf2(node.getRight())) { int toshift = Integer.numberOfTrailingZeros((int) ((FloatConstant) node.getRight()).getValue()); node.getLeft().accept(this); Operation tobedivided = toappend; ConstantShift cs = new ConstantShift(toshift, ShiftMode.Right); cs.setData(tobedivided); toappend = cs; addToGraph(cs); }else{ visitbinary(node, DIVISION); }} @Override public void visit(InnerProduct node) { // TODO Auto-generated method stub } private boolean isSquare(Exponentiation exponentiation) { final FloatConstant two = new FloatConstant(2.0f); return two.equals(exponentiation.getRight()); } private boolean isSqrt(Exponentiation exp) { final FloatConstant one = new FloatConstant(1.0f); final FloatConstant two = new FloatConstant(2.0f); final FloatConstant half = new FloatConstant(0.5f); if(exp.getRight() instanceof FloatConstant) { return exp.getRight().equals(half); } if(exp.getRight() instanceof Division) { Division div = (Division)exp.getRight(); if(div.getLeft().equals(one) && div.getRight().equals(two)) return true; } return false; } @Override public void visit(Multiplication node) { System.out.println("MyMultVisit"); if (isPowerOf2(node.getLeft())) { int toshift = Integer.numberOfTrailingZeros((int) ((FloatConstant) node.getLeft()).getValue()); node.getRight().accept(this); Operation rhs = toappend; ConstantShift cs = new ConstantShift(toshift, ShiftMode.Left); cs.setData(rhs); toappend = cs; addToGraph(cs); //toappend = New ConstantShift(); } else if (isPowerOf2(node.getRight())) { int toshift = Integer.numberOfTrailingZeros((int) ((FloatConstant) node.getRight()).getValue()); node.getLeft().accept(this); Operation lhs = toappend; ConstantShift cs = new ConstantShift(toshift, ShiftMode.Left); cs.setData(lhs); toappend = cs; addToGraph(cs); } else { // if(node.getRight() instanceof FloatConstant || node.getLeft() instanceof FloatConstant) { // visitbinary(node, MULTIPLICATION_const); // } else { visitbinary(node, MULTIPLICATION); // } } } // private boolean isPowerOf2(Expression node) { // throw new UnsupportedOperationException("Not yet implemented"); // } public boolean isPowerOf2(Expression node) { double f; int fi; if (node instanceof FloatConstant) { f = ((FloatConstant) node).getValue(); fi = (int) ((FloatConstant) node).getValue(); if ((fi >=2) &&(f == fi) && (Integer.bitCount(fi) == 1 )) { return true; } else { return false; } } else { return false; } } private boolean mathfunctionHack; @Override public void visit(MathFunctionCall node) { System.out.println("MyMathFuncVisit"); mathfunctionHack = true; node.getOperand().accept(this); mathfunctionHack = false; UnaryOperation newOp; switch (node.getFunction()) { case SQRT: newOp = new SquareRoot(); break; case ABS: newOp = new Absolut(); break; case ACOS: newOp = new ArcCos(); break; case COS: newOp = new Cos(); break; case SIN: newOp = new Sin(); break; default: throw new UnsupportedOperationException("Math function " + node.toString() + " not supported."); } newOp.setData(toappend); toappend = newOp; addToGraph(toappend); } @Override public void visit(Variable exnode) { System.out.println("MyExpression/VariableNodeVisit Eingangswerte " + exnode.getName()); // HWInput hw = new HWInput(exnode); // top.setSource(hw); lastcomponent = exnode.getName(); if(mathfunctionHack) { if(!lastcomponent.contains("CSE")) lastcomponent = lastcomponent+"0"; } if (variableToHWInput.containsKey(exnode)) { toappend = variableToHWInput.get(exnode); } else if(isVariable == false && (getAssignmentToOperationMap().get( getStringToAssignment().get(lastcomponent)) != null)) { toappend = getAssignmentToOperationMap().get( getStringToAssignment().get(lastcomponent)); } else if(isVariable == true) { // lastcomponent is already set } else { System.out.println(variableToHWInput); System.out.println(""); System.out.println(getStringToAssignment().keySet()); assert false : "should not happen " + exnode + " " + lastcomponent; // HWInput hw = new HWInput(exnode); // TopLevelInput top = new TopLevelInput(); // top.setSource(hw); // top.setName(exnode.getName()); // if (exnode.getMinValue() != null) { // double min = Double.parseDouble(exnode.getMinValue()); // double max = Double.parseDouble(exnode.getMaxValue()); // int prec = Math.max(wordlengthoptimization.Util.bitsRequiredForFraction(exnode.getMinValue()), // wordlengthoptimization.Util.bitsRequiredForFraction(exnode.getMaxValue())); // hw.setType(new FixedPoint(wordlengthoptimization.Util.bitsRequired(min, max) + prec, prec, min < 0)); // top.setType(hw.getType()); // } // addToGraph(hw); // toappend = top; // addToGraph(toappend); // variableToHWInput.put(exnode, top); } } @Override public void visit(MultivectorComponent mc) { System.out.println("MyComponentVisit"); StringBuilder temp = new StringBuilder(); temp.append(mc.getName()); temp.append(mc.getBladeIndex()); // VerilogVariableNode newnode =new VerilogVariableNode(dfg); // newnode.setNode(mc); // newnode.setVarname(temp.toString()); lastcomponent = temp.toString(); System.out.println(lastcomponent); toappend = null; if (isVariable == false) { // getAssignmentToNodeMap().get(getStringToNode().get(lastcomponent)).appendDFGNode(newnode); toappend = getAssignmentToOperationMap().get( getStringToAssignment().get(lastcomponent)); } } @Override public void visit(Exponentiation exnode) { System.out.println("MyExponentiationNodeVisit"); // if (isSquare(exnode)) { // visitbinary(exnode, EXPONENTIATIONSquare); // } //else if(isSqrt(exnode)) { System.out.println("found stupid other sqrt"); UnaryOperation newOp; newOp = new SquareRoot(); exnode.getLeft().accept(this); assert toappend != null; newOp.setData(toappend); toappend = newOp; } else { assert exnode.getRight() instanceof FloatConstant; FloatConstant c = (FloatConstant)exnode.getRight(); assert (c.getValue() - (double)(new Double(c.getValue())).intValue() == 0f); int exponent = (int)c.getValue(); assert exponent >= 2 : "assert exponent >= 2 error: exponent="+exponent; exnode.getLeft().accept(this); assert toappend != null; Operation op = toappend; datapath.graph.operations.Multiplication lastM = new datapath.graph.operations.Multiplication(); lastM.setLHS(op); lastM.setRHS(op); exponent -= 2; while(exponent > 0) { datapath.graph.operations.Multiplication newM = new datapath.graph.operations.Multiplication(); newM.setRHS(lastM); newM.setLHS(op); lastM = newM; addToGraph(newM); exponent--; } toappend = lastM; } assert toappend != null; addToGraph(toappend); } @Override public void visit(FloatConstant fcnode) { System.out.println("MyFloatConstantVisit"); // VerilogFloatNode newnode =new VerilogFloatNode(dfg); // FPValue fpv = new FPValue(fcnode.getValue(),32,16); // ConstantOperation co = new // ConstantOperation(Integer.toString((int)fpv.getBinaryvalue())); // VerilogFloatNode newnode =new VerilogFloatNode(dfg); // ConstantOperation co = new ConstantOperation(Float.toString(fcnode // .getValue())); FloatValue value = new FloatValue(); value.setValue(new Float(fcnode.getValue()).floatValue()); ConstantOperation co = new ConstantOperation(value, fcnode.toString()); co.setOutputBitsize(32); // newnode.setValue(fcnode.getValue()); toappend = co; addToGraph(toappend); } @Override public void visit(OuterProduct opnode) { throw new UnsupportedOperationException( "The Verilog backend does not support Outer Products"); } @Override public void visit(BaseVector node) { throw new UnsupportedOperationException( "The Verilog backend does not support base vectors."); } @Override public void visit(Negation node) { System.out.println("MyNegationVisit"); node.getOperand().accept(this); datapath.graph.operations.Negation n = new datapath.graph.operations.Negation(); n.setData(toappend); toappend = n; addToGraph(toappend); } @Override public void visit(Reverse node) { throw new UnsupportedOperationException( "The Verilog backend does not support the reverse operation."); } @Override public void visit(StartNode node) { System.out.println("MyStartVisit"); formerGraph = node.getGraph(); l = new LoopInit(); LoopEnd le = new LoopEnd(); Predicate x = new Predicate(Predicate.TYPE.INIT); le.addPredicate(x); x.setData(l); g.addOperation(l); g.addOperation(x); g.addOperation(le); // Input Parameters for (Variable exnode : node.getGraph().getInputVariables()) { HWInput hw = new HWInput(exnode); TopLevelInput top = new TopLevelInput(); top.setSource(hw); top.setName(exnode.getName()); if (exnode.getMinValue() != null) { double min = Double.parseDouble(exnode.getMinValue()); double max = Double.parseDouble(exnode.getMaxValue()); int prec = Math.max(wordlengthoptimization.Util.bitsRequiredForFraction(exnode.getMinValue()), wordlengthoptimization.Util.bitsRequiredForFraction(exnode.getMaxValue())); hw.setType(new FixedPoint(wordlengthoptimization.Util.bitsRequired(min, max) + prec, prec, min < 0)); top.setType(hw.getType()); } addToGraph(hw); addToGraph(top); System.out.println("adding InputVariable " + exnode); variableToHWInput.put(exnode, top); } node.getSuccessor().accept(this); } @Override public void visit(AssignmentNode node) { System.out.println("MyAssignmentVisit"); isVariable = true; System.out.println("---------Getting Variable----------"); node.getVariable().accept(this); getStringToAssignment().put(lastcomponent, node); String debug = lastcomponent; isVariable = false; System.out.println("---------Getting Value----------"); node.getValue().accept(this); assert toappend != null : "toappend nicht null"; getAssignmentToOperationMap().put(node, toappend); toappend.setDebugMessage(debug); // new VerilogNode(dfg); node.getSuccessor().accept(this); } @Override public void visit(StoreResultNode node) { System.out.println("MyStoreResultVisit"); node.getSuccessor().accept(this); // TODO Auto-generated method stub } @Override public void visit(EndNode node) { System.out.println("Fertig mit Graph"); // add ouptut Nodes for (Entry<AssignmentNode, Operation> iterable_element : assginmentToOperation .entrySet()) { HWOutput out = new HWOutput(); out.setName(iterable_element.getKey().getVariable().toString() .replace("[", "").replace("]", "")); out.setData(iterable_element.getValue()); Predicate ptemp = new Predicate(Predicate.TYPE.INIT); g.addOperation(ptemp); ptemp.setData(l); out.addPredicate(ptemp); g.addOperation(out); } Schedule s = new GreedySchedule(); /* store helping information from the old graph in the options */ Options opts = new Options(); opts.setStartVariableMinValues(formerGraph.getPragmaMinValue()); opts.setStartVariableMaxValues(formerGraph.getPragmaMaxValue()); opts.setOutputVariables(formerGraph.getPragmaOutputVariables()); DeadTreeElimination dte = new DeadTreeElimination(g, opts.getOutputVariables()); dte.perform(); WordLengthGUI dialog = new WordLengthGUI(null, true, opts); dialog.setVisible(true); WordlengthOptimization w = opts.getSelectedOptimizer(); w.setOptions(opts); System.out.println("Wordlength optimization (" + w + ") finished. Changed " + w.optimize(g) + " nodes"); wordlengthoptimization.Util.fixHWInputs(g); s.scheduleAll(g); g.display(new DotDisplayFactory()); for(ParentOutput out : g.getOutput()){ System.out.println("building graph for "+out.getName()); g.display(new DotDisplayFactory(), out); } try { StringWriter x = new StringWriter(); ModlibWriter.write(g, new BufferedWriter(new FileWriter( "testoutput.v"))); ModlibWriter.write(g, new BufferedWriter(x)); result = x.toString(); TestbenchCreator.writeTestbench(g, new BufferedWriter( new FileWriter("testbench.v"))); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // tellWithout(); } public HashMap<AssignmentNode, Operation> getAssignmentToOperationMap() { return assginmentToOperation; } public HashMap<String, AssignmentNode> getStringToAssignment() { return stringToAssignmentNode; } public void addToGraph(Operation n) { assert n != null; System.out.println("Adding Node to CookieGraph: " + n.getClass().getSimpleName()); g.addOperation(n); } @Override public void visit(LogicalNegation node) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(FunctionArgument node) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(MacroCall node) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(LoopNode node) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(BreakNode node) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(Macro node) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(ExpressionStatement node) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void visit(ColorNode node) { throw new UnsupportedOperationException("Not supported yet."); } // public void pumpoutGraph(){ // // for (VerilogNode iterable_element : allnodes) { // System.out.println("test pump: " + iterable_element.getVarname() ); // // } // // } // public void tellWithout(){ // // for (VerilogNode iterable_element : allnodes) { // if (iterable_element.getPredecessors().length==0) { // System.out.println("test pump: " + iterable_element.getVarname() + // " hat keinen Vorgaenger" ); // // } // } // // } }