📄 library.java
字号:
// startLib references refLib. Find out why boolean found = false; // find a cell instance that creates dependency for (Iterator<Cell> itCell = startLib.getCells(); itCell.hasNext(); ) { Cell c = itCell.next(); for (Iterator<NodeInst> it = c.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); if (ni.isCellInstance()) { Cell cc = (Cell)ni.getProto(); if (cc.getLibrary() == refLib) { d.dependencies.add(c); d.dependencies.add(cc); found = true; break; } } } if (found) break; } if (!found) System.out.println("ERROR: Library.addReferencedLib dependency trace failed inexplicably"); startLib = refLib; } return d; } // would not create circular dependency, add and return synchronized(referencedLibs) { referencedLibs.add(lib); updateBackup(d, backup.modified, backupReferencedLibs(backup.referencedLibs)); } return null; } /** * Try to remove lib as a referenced library. If it is no longer referenced, * it is removed as a reference library. * @param lib the reference library that may no longer be referenced */ void removeReferencedLib(Library lib) { if (lib == this) return; // we don't store references to self synchronized(referencedLibs) { if (!referencedLibs.contains(lib)) return;// assert(referencedLibs.contains(lib)); } boolean refFound = false; for (Iterator<Cell> itCell = getCells(); itCell.hasNext(); ) { Cell c = itCell.next(); for (Iterator<NodeInst> it = c.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); if (ni.isCellInstance()) { Cell cc = (Cell)ni.getProto(); if (cc.getLibrary() == lib) { refFound = true; break; } } } if (refFound) break; } if (!refFound) { // no instance that would create reference found, ok to remove reference synchronized(referencedLibs) { referencedLibs.remove(lib); updateBackup(d, backup.modified, backupReferencedLibs(backup.referencedLibs)); } } } /** * Returns true if this Library directly references the specified Library 'lib'. * It does not return true if the library is referenced through another library. * @param lib the possible referenced library * @return true if the library is directly referenced by this library, false otherwise */ public boolean referencesLib(Library lib) { synchronized(referencedLibs) { if (referencedLibs.contains(lib)) return true; } return false; } /** * Checks to see if lib is referenced by this library, or by * any libraries this library references, recursively. * @param lib the lib to check if it is a referenced lib * @return true if it is through any number of references, false otherwise */ private boolean isReferencedLib(Library lib, List<Library> libDepedencies) { List<Library> reflibsCopy = new ArrayList<Library>(); synchronized(referencedLibs) { if (referencedLibs.contains(lib)) { libDepedencies.add(lib); return true; } reflibsCopy.addAll(referencedLibs); } for (Library reflib : reflibsCopy) { // if reflib already in dependency list, ignore if (libDepedencies.contains(reflib)) continue; // check recursively libDepedencies.add(reflib); if (reflib.isReferencedLib(lib, libDepedencies)) return true; // remove reflib in accumulated list, try again libDepedencies.remove(reflib); } return false; } static class LibraryDependency { private List<Cell> dependencies; private Library startLib; private Library finalRefLib; private LibraryDependency() { dependencies = new ArrayList<Cell>(); } public String toString() { StringBuffer buf = new StringBuffer(); buf.append(startLib + " depends on " + finalRefLib + " through the following references:\n"); for (Iterator<Cell> it = dependencies.iterator(); it.hasNext(); ) { Cell libCell = it.next(); Cell instance = it.next(); buf.append(" " + libCell.libDescribe() + " instantiates " + instance.libDescribe() + "\n"); } return buf.toString(); } } // ----------------- public interface -------------------- /** * Returns persistent data of this Library. * @return persistent data of this Library. */ @Override public ImmutableLibrary getD() { return d; } /** * Modifies persistend data of this Library. * @param newD new persistent data. * @return true if persistent data was modified. */ private boolean setD(ImmutableLibrary newD) { checkChanging(); ImmutableLibrary oldD = d; if (newD == oldD) return false; d = newD;// setChanged(); assert isLinked(); updateBackup(d, true, backup.referencedLibs); Constraints.getCurrent().modifyLibrary(this, oldD); return true; } /** * Method to add a Variable on this Library. * It may add repaired copy of this Variable in some cases. * @param var Variable to add. */ public void addVar(Variable var) { setD(getD().withVariable(var)); } /** * Method to delete a Variable from this Library. * @param key the key of the Variable to delete. */ public void delVar(Variable.Key key) { setD(getD().withoutVariable(key)); } /** * Method to return LibId of this Library. * LibId identifies Library independently of threads. * @return LibId of this Library. */ public LibId getId() { return d.libId; } /** * Returns a Library by LibId. * Returns null if the Library is not linked to the database. * @param libId LibId to find. * @return Library or null. */ public static Library inCurrentThread(LibId libId) { return EDatabase.theDatabase.getLib(libId); } /** * Returns true if this Library is linked into database. * @return true if this Library is linked into database. */ public boolean isLinked() { return inCurrentThread(getId()) == this; } /** * Returns database to which this Library belongs. * @return database to which this Library belongs. */ public EDatabase getDatabase() { return database; } /* * Low-level method to backup this Library to LibraryBackup. * @return LibraryBackup which is the backup of this Library. */ public LibraryBackup backup() { return backup; } void recover(LibraryBackup recoverBackup) { checkUndoing(); backup = recoverBackup; this.d = recoverBackup.d; referencedLibs.clear(); for (LibId libId: recoverBackup.referencedLibs) referencedLibs.add(database.getLib(libId)); } void checkFresh(LibraryBackup libBackup) { assert d == libBackup.d; assert backup == libBackup; assert libBackup.referencedLibs.length == referencedLibs.size(); for (int i = 0; i < libBackup.referencedLibs.length; i++) assert libBackup.referencedLibs[i] == referencedLibs.get(i).getId(); } private LibId[] backupReferencedLibs(LibId[] oldReferencedLibs) { int numRefs = Math.min(oldReferencedLibs.length, referencedLibs.size()); int matchedRefs = 0; while (matchedRefs < numRefs && oldReferencedLibs[matchedRefs] == referencedLibs.get(matchedRefs).getId()) matchedRefs++; if (matchedRefs == oldReferencedLibs.length && matchedRefs == referencedLibs.size()) return oldReferencedLibs; LibId[] newRefs = new LibId[referencedLibs.size()]; System.arraycopy(oldReferencedLibs, 0, newRefs, 0, matchedRefs); for (int i = matchedRefs; i < referencedLibs.size(); i++) newRefs[i] = referencedLibs.get(i).getId(); return newRefs; } public static void repairAllLibraries() { ErrorLogger errorLogger = ErrorLogger.newInstance("Repair Libraries"); for (Iterator<Library> it = Library.getLibraries(); it.hasNext(); ) { Library l = it.next(); l.checkAndRepair(true, errorLogger); } System.out.println("Repair Libraries: " + errorLogger.getNumErrors() + " errors, " + errorLogger.getNumWarnings() + " warnings"); } /** * Method to check and repair data structure errors in this Library. */ public int checkAndRepair(boolean repair, ErrorLogger errorLogger) { int errorCount = 0; boolean verbose = !isHidden(); if (verbose) { System.out.print("Checking " + this); if (repair) System.out.print(" for repair"); } for(Iterator<Cell> it = getCells(); it.hasNext(); ) { Cell cell = it.next(); errorCount += cell.checkAndRepair(repair, errorLogger); } if (errorCount != 0) { if (repair) { if (verbose) System.out.println("... library repaired");// setChanged(); } else { if (verbose) System.out.println("... library has to be repaired"); } } else { if (verbose) System.out.println("... library checked"); } return errorCount; } /** * Method to check invariants in this Library. * @exception AssertionError if invariants are not valid */ protected void check() { assert getD() == backup.d; assert backup.referencedLibs.length == referencedLibs.size(); super.check(); String libName = d.libId.libName; assert libName != null; assert libName.length() > 0; assert libName.indexOf(' ') == -1 && libName.indexOf(':') == -1 : libName; for (int i = 0; i < referencedLibs.size(); i++) { Library rLib = referencedLibs.get(i); assert rLib.isLinked() && rLib.database == database; assert backup.referencedLibs[i] == referencedLibs.get(i).getId(); } HashSet<Cell.CellGroup> cellGroups = new HashSet<Cell.CellGroup>(); String protoName = null; Cell.CellGroup cellGroup = null; Cell newestVersion = null; for(Map.Entry<CellName,Cell> e : cells.entrySet()) { CellName cn = e.getKey(); Cell cell = e.getValue(); assert cell.isLinked() && cell.getDatabase() == database; assert cell.getCellName() == cn; assert cell.getLibrary() == this; if (protoName == null || !cell.getName().equals(protoName)) { protoName = cell.getName(); cellGroup = cell.getCellGroup(); assert cellGroup != null : cell; cellGroups.add(cellGroup); newestVersion = cell; } if (cell.getView() != newestVersion.getView()) newestVersion = cell; assert cell.getCellGroup() == cellGroup : cell; assert cell.newestVersion == newestVersion; } for (Iterator<Cell.CellGroup> it = cellGroups.iterator(); it.hasNext(); ) { cellGroup = it.next(); cellGroup.check(); } } private void setFlag(int mask, boolean value) { setD(d.withFlags(value ? d.flags | mask : d.flags & ~mask)); } private boolean isFlag(int mask) { return (d.flags & mask) != 0; } /** * Method to indicate that this Library has changed. */ public void setChanged() { checkChanging(); if (!isChanged()) updateBackup(d, true, backup.referencedLibs); } /** * Method to indicate that this Library has not changed. */ public void clearChanged() { checkChanging(); for (Cell cell: cells.values()) cell.clearModified(); if (isChanged()) updateBackup(d, false, backup.referencedLibs); } private void updateBackup(ImmutableLibrary d, boolean modified, LibId[] referencedLibs) { backup = new LibraryBackup(d, modified, referencedLibs); database.unfreshSnapshot(); } /** * Method to return true if this Library has changed. * @return true if this Library has changed. */ public boolean isChanged() { return backup.modified; } /** * Method to indicate that this Library came from disk. * Libraries that come from disk are saved without a file-selection dialog. */ public void setFromDisk() { setFlag(READFROMDISK, true); } /** * Method to indicate that this Library did not come from disk. * Libraries that come from disk are saved without a file-selection dialog. */ public void clearFromDisk() { setFlag(READFROMDISK, false); } /** * Method to return true if this Library came from disk. * Libraries that come from disk are saved without a file-selection dialog. * @return true if this Library came from disk. */ public boolean isFromDisk() { return isFlag(READFROMDISK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -