📄 layout.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: Layout.java * * Copyright (c) 2003 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.database.constraint;import com.sun.electric.database.CellBackup;import com.sun.electric.database.IdMapper;import com.sun.electric.database.ImmutableArcInst;import com.sun.electric.database.ImmutableCell;import com.sun.electric.database.ImmutableExport;import com.sun.electric.database.ImmutableLibrary;import com.sun.electric.database.ImmutableNodeInst;import com.sun.electric.database.Snapshot;import com.sun.electric.database.geometry.Poly;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.EDatabase;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.hierarchy.Library;import com.sun.electric.database.id.CellId;import com.sun.electric.database.prototype.PortProto;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.ElectricObject;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.Technology;import java.awt.geom.AffineTransform;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;/** * Class to implement the layout-constraint system. * Handles the fixed-angle and rigid constraints. * Also propagates these constraints up the hierarchy. */public class Layout extends Constraints{// private static final Layout layoutConstraint = new Layout(); static final boolean DEBUG = false; private static boolean doChangesQuietly; private static Snapshot oldSnapshot; private static long revisionDate; private static String userName; private static Set<Cell> goodSpacingDRCCells, goodAreaDRCCells; private static Variable goodSpacingDRCDate, goodSpacingDRCBit, goodAreaDRCDate; /** Shadow Cell info */ private static final ArrayList<LayoutCell> cellInfos = new ArrayList<LayoutCell>(); /** Map which contains temporary rigidity of ArcInsts. */ private static final HashMap<ArcInst,Boolean> tempRigid = new HashMap<ArcInst,Boolean>(); /** key of Variable for last valid DRC date on a Cell. Only spacing rules */ public static final Variable.Key DRC_LAST_GOOD_DATE_SPACING = Variable.newKey("DRC_last_good_drc_date"); /** key of Variable for last valid DRC bit on a Cell. Only spacing rules */ public static final Variable.Key DRC_LAST_GOOD_BIT_SPACING = Variable.newKey("DRC_last_good_drc_bit"); /** Default valud when no bit is found **/ public static final int DRC_LAST_GOOD_BIT_DEFAULT = -1; /** No need of bit for area since it is only 1 mode */ public static final Variable.Key DRC_LAST_GOOD_DATE_AREA = Variable.newKey("DRC_last_good_drc_area_date"); Layout() {}// /**// * Method to return the current constraint solver.// * @return the current constraint solver.// */// public static Layout getConstraint() { return layoutConstraint; } /** * Method to set the subsequent changes to be "quiet". * Quiet changes are not passed to constraint satisfaction, not recorded for Undo and are not broadcast. * This method is used to suppress endBatch. */ public static void changesQuiet(boolean quiet) { doChangesQuietly = true; } /** * Method to start a batch of changes. * @param initialSnapshot snapshot before job changes. */ @Override public void startBatch(Snapshot initialSnapshot) { // force every cell to remember its current bounds doChangesQuietly = false; oldSnapshot = initialSnapshot; tempRigid.clear(); goodSpacingDRCCells = null; goodAreaDRCCells = null; makeLayoutCells(); } /** * Method to do hierarchical update on any cells that changed */ @Override public void endBatch(String userName) { if (DEBUG) { System.out.println("Temporary rigid:"); for (Map.Entry<ArcInst,Boolean> e : tempRigid.entrySet()) { System.out.println("\t" + e.getKey() + " --> " + e.getValue()); } } Layout.userName = userName; revisionDate = System.currentTimeMillis(); if (goodSpacingDRCCells != null) { TextDescriptor td = TextDescriptor.getCellTextDescriptor().withDisplay(false); goodSpacingDRCDate = Variable.newInstance(DRC_LAST_GOOD_DATE_SPACING, new Long(revisionDate + 1), td); // If cell is changed during this 1 millisecond ??? } if (goodAreaDRCCells != null) { TextDescriptor td = TextDescriptor.getCellTextDescriptor().withDisplay(false); goodAreaDRCDate = Variable.newInstance(DRC_LAST_GOOD_DATE_AREA, new Long(revisionDate + 1), td); // If cell is changed during this 1 millisecond ??? } if (!doChangesQuietly) { // Propagate changes and mark changed cells. for(Iterator<Library> it = Library.getLibraries(); it.hasNext(); ) { Library lib = it.next(); for(Iterator<Cell> cIt = lib.getCells(); cIt.hasNext(); ) { Cell cell = cIt.next(); assert cell.isLinked(); LayoutCell cellInfo = getCellInfo(cell); cellInfo.compute(); } } } cellInfos.clear(); tempRigid.clear(); // Set revision dates to modified Cells, update DRC date, update bounds for(Iterator<Library> it = Library.getLibraries(); it.hasNext(); ) { Library lib = it.next(); for(Iterator<Cell> cIt = lib.getCells(); cIt.hasNext(); ) { Cell cell = cIt.next(); cell.lowLevelMadeRevision(revisionDate, userName, oldSnapshot.getCellRevision(cell.getId())); if (goodSpacingDRCCells != null && goodSpacingDRCCells.contains(cell)) { cell.addVar(goodSpacingDRCDate); cell.addVar(goodSpacingDRCBit); } if (goodAreaDRCCells != null && goodAreaDRCCells.contains(cell)) { cell.addVar(goodAreaDRCDate); } } } EDatabase.serverDatabase().backup(); goodSpacingDRCCells = null; goodAreaDRCCells = null; oldSnapshot = null; } /** * Method to handle a change to a NodeInst. * @param ni the NodeInst that was changed. * @param oD the old contents of the NodeInst. */ @Override public void modifyNodeInst(NodeInst ni, ImmutableNodeInst oD) { if (doChangesQuietly) return; getCellInfo(ni.getParent()).modifyNodeInst(ni, oD); } /** * Method to handle a change to an ArcInst. * @param ai the ArcInst that changed. * @param oD the old contents of the ArcInst. */ @Override public void modifyArcInst(ArcInst ai, ImmutableArcInst oD) { if (doChangesQuietly) return; getCellInfo(ai.getParent()).modifyArcInst(ai, oD); } /** * Method to handle a change to an Export. * @param pp the Export that moved. * @param oldD the old contents of the Export. */ @Override public void modifyExport(Export pp, ImmutableExport oldD) { if (doChangesQuietly) return; PortInst oldPi = pp.getParent().getPortInst(oldD.originalNodeId, oldD.originalPortId); if (oldPi == pp.getOriginalPort()) return; getCellInfo(pp.getParent()).modifyExport(pp, oldPi); } /** * Method to handle a change to a Cell. * @param cell the Cell that was changed. * @param oD the old contents of the Cell. */ @Override public void modifyCell(Cell cell, ImmutableCell oD) {} /** * Method to handle a change to a Library. * @param lib the Library that was changed. * @param oldD the old contents of the Library. */ @Override public void modifyLibrary(Library lib, ImmutableLibrary oldD) {} /** * Method to handle the creation of a new ElectricObject. * @param obj the ElectricObject that was just created. */ @Override public void newObject(ElectricObject obj) { if (doChangesQuietly) return; Cell cell = obj.whichCell(); if (obj == cell) newCellInfo(cell, null); else if (cell != null) getCellInfo(cell).newObject(obj); } /** * Method to announce than Ids were renamed. * @param idMapper mapper from old Ids to new Ids. */ @Override public void renameIds(IdMapper idMapper) { EDatabase database = EDatabase.serverDatabase(); for (CellId cellId: idMapper.getNewCellIds()) newObject(cellId.inDatabase(database));// for (ExportId exportId: idMapper.getNewExportIds())// newObject(exportId.inDatabase(database)); } /** * Method to set temporary rigidity on an ArcInst. * @param ai the ArcInst to make temporarily rigid/not-rigid. * @param tempRigid true to make the ArcInst temporarily rigid; * false to make it temporarily not-rigid. */ public static void setTempRigid(ArcInst ai, boolean tempRigid) { if (DEBUG) System.out.println("setTempRigid " + ai + " " + tempRigid); ai.checkChanging(); Layout.tempRigid.put(ai, Boolean.valueOf(tempRigid));// if (tempRigid)// {// if (ai.getChangeClock() == changeClock + 2) return;// ai.setChangeClock(changeClock + 2);// } else// {// if (ai.getChangeClock() == changeClock + 3) return;// ai.setChangeClock(changeClock + 3);// } } /** * Method to remove temporary rigidity on an ArcInst. * @param ai the ArcInst to remove temporarily rigidity. */ public static void removeTempRigid(ArcInst ai) { ai.checkChanging(); tempRigid.remove(ai);// if (ai.getChangeClock() != changeClock + 3 && ai.getChangeClock() != changeClock + 2) return;// ai.setChangeClock(changeClock - 3); } /* * Method to request to set */ public static void setGoodDRCCells(Set<Cell> goodDRCCells, Variable.Key key, int activeBits, boolean inMemory) { assert(!inMemory); // call only if you are storing in disk if (key == DRC_LAST_GOOD_DATE_SPACING) { Layout.goodSpacingDRCCells = goodDRCCells; TextDescriptor td = TextDescriptor.getCellTextDescriptor().withDisplay(false); goodSpacingDRCBit = Variable.newInstance(DRC_LAST_GOOD_BIT_SPACING, new Integer(activeBits), td); } else // min area { Layout.goodAreaDRCCells = goodDRCCells; } } /** ** Returns rigidity of an ArcInst considering temporary rigidity. * @param ai ArcInst to test rigidity. * @return true if the ArcInst is considered rigid in this batch. */ static boolean isRigid(ArcInst ai) { Boolean override = tempRigid.get(ai); return override != null ? override.booleanValue() : ai.isRigid(); } private static void makeLayoutCells() { cellInfos.clear(); for(Iterator<Library> it = Library.getLibraries(); it.hasNext(); ) { Library lib = it.next(); for(Iterator<Cell> cIt = lib.getCells(); cIt.hasNext(); ) { Cell cell = cIt.next(); newCellInfo(cell, oldSnapshot.getCell(cell.getId())); } } } /******************** NODE MODIFICATION CODE *************************/ /** * Method to compute the position of portinst "pi" and * place the center of the area in the parameters "x" and "y". The position * is the "old" position, as determined by any changes that may have occured * to the nodeinst (and any sub-nodes). */ static Poly oldPortPosition(PortInst pi) { NodeInst ni = pi.getNodeInst(); PortProto pp = pi.getPortProto(); // descend to the primitive node AffineTransform subrot = makeOldRot(ni); if (subrot == null) return null; NodeInst bottomNi = ni; PortProto bottomPP = pp; while (bottomNi.isCellInstance()) { AffineTransform localtran = makeOldTrans(bottomNi); subrot.concatenate(localtran); PortInst bottomPi = getOldOriginalPort((Export)bottomPP); bottomNi = bottomPi.getNodeInst(); bottomPP = bottomPi.getPortProto(); localtran = makeOldRot(bottomNi); subrot.concatenate(localtran); } // if the node hasn't changed, use its current values ImmutableNodeInst d = Layout.getOldD(bottomNi); assert d != null; if (d != bottomNi.getD()) { // create a fake node with these values bottomNi = NodeInst.makeDummyInstance(bottomNi.getProto()); bottomNi.lowLevelModify(d); } PrimitiveNode np = (PrimitiveNode)bottomNi.getProto(); Technology tech = np.getTechnology(); Poly poly = tech.getShapeOfPort(bottomNi, (PrimitivePort)bottomPP); poly.transform(subrot); return (poly); } private static AffineTransform makeOldRot(NodeInst ni) { // if the node has not been modified, just use the current transformation ImmutableNodeInst d = getOldD(ni); if (d == null) return null; // get the old values double cX = d.anchor.getX(); double cY = d.anchor.getY(); return d.orient.rotateAbout(cX, cY); } private static AffineTransform makeOldTrans(NodeInst ni) { ImmutableNodeInst d = getOldD(ni); if (d == null) return null; // create the former translation matrix AffineTransform transform = new AffineTransform(); double cX = d.anchor.getX(); double cY = d.anchor.getY(); transform.translate(cX, cY); return transform; } static PortInst getOldOriginalPort(Export e) { return getCellInfo(e.getParent()).getOldOriginalPort(e); } static ImmutableNodeInst getOldD(NodeInst ni) { return getCellInfo(ni.getParent()).getOldD(ni); } private static void newCellInfo(Cell cell, CellBackup oldBackup) { int cellIndex = cell.getCellIndex(); while (cellInfos.size() <= cellIndex) cellInfos.add(null);// assert cellInfos.get(cellIndex) == null; cellInfos.set(cellIndex, new LayoutCell(cell, oldBackup)); } static LayoutCell getCellInfo(Cell cell) { return cellInfos.get(cell.getCellIndex()); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -