📄 cellrevision.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: CellRevision.java * Written by: Dmitry Nadezhin, 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.database;import static com.sun.electric.database.UsageCollector.EMPTY_BITSET;import com.sun.electric.database.id.CellId;import com.sun.electric.database.id.CellUsage;import com.sun.electric.database.id.ExportId;import com.sun.electric.database.id.IdReader;import com.sun.electric.database.id.IdWriter;import com.sun.electric.database.id.PortProtoId;import com.sun.electric.database.id.PrimitiveNodeId;import com.sun.electric.database.id.TechId;import com.sun.electric.database.text.CellName;import com.sun.electric.database.text.ImmutableArrayList;import com.sun.electric.database.text.TextUtils;import com.sun.electric.database.variable.TextDescriptor;import com.sun.electric.database.variable.Variable;import java.io.IOException;import java.util.ArrayList;import java.util.Arrays;import java.util.BitSet;import java.util.Iterator;import java.util.LinkedHashSet;import java.util.Map;import java.util.Set;import java.util.TreeMap;/** * This class represents Cell data (with all arcs/nodes/exports) as it is saved to disk. * This representation should be technology-independent */public class CellRevision { public static final CellRevision[] NULL_ARRAY = {}; public static final ImmutableArrayList<CellRevision> EMPTY_LIST = new ImmutableArrayList<CellRevision>(NULL_ARRAY); private static final int[] NULL_INT_ARRAY = {}; static final CellUsageInfo[] NULL_CELL_USAGE_INFO_ARRAY = {}; static int cellRevisionsCreated = 0; /** Cell persistent data. */ public final ImmutableCell d; /** An array of Exports on the Cell by chronological index. */ public final ImmutableArrayList<ImmutableExport> exports; /** A list of NodeInsts in this Cell. */ public final ImmutableArrayList<ImmutableNodeInst> nodes; /** A list of ArcInsts in this Cell. */ public final ImmutableArrayList<ImmutableArcInst> arcs; /** TechId usage counts. */ final BitSet techUsages; /** CellUsageInfos indexed by CellUsage.indefInParent */ final CellUsageInfo[] cellUsages; /** definedExport == [0..definedExportLength) - deletedExports . */ /** Map from chronIndex of Exports to sortIndex. */ final int exportIndex[]; /** Bitmap of defined exports. */ final BitSet definedExports; /** Length of defined exports. */ final int definedExportsLength; /** Bitmap of deleted exports. */ final BitSet deletedExports; /** Creates a new instance of CellRevision */ private CellRevision(ImmutableCell d, ImmutableArrayList<ImmutableNodeInst> nodes, ImmutableArrayList<ImmutableArcInst> arcs, ImmutableArrayList<ImmutableExport> exports, BitSet techUsages, CellUsageInfo[] cellUsages, int[] exportIndex, BitSet definedExports, int definedExportsLength, BitSet deletedExports) { this.d = d; this.nodes = nodes; this.arcs = arcs; this.exports = exports; this.techUsages = techUsages; this.cellUsages = cellUsages; this.exportIndex = exportIndex; this.definedExports = definedExports; this.definedExportsLength = definedExportsLength; this.deletedExports = deletedExports; cellRevisionsCreated++; } /** Creates a new instance of CellRevision */ public CellRevision(ImmutableCell d) { this(d, ImmutableNodeInst.EMPTY_LIST, ImmutableArcInst.EMPTY_LIST, ImmutableExport.EMPTY_LIST, makeTechUsages(d.techId), NULL_CELL_USAGE_INFO_ARRAY, NULL_INT_ARRAY, EMPTY_BITSET, 0, EMPTY_BITSET); if (d.techId == null) throw new NullPointerException("techId"); } private static BitSet makeTechUsages(TechId techId) { BitSet techUsages = new BitSet(); techUsages.set(techId.techIndex); return techUsages; } /** * Creates a new instance of CellRevision which differs from this CellRevision by revision date. * @param revisionDate new revision date. * @return new CellRevision which differs from this CellRevision by revision date. */ public CellRevision withRevisionDate(long revisionDate) { if (d.revisionDate == revisionDate) return this; return new CellRevision(this.d.withRevisionDate(revisionDate), this.nodes, this.arcs, this.exports, this.techUsages, this.cellUsages, this.exportIndex, this.definedExports, this.definedExportsLength, this.deletedExports); } /** * Creates a new instance of CellRevision which differs from this CellRevision. * Four array parameters are supplied. Each parameter may be null if its contents is the same as in this Snapshot. * @param d new persistent data of a cell. * @param nodesArray new array of nodes * @param arcsArray new array of arcs * @param exportsArray new array of exports * @return new snapshot which differs froms this Snapshot or this Snapshot. * @throws IllegalArgumentException on invariant violation. * @throws ArrayOutOfBoundsException on some invariant violations. */ public CellRevision with(ImmutableCell d, ImmutableNodeInst[] nodesArray, ImmutableArcInst[] arcsArray, ImmutableExport[] exportsArray) { ImmutableArrayList<ImmutableNodeInst> nodes = copyArray(nodesArray, this.nodes); ImmutableArrayList<ImmutableArcInst> arcs = copyArray(arcsArray, this.arcs); ImmutableArrayList<ImmutableExport> exports = copyArray(exportsArray, this.exports); if (this.d == d && this.nodes == nodes && this.arcs == arcs && this.exports == exports) { return this; } CellId cellId = d.cellId; boolean busNamesAllowed = d.busNamesAllowed(); if (this.d != d) { if (d.techId == null) throw new NullPointerException("tech");// if (cellId != this.d.cellId)// throw new IllegalArgumentException("cellId"); } BitSet techUsages = this.techUsages; CellUsageInfo[] cellUsages = this.cellUsages; if (this.d.cellId != d.cellId || this.d.techId != d.techId || this.d.getVars() != d.getVars() || nodes != this.nodes || arcs != this.arcs || exports != this.exports) { UsageCollector uc = new UsageCollector(d, nodes, arcs, exports); techUsages = uc.getTechUsages(this.techUsages); cellUsages = uc.getCellUsages(this.cellUsages); } if (cellId.isIcon() && cellUsages.length != 0) throw new IllegalArgumentException("Icon contains subcells"); if (nodes != this.nodes && !nodes.isEmpty()) { boolean hasCellCenter = false; ImmutableNodeInst prevN = null; for (int i = 0; i < nodes.size(); i++) { ImmutableNodeInst n = nodes.get(i); if (ImmutableNodeInst.isCellCenter(n.protoId)) { if (hasCellCenter) throw new IllegalArgumentException("Duplicate cell center"); hasCellCenter = true; } if (prevN != null && TextUtils.STRING_NUMBER_ORDER.compare(prevN.name.toString(), n.name.toString()) >= 0) throw new IllegalArgumentException("nodes order"); prevN = n; } } int[] exportIndex = this.exportIndex; BitSet definedExports = this.definedExports; int definedExportsLength = this.definedExportsLength; BitSet deletedExports = this.deletedExports; if (exports != this.exports) { int exportIndexLength = 0; String prevExportName = null; for (ImmutableExport e: exports) { if (e.exportId.parentId != cellId) throw new IllegalArgumentException("exportId"); String exportName = e.name.toString(); if (!busNamesAllowed && e.name.busWidth() != 1) throw new IllegalArgumentException("arrayedName " + e.name); if (prevExportName != null && TextUtils.STRING_NUMBER_ORDER.compare(prevExportName, exportName) >= 0) throw new IllegalArgumentException("exportName"); prevExportName = exportName; int chronIndex = e.exportId.chronIndex; exportIndexLength = Math.max(exportIndexLength, chronIndex + 1); } exportIndex = new int[exportIndexLength]; Arrays.fill(exportIndex, -1); for (int portIndex = 0; portIndex < exports.size(); portIndex++) { ImmutableExport e = exports.get(portIndex); int chronIndex = e.exportId.chronIndex; if (exportIndex[chronIndex] >= 0) throw new IllegalArgumentException("exportChronIndex"); exportIndex[chronIndex] = portIndex; //checkPortInst(nodesById.get(e.originalNodeId), e.originalPortId); } if (Arrays.equals(this.exportIndex, exportIndex)) { exportIndex = this.exportIndex; } else { definedExports = new BitSet(); for (int chronIndex = 0; chronIndex < exportIndex.length; chronIndex++) { if (exportIndex[chronIndex] < 0) continue; definedExports.set(chronIndex); } definedExports = UsageCollector.bitSetWith(this.definedExports, definedExports); if (definedExports != this.definedExports) { definedExportsLength = definedExports.length(); deletedExports = new BitSet(); deletedExports.set(0, definedExportsLength); deletedExports.andNot(definedExports); deletedExports = UsageCollector.bitSetWith(this.deletedExports, deletedExports); } } } CellRevision revision = new CellRevision(d, nodes, arcs, exports, techUsages, cellUsages, exportIndex, definedExports, definedExportsLength, deletedExports); return revision; } private static <T> ImmutableArrayList<T> copyArray(T[] newArray, ImmutableArrayList<T> oldList) { return newArray != null ? new ImmutableArrayList<T>(newArray) : oldList; } /** * Returns CellRevision which differs from this CellRevision by renamed Ids. * @param idMapper a map from old Ids to new Ids. * @return CellRevision with renamed Ids. */ CellRevision withRenamedIds(IdMapper idMapper, CellName newGroupName) { ImmutableCell d = this.d.withRenamedIds(idMapper).withGroupName(newGroupName); ImmutableNodeInst[] nodesArray = null; for (int i = 0; i < nodes.size(); i++) { ImmutableNodeInst oldNode = nodes.get(i); ImmutableNodeInst newNode = oldNode.withRenamedIds(idMapper); if (newNode != oldNode && nodesArray == null) { nodesArray = new ImmutableNodeInst[nodes.size()]; for (int j = 0; j < i; j++) nodesArray[j] = nodes.get(j); } if (nodesArray != null) nodesArray[i] = newNode; } ImmutableArcInst[] arcsArray = null; for (int i = 0; i < arcs.size(); i++) { ImmutableArcInst oldArc = arcs.get(i); ImmutableArcInst newArc = oldArc.withRenamedIds(idMapper); if (newArc != oldArc && arcsArray == null) { arcsArray = new ImmutableArcInst[arcs.size()]; for (int j = 0; j < i; j++) arcsArray[j] = arcs.get(j); } if (arcsArray != null) arcsArray[i] = newArc; } ImmutableExport[] exportsArray = null; for (int i = 0; i < exports.size(); i++) { ImmutableExport oldExport = exports.get(i); ImmutableExport newExport = oldExport.withRenamedIds(idMapper); if (newExport != oldExport && exportsArray == null) { exportsArray = new ImmutableExport[exports.size()]; for (int j = 0; j < i; j++) exportsArray[j] = exports.get(j); } if (exportsArray != null) exportsArray[i] = newExport; } if (this.d == d && nodesArray == null && arcsArray == null && exportsArray == null) return this; CellRevision newRevision = with(d, nodesArray, arcsArray, exportsArray); newRevision.check(); return newRevision; } /** * Returns ImmutableNodeInst by its node id. * @param nodeId id of node. * @return ImmutableNodeInst with this id or null if node doesn't exist. */ // FIX ME !!! public ImmutableNodeInst getNode(int nodeId) { return nodeId < nodes.size() ? nodes.get(nodeId) : null; } /** * Returns ImmutableArcInst by its arc id. * @param arcId id of node. * @return ImmutableArcInst with this id or null if node doesn't exist. */ // FIX ME !!! public ImmutableArcInst getArc(int arcId) { return arcId < arcs.size() ? arcs.get(arcId) : null; } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -