/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: NodeInfo.java * Technology Editor, node information * Written by Steven M. Rubin, Sun Microsystems. * * Copyright (c) 2005 Sun Microsystems and Static Free Software * * 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.user.tecEdit; import com.sun.electric.database.geometry.Poly; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.database.hierarchy.Library; import com.sun.electric.database.prototype.PortCharacteristic; import com.sun.electric.database.topology.NodeInst; import com.sun.electric.database.variable.TextDescriptor; import com.sun.electric.database.variable.Variable; import com.sun.electric.technology.PrimitiveNode; import com.sun.electric.technology.PrimitivePort; import com.sun.electric.technology.SizeOffset; import com.sun.electric.technology.Technology; import com.sun.electric.technology.technologies.Artwork; import java.awt.geom.Dimension2D; import java.util.ArrayList; import java.util.BitSet; import java.util.Iterator; import java.util.List; /** * This class defines information about nodes in the Technology Editor. */ public class NodeInfo extends Info { static class PortDetails { String name; ArcInfo [] connections; int angle; int range; int netIndex; Technology.TechPoint[] values; PortCharacteristic characterisitic; boolean isolated; boolean negatable; } static class LayerDetails { LayerInfo layer; Poly.Type style; int representation; Technology.TechPoint[] values; Sample ns; int portIndex; boolean inLayers; boolean inElectricalLayers; boolean multiCut; /* true if a multi-cut layer */ double multiXS, multiYS; /* size of multicut */ double multiIndent, multiSep, multiSep2D; /* indent and separation of multicuts */ double lWidth, rWidth, extendT, extendB; /* serpentine transistor information */ String message; TextDescriptor descriptor; BitSet inNodes; public LayerDetails() { inLayers = true; inElectricalLayers = true; } public LayerDetails duplicate() { LayerDetails dup = new LayerDetails(); dup.layer = layer; dup.style = style; dup.representation = representation; dup.values = new Technology.TechPoint[values.length]; for(int i=0; i<values.length; i++) dup.values[i] = values[i]; dup.ns = ns; dup.portIndex = portIndex; dup.inLayers = inLayers; dup.inElectricalLayers = inElectricalLayers; dup.multiCut = multiCut; dup.multiXS = multiXS; dup.multiYS = multiYS; dup.multiIndent = multiIndent; dup.multiSep = multiSep; dup.multiSep2D = multiSep2D; dup.lWidth = lWidth; dup.rWidth = rWidth; dup.extendT = extendT; dup.extendB = extendB; dup.message = message; dup.descriptor = descriptor; return dup; } } String name; String abbrev; PrimitiveNode generated; PrimitiveNode.Function func; boolean serp; boolean arcsShrink; boolean square; boolean canBeZeroSize; boolean wipes; boolean lockable; boolean edgeSelect; boolean skipSizeInPalette; boolean notUsed; boolean lowVt; boolean highVt; boolean nativeBit; boolean od18; boolean od25; boolean od33; LayerDetails [] nodeLayers; PortDetails [] nodePortDetails; PrimitivePort[] primPorts; SizeOffset so; PrimitiveNode.NodeSizeRule nodeSizeRule; Dimension2D autoGrowth; int specialType; double [] specialValues; double xSize, ySize; String spiceTemplate; List<String> primitiveNodeGroupNames; static SpecialTextDescr [] nodeTextTable = { new SpecialTextDescr(0, 18, NODEFUNCTION), new SpecialTextDescr(0, 15, NODESERPENTINE), new SpecialTextDescr(0, 12, NODESQUARE), new SpecialTextDescr(0, 9, NODEWIPES), new SpecialTextDescr(0, 6, NODELOCKABLE), new SpecialTextDescr(0, 3, NODESPICETEMPLATE) }; NodeInfo() { func = PrimitiveNode.Function.UNKNOWN; } /** * Method to return an array of cells that comprise the nodes in a technology library. * @param lib the technology library. * @return an array of cells for each node (in the proper order). */ public static Cell [] getNodeCells(Library lib) { Library [] oneLib = new Library[1]; oneLib[0] = lib; return findCellSequence(oneLib, "node-", NODESEQUENCE_KEY); } /** * Method to build the appropriate descriptive information for a node into * cell "np". The function is in "func", the serpentine transistor factor * is in "serp", the node is square if "square" is true, the node * is invisible on 1 or 2 arcs if "wipes" is true, and the node is lockable * if "lockable" is true. */ void generate(Cell np) { // load up the structure with the current values loadTableEntry(nodeTextTable, NODEFUNCTION, func); loadTableEntry(nodeTextTable, NODESERPENTINE, Boolean.valueOf(serp)); loadTableEntry(nodeTextTable, NODESQUARE, Boolean.valueOf(square)); loadTableEntry(nodeTextTable, NODEWIPES, Boolean.valueOf(wipes)); loadTableEntry(nodeTextTable, NODELOCKABLE, Boolean.valueOf(lockable)); loadTableEntry(nodeTextTable, NODESPICETEMPLATE, spiceTemplate); // now create those text objects createSpecialText(np, nodeTextTable); } /** * Method to parse the node cell in "np" and return an NodeInfo object that describes it. */ static NodeInfo parseCell(Cell np) { NodeInfo nIn = new NodeInfo(); // look at all nodes in the arc description cell for(Iterator<NodeInst> it = np.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); Variable var = ni.getVar(OPTION_KEY); if (var == null) continue; switch (((Integer)var.getObject()).intValue()) { case NODEFUNCTION: nIn.func = PrimitiveNode.Function.findName(getValueOnNode(ni)); if (nIn.func == null) nIn.func = PrimitiveNode.Function.UNKNOWN; break; case NODESQUARE: nIn.square = getValueOnNode(ni).equalsIgnoreCase("yes"); break; case NODEWIPES: nIn.wipes = getValueOnNode(ni).equalsIgnoreCase("yes"); break; case NODELOCKABLE: nIn.lockable = getValueOnNode(ni).equalsIgnoreCase("yes"); break; case NODESERPENTINE: nIn.serp = getValueOnNode(ni).equalsIgnoreCase("yes"); break; case NODESPICETEMPLATE: nIn.spiceTemplate = getValueOnNode(ni); break; } } return nIn; } /** * Method to compact a Node technology-edit cell */ static void compactCell(Cell cell) { // move the examples TechConversionResult tcr = new TechConversionResult(); List<Example> neList = Example.getExamples(cell, true, tcr, null); if (tcr.failed()) tcr.showError(); if (neList == null || neList.size() == 0) return; Example firstEx = neList.get(0); int numExamples = neList.size(); Example smallest = firstEx; Example biggest = firstEx; for(Example ne : neList) { if (ne.hx-ne.lx > biggest.hx-biggest.lx || ne.hy-ne.ly > biggest.hx-biggest.ly) biggest = ne; } if (numExamples == 1) { moveExample(firstEx, -(firstEx.lx + firstEx.hx) / 2, -firstEx.hy); return; } if (numExamples != 4) return; Example stretchX = null; Example stretchY = null; for(Example ne : neList) { if (ne == biggest || ne == smallest) continue; if (stretchX == null) stretchX = ne; else if (stretchY == null) stretchY = ne; } if (stretchX.hx-stretchX.lx < stretchY.hx-stretchY.lx) { Example swap = stretchX; stretchX = stretchY; stretchY = swap; } double separation = Math.min(smallest.hx - smallest.lx, smallest.hy - smallest.ly); double totalWid = (stretchX.hx-stretchX.lx) + (smallest.hx-smallest.lx) + separation; double totalHei = (stretchY.hy-stretchY.ly) + (smallest.hy-smallest.ly) + separation; // center the smallest (main) example double cX = -totalWid / 2 - smallest.lx; double cY = -smallest.hy - 1; moveExample(smallest, cX, cY); // center the stretch-x (upper-right) example cX = totalWid/2 - stretchX.hx; cY = -stretchX.hy - 1; moveExample(stretchX, cX, cY); // center the stretch-y (lower-left) example cX = -totalWid/2 - stretchY.lx; cY = -totalHei - stretchY.ly - 1; moveExample(stretchY, cX, cY); // center the biggest (lower-right) example cX = totalWid/2 - biggest.hx; cY = -totalHei - biggest.ly - 1; moveExample(biggest, cX, cY); } private static void moveExample(Example ne, double dX, double dY) { for(Sample ns : ne.samples) { ns.node.move(dX, dY); } } }