📄 library.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: Library.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.hierarchy;import com.sun.electric.database.EObjectInputStream;import com.sun.electric.database.EObjectOutputStream;import com.sun.electric.database.IdMapper;import com.sun.electric.database.ImmutableLibrary;import com.sun.electric.database.LibraryBackup;import com.sun.electric.database.Snapshot;import com.sun.electric.database.constraint.Constraints;import com.sun.electric.database.id.LibId;import com.sun.electric.database.text.CellName;import com.sun.electric.database.text.Pref;import com.sun.electric.database.text.TextUtils;import com.sun.electric.database.text.Version;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.variable.ElectricObject;import com.sun.electric.database.variable.Variable;import com.sun.electric.tool.Job;import com.sun.electric.tool.user.ErrorLogger;import java.io.IOException;import java.io.InvalidObjectException;import java.io.NotSerializableException;import java.net.URL;import java.util.ArrayList;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import java.util.TreeMap;import java.util.prefs.BackingStoreException;import java.util.prefs.Preferences;/** * A Library represents a collection of Cells. * To find of a Library, you use Electric.getLibrary(String name). * Use Electric.newLibrary(String name) to create a new library, or * Electric.getCurrent() to get the current Library. * <p> * Once you have a Library, you can create a new Cell in it, find an existing * Cell, get an Enumeration of all Cells, or find the Cell that the user * is currently editing. */public class Library extends ElectricObject implements Comparable<Library>{ /** key of Variable holding font associations. */ public static final Variable.Key FONT_ASSOCIATIONS = Variable.newKey("LIB_font_associations"); // ------------------------ private data ------------------------------// /** library has changed significantly */ private static final int LIBCHANGEDMAJOR = 01;// /** set to see library in explorer */ private static final int OPENINEXPLORER = 02; /** set if library came from disk */ private static final int READFROMDISK = 04;// /** internal units in library (see INTERNALUNITS) */ private static final int LIBUNITS = 070;// /** right shift for LIBUNITS */ private static final int LIBUNITSSH = 3;// /** library has changed insignificantly */ private static final int LIBCHANGEDMINOR = 0100; /** library is "hidden" (clipboard library) */ public static final int HIDDENLIBRARY = 0200;// /** library is unwanted (used during input) */ private static final int UNWANTEDLIB = 0400; /** Database to which this Library belongs. */ private final EDatabase database; /** persistent data of this Library. */ private ImmutableLibrary d; /** list of referenced libs */ private final List<Library> referencedLibs = new ArrayList<Library>(); /** Last backup of this Library */ LibraryBackup backup; /** list of Cells in this library */ final TreeMap<CellName,Cell> cells = new TreeMap<CellName,Cell>(); /** Preference for cell currently being edited */ private Pref curCellPref; /** preferences for this library */ final Preferences prefs; /** preferences group for this library */ private final Pref.Group prefsGroup; /** DELIB cell files. */ private HashSet<String> delibCellFiles = new HashSet<String>(); /** preferences for all libraries */ private static Preferences allPrefs = null; /** the current library in Electric */ private static Library curLib = null; // ----------------- private and protected methods -------------------- /** * The constructor is never called. Use the factor method "newInstance" instead. */ Library(EDatabase database, ImmutableLibrary d) { if (database == null) throw new NullPointerException(); this.database = database; this.d = d; backup = new LibraryBackup(d, true, LibId.NULL_ARRAY); if (allPrefs == null) allPrefs = Preferences.userNodeForPackage(getClass()); prefs = allPrefs.node(getName()); prefs.put("LIB", getName()); prefsGroup = new Pref.Group(prefs); } /** * This method is a factory to create new libraries. * A Library has both a name and a file. * @param libName the name of the library (for example, "gates"). * Library names must be unique, and they must not contain spaces or colons. * @param libFile the URL to the disk file (for example "/home/strubin/gates.elib"). * If the Library is being created, the libFile can be null. * If the Library file is given and it points to an existing file, then the I/O system * can be told to read that file and populate the Library. * @return the Library object. */ public static Library newInstance(String libName, URL libFile) { // make sure the name is legal String legalName = LibId.legalLibraryName(libName); if (legalName == null) return null; if (legalName != libName) System.out.println("Warning: library '" + libName + "' renamed to '" + legalName + "'"); // see if the library name already exists Library existingLibrary = Library.findLibrary(legalName); if (existingLibrary != null) { System.out.println("Error: library '" + legalName + "' already exists"); return existingLibrary; } // create the library EDatabase database = EDatabase.serverDatabase(); return newInstance(database, database.getIdManager().newLibId(legalName), libFile); } /** * This method is a factory to create new libraries. * A Library has both a name and a file. * @param libId ID of new Library. * @param libFile the URL to the disk file (for example "/home/strubin/gates.elib"). * If the Library is being created, the libFile can be null. * If the Library file is given and it points to an existing file, then the I/O system * can be told to read that file and populate the Library. * @return the Library object. * @throws NullPointerException if libId or legalName is null. */ private static Library newInstance(EDatabase edb, LibId libId, URL libFile) { // create the library ImmutableLibrary d = ImmutableLibrary.newInstance(libId, libFile, null); Library lib = new Library(edb, d); // add the library to the global list edb.addLib(lib); // always broadcast library changes// Undo.setNextChangeQuiet(false); edb.unfreshSnapshot(); Constraints.getCurrent().newObject(lib); return lib; } /** * Method for serialization. */ private Object writeReplace() { return new LibraryKey(this); } private static class LibraryKey extends EObjectInputStream.Key<Library> { public LibraryKey() {} private LibraryKey(Library lib) { super(lib); } @Override public void writeExternal(EObjectOutputStream out, Library lib) throws IOException { if (lib.getDatabase() != out.getDatabase() || !lib.isLinked()) throw new NotSerializableException(lib + " not linked"); out.writeObject(lib.getId()); } @Override public Library readExternal(EObjectInputStream in) throws IOException, ClassNotFoundException { LibId libId = (LibId)in.readObject(); Library lib = libId.inDatabase(in.getDatabase()); if (lib == null) throw new InvalidObjectException(libId + " not linked"); return lib; } } /** * Method to delete this Library. * @param reason the reason for deleting this library (replacement or deletion). * @return true if the library was deleted. * Returns false on error. */ public boolean kill(String reason) { if (!isLinked()) { System.out.println("Library already killed"); return false; } // cannot delete the current library Library newCurLib = null; if (curLib == this) curLib = null;// {// // find another library// for (Library lib : database.libraries.values())// {// if (lib == curLib) continue;// if (lib.isHidden()) continue;// newCurLib = lib;// break;// }// if (newCurLib == null)// {// System.out.println("Cannot delete the last library");// Job.getUserInterface().showInformationMessage("Cannot delete the last "+toString(),// "Close library");// return false;// }// } // make sure it is in the list of libraries if (database.libraries.get(getName()) != this) { System.out.println("Cannot delete library " + this); Job.getUserInterface().showErrorMessage("Cannot delete "+toString(), "Close library"); return false; } // make sure none of these cells are referenced by other libraries boolean referenced = false; for (Library lib : database.libraries.values()) { if (lib == this) continue; for(Iterator<Cell> cIt = lib.getCells(); cIt.hasNext(); ) { Cell cell = cIt.next(); for(Iterator<NodeInst> nIt = cell.getNodes(); nIt.hasNext(); ) { NodeInst ni = nIt.next(); if (ni.isCellInstance()) { Cell subCell = (Cell)ni.getProto(); if (subCell.getLibrary() == this) { Job.getUserInterface().showErrorMessage("Library close failed. Cannot " + reason + " " + toString() + " because one of its cells (" + subCell.noLibDescribe() + ") is being used (by " + cell.libDescribe() + ")", "Close library"); referenced = true; break; } } } if (referenced) break; } if (referenced) break; } if (referenced) return false; // remove all cells in the library erase(); for (Library lib: database.libraries.values()) { if (lib == this) continue; lib.removeReferencedLib(this); } // remove it from the list of libraries database.removeLib(getId()); // set the new current library if appropriate if (newCurLib != null) newCurLib.setCurrent(); // always broadcast library changes// Undo.setNextChangeQuiet(false); database.unfreshSnapshot(); Constraints.getCurrent().killObject(this); return true; } /** * Method to remove all contents from this Library. */ public void erase() { // remove all cells in the library for (Iterator<Cell> it = getCells(); it.hasNext(); ) { Cell c = it.next(); c.kill(); } cells.clear(); } /** * Method to add a Cell to this Library. * @param c the Cell to add. */ void addCell(Cell c) { CellName cn = c.getCellName(); // sanity check: make sure Cell isn't already in the list synchronized (cells) { if (cells.containsKey(cn)) { System.out.println("Tried to re-add a cell to a library: " + c); return; } cells.put(cn, c); updateNewestVersions(); } setChanged(); } /** * Method to remove a Cell from this Library. * @param c the Cell to remove. */ void removeCell(Cell c) { CellName cn = c.getCellName(); // sanity check: make sure Cell is in the list synchronized (cells) { if (cells.get(cn) != c) { System.out.println("Tried to remove a non-existant Cell from a library: " + c); return; } cells.remove(cn); c.newestVersion = null; updateNewestVersions(); } setChanged(); } /** * Collect cells from database snapshot into cells list of this Library. */ void collectCells() { synchronized(cells) { cells.clear(); for (int cellIndex = 0; cellIndex < database.linkedCells.size(); cellIndex++) { Cell cell = database.getCell(cellIndex); if (cell == null || cell.getLibrary() != this) continue; cells.put(cell.getCellName(), cell); } updateNewestVersions(); } } /** * Update newestVersion fields of cells in this Library. */ private void updateNewestVersions() { Cell newestVersion = null; for (Cell cell: cells.values()) { if (newestVersion == null || !newestVersion.getName().equals(cell.getName()) || newestVersion.getView() != cell.getView()) newestVersion = cell; cell.newestVersion = newestVersion; } } /** * Adds lib as a referenced library. This also checks the dependency * would create a circular dependency, in which case the reference is * not logged, and the method returns a LibraryDependency object. * If everything is ok, the method returns null. * @param lib the library to be added as a referenced lib * @return null if ok, a LibraryDependency object if this would create circular dependency */ LibraryDependency addReferencedLib(Library lib) { synchronized(referencedLibs) { if (referencedLibs.contains(lib)) return null; // already a referenced lib, is ok } // check recursively if there is a circular dependency List<Library> libDependencies = new ArrayList<Library>(); if (lib.isReferencedLib(this, libDependencies)) { // there is a dependency // trace the dependency (this is an expensive operation) LibraryDependency d = new LibraryDependency(); d.startLib = lib; d.finalRefLib = this; Library startLib = lib; for (Library refLib : libDependencies) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -