package com.sun.electric.tool.generator.flag.hornFunnel2; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.database.topology.ArcInst; import com.sun.electric.database.topology.NodeInst; import com.sun.electric.database.topology.PortInst; import com.sun.electric.technology.ArcProto; import com.sun.electric.technology.PrimitiveNode; import com.sun.electric.technology.Technology; import com.sun.electric.tool.generator.layout.LayoutLib; import com.sun.electric.tool.Job; public class BinaryTree { private static final double DEF_SIZE = LayoutLib.DEF_SIZE; private final boolean SLANTED_EDGES = true; private static final Technology SCHEM_TECH = Technology.findTechnology("schematic"); private static final PrimitiveNode SCH_ICON_PROTO = SCHEM_TECH.findNodeProto("Buffer"); private static final PrimitiveNode DOT_ICON_PROTO = SCHEM_TECH.findNodeProto("Wire_Pin"); private static final ArcProto LINE_PROTO = SCHEM_TECH.findArcProto("Wire"); private final int SLOT_WID = 6; private final int SLOT_HEI = 24; private List<Node> slots; private final int height; private final int numSlots; private final Node root; private void prln(String s) {System.out.println(s);} private void pr(String s) {System.out.print(s);} private List<Node> makeSlots(int nbSlots) { List<Node> slots = new ArrayList<Node>(); for (int i=0; i<nbSlots; i++) slots.add(null); return slots; } private void drawExternalArc(Cell c, Map<Node, NodeInst> nodeToInst) { int dotX = -SLOT_WID; int dotY = (height+1) * (SLOT_HEI); NodeInst dot = LayoutLib.newNodeInst(DOT_ICON_PROTO, dotX, dotY, DEF_SIZE, DEF_SIZE, 0, c); PortInst dotPi = dot.getOnlyPortInst(); PortInst inPi = nodeToInst.get(root).findPortInst("a"); drawArc(dotPi, inPi); } private void drawArc(PortInst p1, PortInst p2) { if (SLANTED_EDGES) { ArcInst aL = ArcInst.makeInstance(LINE_PROTO, p1, p2); aL.setFixedAngle(false); } else { LayoutLib.newArcInst(LINE_PROTO, DEF_SIZE, p1, p2); } } private void drawArcs(Node n, Map<Node, NodeInst> nodeToInst) { if (n.isLeaf()) return; PortInst cur = nodeToInst.get(n).findPortInst("y"); PortInst left = nodeToInst.get(n.getLeftChild()).findPortInst("a"); PortInst right = nodeToInst.get(n.getRightChild()).findPortInst("a"); drawArc(cur, left); drawArc(cur, right); drawArcs(n.getLeftChild(), nodeToInst); drawArcs(n.getRightChild(), nodeToInst); } private void setSlot(int slot, Node n) { slots.set(slot, n); n.setSlot(slot); } public BinaryTree(int height) { this.height = height; numSlots = (int) Math.pow(2, height)-1; slots = makeSlots(numSlots); int halfNbSlots = (numSlots+1)/2; Node.resetIds(); root = new Node(null, height, -1 + halfNbSlots, slots); } public int getHeight() {return height;} public Node getRoot() {return root;} public int getNumSlots() {return numSlots;} public void checkSlots() { Map<Node, Integer> nodeToNdx = new HashMap<Node, Integer>(); for (int i=0; i<slots.size(); i++) { Node n = slots.get(i); Job.error(n.getSlot()!=i, "wrong slot. actual="+i+" incorrect="+n.getSlot()); Integer index = nodeToNdx.get(n); Job.error(index!=null, "already at: "+index); nodeToNdx.put(n, i); } } private boolean isLocked(Node n, int movableHeight) { int h = n.getHeight(); return h>movableHeight; } /** move Node n to slot dst */ public void moveTo(Node n, int dst, int moveableHeight) { checkSlots(); int src = n.getSlot(); Job.error(isLocked(slots.get(dst), moveableHeight), "moveTo fails because destination is locked. \n"+ " src: "+slots.get(src).toString()+"\n"+ " dest: "+slots.get(dst).toString()); int incr = dst>=src ? 1 : -1; Node movee = slots.get(src); int wr = src; while (wr!=dst) { int rd = wr+incr; while (isLocked(slots.get(rd), moveableHeight)) rd+=incr; setSlot(wr, slots.get(rd)); wr = rd; } setSlot(dst, movee); checkSlots(); } /** Label each node with it's identifier */ public void addId(NodeInst ni, int id) { ni.setName(""+id); } /** Draw a schematic Cell for this tree */ public void draw(Cell c) { Map<Node, NodeInst> nodeToInst = new HashMap<Node, NodeInst>(); for (Node n : slots) { int h = n.getHeight(); int s = n.getSlot(); double x = s * SLOT_WID; double y = h * SLOT_HEI; NodeInst ni = LayoutLib.newNodeInst(SCH_ICON_PROTO, x, y, DEF_SIZE, DEF_SIZE, 270, c); addId(ni, n.getId()); Job.error(nodeToInst.containsKey(n), "duplicate entry"); nodeToInst.put(n, ni); } drawExternalArc(c, nodeToInst); drawArcs(root, nodeToInst); printStats(); } public int calcWireLength() { // there's an implicit edge to the root node int wireLen = getRoot().getSlot()+1; for (Node n : slots) wireLen += n.getChildWireLength(); return wireLen; } public int maxWireLength() { // there's an implicit edge to the root node int maxLen = getRoot().getSlot()+1; for (Node n : slots) maxLen = Math.max(maxLen, n.getChildWireLength()); return maxLen; } public int[] countTracks() { int[] counts = new int[numSlots]; for (Node n : slots) { if (n.isLeaf()) continue; int minSlot = n.getMinChildWireSlot(); int maxSlot = n.getMaxChildWireSlot(); for (int i=minSlot; i<=maxSlot; i++) counts[i]++; } // there's an implicit edge to the root node for (int i=0; i<=getRoot().getSlot(); i++) counts[i]++; return counts; } public List<Node> getNodesSortedByChildWireLength() { List<Node> sorted = new ArrayList<Node>(); sorted.addAll(slots); Collections.sort(sorted, new Comparator<Node> () { public int compare(Node n1, Node n2) { return n1.getChildWireLength() - n2.getChildWireLength(); } }); return sorted; } public Node getNodeWithLongestChildWire() { List<Node> sorted = getNodesSortedByChildWireLength(); return sorted.get(sorted.size()-1); } public int getLowBoundWireLen() { return (int) Math.ceil(((double)getNumSlots()) / height); } public void printStats() { pr("Track counts: "); int[] counts = countTracks(); int maxNbTracks = -1; for (int count : counts) { pr(count+" "); maxNbTracks = Math.max(maxNbTracks, count); } prln(""); prln("Max numb tracks: "+maxNbTracks); prln("Total wire length: "+calcWireLength()); prln("Maximum wire length: "+maxWireLength()); int lowBoundWireLen = getLowBoundWireLen(); prln("Lower bound on wire length: "+lowBoundWireLen); prln("Nodes with child wire length exceeding lower bound: "); for (Node n : getNodesSortedByChildWireLength()) { if (!n.isLeaf() && n.getChildWireLength()>lowBoundWireLen) prln(n.toString()); } } public List<Node> getNodesAtHeight(int h) { List<Node> nodes = new ArrayList<Node>(); for (Node n : slots) if (n.getHeight()==h) nodes.add(n); return nodes; } public Node getNodeInSlot(int i) {return slots.get(i);} }