/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: BookshelfNets.java * * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */ package com.sun.electric.tool.io.input.bookshelf; import com.sun.electric.database.geometry.EPoint; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.database.hierarchy.Export; import com.sun.electric.database.hierarchy.Library; import com.sun.electric.database.prototype.NodeProto; 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.database.variable.TextDescriptor; import com.sun.electric.database.variable.Variable; import com.sun.electric.database.variable.Variable.Key; import com.sun.electric.technology.ArcProto; import com.sun.electric.technology.Technology; import com.sun.electric.technology.technologies.Artwork; import com.sun.electric.technology.technologies.Generic; import com.sun.electric.tool.Job; import com.sun.electric.tool.io.input.bookshelf.BookshelfNodes.BookshelfNode; import com.sun.electric.tool.io.input.bookshelf.BookshelfNodes.BookshelfPin; import com.sun.electric.util.CollectionFactory; import com.sun.electric.util.TextUtils; import com.sun.electric.util.math.Orientation; import java.awt.geom.Point2D; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; /** * @author Felix Schmidt * */ public class BookshelfNets implements BookshelfInputParser<Void> { private String fileName; private Library lib; private Map<String, PortInst> netIndex = CollectionFactory.createHashMap(); public BookshelfNets(String fileName, Library lib) { this.fileName = fileName; this.lib = lib; } public Void parse() throws IOException { Job.getUserInterface().setProgressNote("Parse Net List File: Step 1/4"); netIndex.clear(); BufferedReader rin; try { File file = new File(fileName); FileReader freader = new FileReader(file); rin = new BufferedReader(freader); } catch (FileNotFoundException e) { System.out.println("ERROR: Cannot find Bookshelf Nets file: " + fileName); return null; } Map<String, List<BookshelfPin>> pins = CollectionFactory.createHashMap(); // make a map of ports on each node Map<BookshelfNode, Set<String>> nodePorts = new HashMap<BookshelfNode, Set<String>>(); Technology mocmos = Technology.getMocmosTechnology(); List<BookshelfNet> allNets = new ArrayList<BookshelfNet>(); String line; while ((line = rin.readLine()) != null) { if (line.startsWith("NetDegree")) { NetDesc desc = parseNetDesc(line); BookshelfNet net = new BookshelfNet(desc.netName); allNets.add(net); for (int i = 0; i < desc.elements; i++) { line = rin.readLine(); BookshelfPin pin = parsePin(line, net); if (!pins.containsKey(pin.getNodeName())) { pins.put(pin.getNodeName(), new ArrayList<BookshelfPin>()); } pins.get(pin.getNodeName()).add(pin); net.getPins().add(pin); // make a list of ports on each node BookshelfNode bn = BookshelfNode.findNode(pin.getNodeName()); if (bn != null) { Set<String> portsOnNode = nodePorts.get(bn); if (portsOnNode == null) nodePorts.put(bn, portsOnNode = new TreeSet<String>()); portsOnNode.add(pin.getLocation().getX() + "," + pin.getLocation().getY()); } } } } Job.getUserInterface().setProgressNote("Parse Net List File: Step 2/4"); // figure out what cell instances exist Map<String, List<BookshelfNode>> nodesBySize = new HashMap<String, List<BookshelfNode>>(); int allNodesNum = BookshelfNode.getAllNodes().size(); int counter = 0; for (BookshelfNode bn : BookshelfNode.getAllNodes()) { Job.getUserInterface().setProgressValue(counter * 100 / allNodesNum); String bnName = bn.getWidth() + "X" + bn.getHeight(); bnName += "Y" + Boolean.toString(bn.isTerminal()); Set<String> ports = nodePorts.get(bn); if (ports != null) { for (String portName : ports) bnName += "/" + portName; } List<BookshelfNode> nodes = nodesBySize.get(bnName); if (nodes == null) nodesBySize.put(bnName, nodes = new ArrayList<BookshelfNode>()); nodes.add(bn); counter++; } Job.getUserInterface().setProgressNote("Parse Net List File: Step 3/4"); // now create cells int cellNumber = 1; counter = 0; allNodesNum = nodesBySize.keySet().size(); for (String desc : nodesBySize.keySet()) { Job.getUserInterface().setProgressValue(counter * 100 / allNodesNum); List<BookshelfNode> nodes = nodesBySize.get(desc); String[] parts = desc.split("/"); String[] size = parts[0].split("Y")[0].split("X"); String terminal = parts[0].split("Y")[1]; double width = TextUtils.atof(size[0]); double height = TextUtils.atof(size[1]); Cell cell = Cell.makeInstance(lib, "Cell" + cellNumber + "{lay}"); cell.setTechnology(mocmos); for (BookshelfNode bn : nodes) bn.setPrototype(cell); cellNumber++; NodeProto np = Artwork.tech().boxNode; NodeInst nInst = NodeInst.makeInstance(np, new EPoint(0, 0), width, height, cell); if (terminal.equals(Boolean.toString(true))) { nInst.setLocked(); } int portNum = 1; for (int i = 1; i < parts.length; i++) { String[] xy = parts[i].split(","); double x = TextUtils.atof(xy[0]); double y = TextUtils.atof(xy[1]); NodeProto pin = mocmos.findNodeProto("Metal-1-Pin"); //Artwork.tech().pinNode; NodeInst ni = NodeInst.makeInstance(pin, new EPoint(x, y), 0, 0, cell); PortInst pi = ni.getOnlyPortInst(); Export.newInstance(cell, pi, "P" + portNum); portNum++; } counter++; } // now create all the nodes Cell mainCell = Cell.makeInstance(lib, lib.getName() + "{lay}"); mainCell.setTechnology(mocmos); Collection<BookshelfNode> allNodes = BookshelfNode.getAllNodes(); for (BookshelfNode bn : allNodes) { Cell np = bn.getPrototype(); NodeInst ni = NodeInst.newInstance(np, new Point2D.Double(bn.getX(), bn.getY()), bn.getWidth(), bn .getHeight(), mainCell, Orientation.IDENT, bn.getName()); Key key = Variable.newKey("weight"); Variable var = Variable.newInstance(key, new Integer(bn.getWeight()), TextDescriptor.getNodeTextDescriptor()); ni.addVar(var); bn.setInstance(ni); } Job.getUserInterface().setProgressNote("Parse Net List File: Step 4/4"); // now run the nets allNodesNum = allNets.size(); counter = 0; for (BookshelfNet bn : allNets) { Job.getUserInterface().setProgressValue(counter * 100 / allNodesNum); Job.getUserInterface().setProgressNote( "Parse Net List File: Step 4/4 (" + counter + "/" + allNodesNum + ")"); BookshelfPin lastPin = null; for (BookshelfPin bp : bn.getPins()) { if (lastPin != null) { // find the exports BookshelfNode bn1 = BookshelfNode.findNode(lastPin.getNodeName()); BookshelfNode bn2 = BookshelfNode.findNode(bp.getNodeName()); EPoint ep1 = new EPoint(lastPin.getLocation().getX(), lastPin.getLocation().getY()); EPoint ep2 = new EPoint(bp.getLocation().getX(), bp.getLocation().getY()); // find the proper pin PortInst pi1 = null; for (Iterator<Export> it = bn1.getPrototype().getExports(); it.hasNext();) { Export e = it.next(); NodeInst ni = e.getOriginalPort().getNodeInst(); if (ni.getAnchorCenterX() == ep1.getX() && ni.getAnchorCenterY() == ep1.getY()) { pi1 = bn1.getInstance().findPortInstFromProto(e); break; } } // find the proper pin PortInst pi2 = null; for (Iterator<Export> it = bn2.getPrototype().getExports(); it.hasNext();) { Export e = it.next(); NodeInst ni = e.getOriginalPort().getNodeInst(); if (ni.getAnchorCenterX() == ep2.getX() && ni.getAnchorCenterY() == ep2.getY()) { pi2 = bn2.getInstance().findPortInstFromProto(e); break; } } if (pi1 == null) { System.out.println("UNABLE TO FIND PORT AT (" + lastPin.getLocation().getX() + "," + lastPin.getLocation().getY() + ") ON INSTANCE " + bn1.getName() + " (CELL " + bn1.getPrototype().describe(false) + ")"); continue; } if (pi2 == null) { System.out.println("UNABLE TO FIND PORT AT (" + bp.getLocation().getX() + "," + bp.getLocation().getY() + ") ON INSTANCE " + bn2.getName() + " (CELL " + bn2.getPrototype().describe(false) + ")"); continue; } EPoint p1 = EPoint.fromLambda(bn1.getX() + ep1.getLambdaX(), bn1.getY() + ep1.getLambdaY()); EPoint p2 = EPoint.fromLambda(bn2.getX() + ep2.getLambdaX(), bn2.getY() + ep2.getLambdaY()); // if (!pi1.getCenter().equals(p1)) { // System.out.println("pi1=" + pi1.getCenter() + " p1=" + // p1); // } // if (!pi2.getCenter().equals(p2)) { // System.out.println("pi2=" + pi2.getCenter() + " p2=" + // p2); // } ArcProto ap = Generic.tech().unrouted_arc; newInstance(mainCell, ap, bn.name, pi1, pi2, p1, p2, 0, 0, 0); } lastPin = bp; counter++; } } return null; } public static void newInstance(Cell parent, ArcProto protoType, String name, PortInst headPort, PortInst tailPort, EPoint headPt, EPoint tailPt, long gridExtendOverMin, int angle, int flags) { if (true) { ArcInst.newInstanceNoCheck(parent, protoType, name, null, headPort, tailPort, headPt, tailPt, gridExtendOverMin, angle, flags); } //else { //ArcInst.makeInstance(protoType, headPort, tailPort); // // make sure the arc can connect to these ports // PortProto headProto = headPort.getPortProto(); // PortProto tailProto = tailPort.getPortProto(); // Name nameKey = Name.findName(name); // TextDescriptor nameDescriptor = // TextDescriptor.getArcTextDescriptor(); // // // search for spare arcId // CellId parentId = parent.getId(); // int arcId; // do { // arcId = parentId.newArcId(); // } while (parent.getArcById(arcId) != null); // ImmutableArcInst d = ImmutableArcInst.newInstance(arcId, // protoType.getId(), nameKey, nameDescriptor, // tailPort.getNodeInst().getD().nodeId, tailProto.getId(), tailPt, // headPort.getNodeInst().getD().nodeId, headProto.getId(), headPt, // gridExtendOverMin, angle, flags); // Topology topology = parent.getTopology(); // ArcInst ai = new ArcInst(topology, d, headPort, tailPort); // topology.addArc(ai); //} } private BookshelfPin parsePin(String line, BookshelfNet net) { String[] splited = line.trim().split(" "); double xPos = 0; double yPos = 0; if (splited.length == 6) { xPos = Double.parseDouble(splited[4]); yPos = Double.parseDouble(splited[5]); } Point2D location = new Point2D.Double(xPos, yPos); return new BookshelfPin(location, net, splited[0]); } private NetDesc parseNetDesc(String line) { NetDesc result = new NetDesc(); String[] splited = line.split(" "); result.elements = Integer.parseInt(splited[2]); result.netName = splited[splited.length - 1]; return result; } private class NetDesc { public String netName; public int elements; } public static class BookshelfNet { private List<BookshelfNode> nodes; private List<BookshelfPin> pins; private String name; public BookshelfNet(String name) { nodes = CollectionFactory.createArrayList(); pins = CollectionFactory.createArrayList(); this.name = name; } /** * @param nodes * the nodes to set */ public void setNodes(List<BookshelfNode> nodes) { this.nodes = nodes; } /** * @return the nodes */ public List<BookshelfNode> getNodes() { return nodes; } /** * @param pins * the pins to set */ public void setPins(List<BookshelfPin> pins) { this.pins = pins; } /** * @return the pins */ public List<BookshelfPin> getPins() { return pins; } } }