📄 cell.java
字号:
/****************************** LOW-LEVEL IMPLEMENTATION ******************************/ private static CellName makeUnique(Library lib, CellName cellName) { // ensure unique cell name String protoName = cellName.getName(); View view = cellName.getView(); int version = cellName.getVersion(); int greatestVersion = 0; boolean conflict = version <= 0; for (Iterator<Cell> it = lib.getCells(); it.hasNext(); ) { Cell c = it.next(); if (c.getName().equals(protoName) && c.getView() == view)// if (c.getName().equalsIgnoreCase(protoName) && c.getView() == view) { if (c.getVersion() == version) conflict = true; if (c.getVersion() > greatestVersion) greatestVersion = c.getVersion(); } } if (conflict) { if (version > 0) System.out.println("Already have cell " + cellName + " with version " + version + ", generating a new version"); int newVersion = greatestVersion + 1; cellName = CellName.newName(protoName, view, newVersion); } return cellName; } /** * Low-level method to get the user bits. * The "user bits" are a collection of flags that are more sensibly accessed * through special methods. * This general access to the bits is required because the ELIB * file format stores it as a full integer. * This should not normally be called by any other part of the system. * @return the "user bits". */ public int lowLevelGetUserbits() { return getD().flags; } /** * Low-level method to set the user bits. * The "user bits" are a collection of flags that are more sensibly accessed * through special methods. * This general access to the bits is required because the ELIB * file format stores it as a full integer. * This should not normally be called by any other part of the system. * @param userBits the new "user bits". */ public void lowLevelSetUserbits(int userBits) { setD(getD().withFlags(userBits)); } /* * Low-level method to backup this Cell to CellBackup. * @return CellBackup which is the backup of this Cell. * @throws IllegalStateException if recalculation of Snapshot is requred in thread which is not enabled to do it. */ public CellBackup backup() { if (cellBackupFresh) return backup; if (!database.canComputeBounds()) throw new IllegalStateException(); return doBackup(); } /* * Low-level method to backup this Cell to CellBackup. * If there is no fresh backup for this database and thread is not enabled to calculate snspshot, returns the latest backup. * @return CellBackup which is the backup of this Cell. * @throws IllegalStateException if recalculation of Snapshot is requred in thread which is not enabled to do it. */ public CellBackup backupUnsafe() { if (cellBackupFresh || !database.canComputeBounds()) return backup; return doBackup(); } /** * Returns data for size computation (connectivity etc). * @return data for size computation. */ public CellBackup.Memoization getMemoization() { return backupUnsafe().getMemoization(); } /** * Returns data for arc shrinkage computation. * @return data for arc shrinkage computation. */ public AbstractShapeBuilder.Shrinkage getShrinkage() { return backupUnsafe().getShrinkage(); } public Topology getTopology() { return topology; } private CellBackup doBackup() { TechPool techPool = database.getTechPool(); if (backup == null) { getTechnology(); backup = CellBackup.newInstance(getD().withoutVariables(), techPool); assert !cellBackupFresh && !cellContentsFresh && !revisionDateFresh; } ImmutableNodeInst[] nodes = null; ImmutableArcInst[] arcs = null; ImmutableExport[] exports = null; if (!cellContentsFresh) {// System.out.println("Refresh contents of " + this); nodes = backupNodes(); arcs = topology.backupArcs(backup.cellRevision.arcs); exports = backupExports(); } backup = backup.with(getD(), nodes, arcs, exports, techPool); cellBackupFresh = true; cellContentsFresh = true; if (backup.modified) lib.setChanged(); return backup; } private ImmutableNodeInst[] backupNodes() { ImmutableNodeInst[] newNodes = new ImmutableNodeInst[nodes.size()]; ImmutableArrayList<ImmutableNodeInst> oldNodes = backup.cellRevision.nodes; boolean changed = nodes.size() != oldNodes.size(); for (int i = 0; i < nodes.size(); i++) { NodeInst ni = nodes.get(i); ImmutableNodeInst d = ni.getD(); changed = changed || oldNodes.get(i) != d; newNodes[i] = d; } return changed ? newNodes : null; } private ImmutableExport[] backupExports() { ImmutableExport[] newExports = new ImmutableExport[exports.length]; ImmutableArrayList<ImmutableExport> oldExports = backup.cellRevision.exports; boolean changed = exports.length != oldExports.size(); for (int i = 0; i < exports.length; i++) { Export e = exports[i]; ImmutableExport d = e.getD(); changed = changed || oldExports.get(i) != d; newExports[i] = d; } return changed ? newExports : null; } void recover(CellBackup newBackup, ERectangle cellBounds) { assert cellBounds != null; this.cellBounds = cellBounds; update(true, newBackup, null); } void undo(CellBackup newBackup, ERectangle cellBounds, BitSet exportsModified, BitSet boundsModified) { if (backup == null) { recover(newBackup, cellBounds); return; } assert cellBackupFresh; assert boundsDirty == BOUNDS_CORRECT; this.cellBounds = cellBounds; if (backup != newBackup) { update(false, newBackup, exportsModified); } else if (exportsModified != null || boundsModified != null) { updateSubCells(exportsModified, boundsModified); } } private void update(boolean full, CellBackup newBackup, BitSet exportsModified) { checkUndoing(); boundsDirty = BOUNDS_RECOMPUTE; unfreshRTree(); CellRevision newRevision = newBackup.cellRevision; this.d = newRevision.d; lib = database.getLib(newRevision.d.getLibId()); tech = database.getTech(newRevision.d.techId); // Update NodeInsts nodes.clear(); essenBounds.clear(); maxSuffix.clear(); cellUsages = newRevision.getInstCounts(); for (int i = 0; i < newRevision.nodes.size(); i++) { ImmutableNodeInst d = newRevision.nodes.get(i); while (d.nodeId >= chronNodes.size()) chronNodes.add(null); NodeInst ni = chronNodes.get(d.nodeId); if (ni != null && ni.getProto().getId() == d.protoId) { ni.setDInUndo(d); if (ni.isCellInstance()) { int subCellIndex = ((Cell)ni.getProto()).getCellIndex(); if (full || exportsModified != null && exportsModified.get(subCellIndex)) ni.updatePortInsts(full); }// ni.lowLevelClearConnections(); } else { ni = NodeInst.lowLevelNewInstance(this, d); chronNodes.set(d.nodeId, ni); if (ni.isCellInstance()) { Cell subCell = (Cell)ni.getProto(); expandedNodes.set(d.nodeId, subCell.isWantExpanded()); expandStatusModified = true; } } ni.setNodeIndex(i); nodes.add(ni); updateMaxSuffix(ni); NodeProto np = ni.getProto(); if (np == Generic.tech().essentialBoundsNode) essenBounds.add(ni);// ni.check(); } assert nodes.size() == newRevision.nodes.size(); int nodeCount = 0; for (int i = 0; i < chronNodes.size(); i++) { NodeInst ni = chronNodes.get(i); if (ni == null) continue; int nodeIndex = ni.getNodeIndex(); if (nodeIndex >= nodes.size() || ni != nodes.get(nodeIndex)) { ni.setNodeIndex(-1); chronNodes.set(i, null); continue; } nodeCount++; } assert nodeCount == nodes.size(); topology.updateArcs(newRevision); exports = new Export[newRevision.exports.size()]; for (int i = 0; i < newRevision.exports.size(); i++) { ImmutableExport d = newRevision.exports.get(i); // Add to chronExports int chronIndex = d.exportId.getChronIndex(); if (chronExports.length <= chronIndex) { Export[] newChronExports = new Export[Math.max(chronIndex + 1, chronExports.length*2)]; System.arraycopy(chronExports, 0, newChronExports, 0, chronExports.length); chronExports = newChronExports; } Export e = chronExports[chronIndex]; if (e != null) { e.setDInUndo(d); } else { e = new Export(d, this); chronExports[chronIndex] = e; } e.setPortIndex(i); exports[i] = e; } int exportCount = 0; for (int i = 0; i < chronExports.length; i++) { Export e = chronExports[i]; if (e == null) continue; int portIndex = e.getPortIndex(); if (portIndex >= exports.length || e != exports[portIndex]) { e.setPortIndex(-1); chronExports[i] = null; continue; } exportCount++; } assert exportCount == exports.length; backup = newBackup; cellBackupFresh = true; cellContentsFresh = true; revisionDateFresh = true; getMemoization(); boundsDirty = BOUNDS_RECOMPUTE; ERectangle newBounds = computeBounds(); assert newBounds == cellBounds; boundsDirty = BOUNDS_CORRECT; topology.rebuildRTree(); assert boundsDirty == BOUNDS_CORRECT; } private void updateSubCells(BitSet exportsModified, BitSet boundsModified) { checkUndoing(); unfreshRTree(); if (boundsModified != null) boundsDirty = BOUNDS_RECOMPUTE; for (int i = 0; i < nodes.size(); i++) { NodeInst ni = nodes.get(i); if (!ni.isCellInstance()) continue; int subCellIndex = ((Cell)ni.getProto()).getCellIndex(); if (exportsModified != null && exportsModified.get(subCellIndex)) { ni.updatePortInsts(false); } if (boundsModified != null && boundsModified.get(subCellIndex)) ni.redoGeometric(); } if (boundsModified != null) { assert boundsDirty == BOUNDS_RECOMPUTE; ERectangle newBounds = computeBounds(); assert newBounds == cellBounds; boundsDirty = BOUNDS_CORRECT; } assert boundsDirty == BOUNDS_CORRECT; topology.rebuildRTree(); assert boundsDirty == BOUNDS_CORRECT; } /****************************** GRAPHICS ******************************/ /** * Method to get the width of this Cell. * @return the width of this Cell. */ public double getDefWidth() { return getBounds().getWidth(); } /** * Method to the height of this Cell. * @return the height of this Cell. */ public double getDefHeight() { return getBounds().getHeight(); } /** * Method to get the size offset of this Cell. * @return the size offset of this Cell. It is always zero for cells. */ public SizeOffset getProtoSizeOffset() { return SizeOffset.ZERO_OFFSET; } /** * Method to get the characteristic spacing for this Cell. * The characteristic spacing is used by the Array command to space these cells sensibly. * @return a dimension that is the characteristic spacing for this cell. * Returns null if there is no spacing defined. */// public Dimension2D getCharacteristicSpacing()// {// Variable var = getVar(CHARACTERISTIC_SPACING);// if (var != null)// {// Object obj = var.getObject();// if (obj instanceof Integer[])// {// Integer [] iSpac = (Integer [])obj;// Dimension2D spacing = new Dimension2D.Double(iSpac[0].intValue(), iSpac[1].intValue());// return spacing;// } else if (obj instanceof Double[])// {// Double [] dSpac = (Double [])obj;// Dimension2D spacing = new Dimension2D.Double(dSpac[0].doubleValue(), dSpac[1].doubleValue());// return spacing;// }// }// return null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -