![JAR search and dependency download from the Maven repository](/logo.png)
com.sun.electric.database.CellRevision Maven / Gradle / Ivy
/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: CellRevision.java
* Written by: Dmitry Nadezhin, Sun Microsystems.
*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
*
* 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.variable.TextDescriptor;
import com.sun.electric.database.variable.Variable;
import com.sun.electric.tool.Job;
import com.sun.electric.util.TextUtils;
import com.sun.electric.util.collections.ImmutableArrayList;
import java.io.IOException;
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 EMPTY_LIST = new ImmutableArrayList(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;
/** A list of NodeInsts in this Cell. */
public final ImmutableArrayList nodes;
/** Map from chronIndex of Nodes to sortIndex. */
final int nodeIndex[];
/** A list of ArcInsts in this Cell. */
public final ImmutableArrayList arcs;
/** Map from chronIndex of Arcs to sortIndex. */
final int arcIndex[];
/** An array of Exports on the Cell by chronological index. */
public final ImmutableArrayList exports;
/** Map from chronIndex of Exports to sortIndex. */
final int exportIndex[];
/** TechId usage counts. */
final BitSet techUsages;
/** CellUsageInfos indexed by CellUsage.indefInParent */
final CellUsageInfo[] cellUsages;
/** definedExport == [0..definedExportLength) - deletedExports . */
/** 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 nodes, int[] nodeIndex,
ImmutableArrayList arcs, int[] arcIndex,
ImmutableArrayList exports, int[] exportIndex,
BitSet techUsages,
CellUsageInfo[] cellUsages, BitSet definedExports, int definedExportsLength, BitSet deletedExports) {
this.d = d;
this.nodes = nodes;
this.nodeIndex = nodeIndex;
this.arcs = arcs;
this.arcIndex = arcIndex;
this.exports = exports;
this.exportIndex = exportIndex;
this.techUsages = techUsages;
this.cellUsages = cellUsages;
this.definedExports = definedExports;
this.definedExportsLength = definedExportsLength;
this.deletedExports = deletedExports;
cellRevisionsCreated++;
if (Job.getDebug())
check();
}
/** Creates a new instance of CellRevision */
public CellRevision(ImmutableCell d) {
this(d, ImmutableNodeInst.EMPTY_LIST, NULL_INT_ARRAY,
ImmutableArcInst.EMPTY_LIST, NULL_INT_ARRAY,
ImmutableExport.EMPTY_LIST, NULL_INT_ARRAY,
makeTechUsages(d.techId), NULL_CELL_USAGE_INFO_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.nodeIndex,
this.arcs, this.arcIndex,
this.exports, this.exportIndex,
this.techUsages, this.cellUsages,
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 nodes = copyArray(nodesArray, this.nodes);
ImmutableArrayList arcs = copyArray(arcsArray, this.arcs);
ImmutableArrayList 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");
}
int[] nodeIndex = this.nodeIndex;
if (nodes != this.nodes && !nodes.isEmpty()) {
boolean sameNodeIndex = nodes.size() == this.nodes.size();
int nodeIndexLength = 0;
boolean hasCellCenter = false;
ImmutableNodeInst prevN = null;
for (int nodeInd = 0; nodeInd < nodes.size(); nodeInd++) {
ImmutableNodeInst n = nodes.get(nodeInd);
sameNodeIndex = sameNodeIndex && n.nodeId == this.nodes.get(nodeInd).nodeId;
nodeIndexLength = Math.max(nodeIndexLength, n.nodeId + 1);
if (ImmutableNodeInst.isCellCenter(n.protoId)) {
if (hasCellCenter) {
throw new IllegalArgumentException("Duplicate cell center");
}
hasCellCenter = true;
}
if (!busNamesAllowed && n.name.isBus()) {
throw new IllegalArgumentException("arrayedName " + n.name);
}
if (prevN != null && TextUtils.STRING_NUMBER_ORDER.compare(prevN.name.toString(), n.name.toString()) >= 0) {
throw new IllegalArgumentException("nodes order");
}
prevN = n;
}
if (!sameNodeIndex) {
nodeIndex = new int[nodeIndexLength];
Arrays.fill(nodeIndex, -1);
for (int nodeInd = 0; nodeInd < nodes.size(); nodeInd++) {
ImmutableNodeInst n = nodes.get(nodeInd);
int nodeId = n.nodeId;
if (nodeIndex[nodeId] >= 0) {
throw new IllegalArgumentException("nodeChronIndex");
}
nodeIndex[nodeId] = nodeInd;
}
assert !Arrays.equals(this.nodeIndex, nodeIndex);
}
}
int[] arcIndex = this.arcIndex;
if (arcs != this.arcs && !arcs.isEmpty()) {
boolean sameArcIndex = arcs.size() == this.arcs.size();
int arcIndexLength = 0;
ImmutableArcInst prevA = null;
for (int arcInd = 0; arcInd < arcs.size(); arcInd++) {
ImmutableArcInst a = arcs.get(arcInd);
sameArcIndex = sameArcIndex && a.arcId == this.arcs.get(arcInd).arcId;
arcIndexLength = Math.max(arcIndexLength, a.arcId + 1);
if (!busNamesAllowed && a.name.isBus()) {
throw new IllegalArgumentException("arrayedName " + a.name);
}
if (prevA != null) {
int cmp = TextUtils.STRING_NUMBER_ORDER.compare(prevA.name.toString(), a.name.toString());
if (cmp > 0 || cmp == 0 && (a.name.isTempname() || prevA.arcId >= a.arcId)) {
throw new IllegalArgumentException("arcs order");
}
}
prevA = a;
}
if (!sameArcIndex) {
arcIndex = new int[arcIndexLength];
Arrays.fill(arcIndex, -1);
for (int arcInd = 0; arcInd < arcs.size(); arcInd++) {
ImmutableArcInst a = arcs.get(arcInd);
int arcId = a.arcId;
if (arcIndex[arcId] >= 0) {
throw new IllegalArgumentException("arcChronIndex");
}
arcIndex[arcId] = arcInd;
}
assert !Arrays.equals(this.arcIndex, arcIndex);
}
}
int[] exportIndex = this.exportIndex;
BitSet definedExports = this.definedExports;
int definedExportsLength = this.definedExportsLength;
BitSet deletedExports = this.deletedExports;
if (exports != this.exports) {
boolean sameExportIndex = exports.size() == this.exports.size();
int exportIndexLength = 0;
String prevExportName = null;
for (int exportInd = 0; exportInd < exports.size(); exportInd++) {
ImmutableExport e = exports.get(exportInd);
if (e.exportId.parentId != cellId) {
throw new IllegalArgumentException("exportId");
}
String exportName = e.name.toString();
if (!busNamesAllowed && e.name.isBus()) {
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;
sameExportIndex = sameExportIndex && chronIndex == this.exports.get(exportInd).exportId.chronIndex;
exportIndexLength = Math.max(exportIndexLength, chronIndex + 1);
}
if (!sameExportIndex) {
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);
}
assert !Arrays.equals(this.exportIndex, exportIndex);
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, nodeIndex,
arcs, arcIndex,
exports, exportIndex,
techUsages, cellUsages, definedExports, definedExportsLength, deletedExports);
return revision;
}
private static ImmutableArrayList copyArray(T[] newArray, ImmutableArrayList oldList) {
return newArray != null ? new ImmutableArrayList(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 nodeId.
* @param nodeId of ImmutableNodeInst.
* @return ImmutableNodeInst with given nodeId
*/
public ImmutableNodeInst getNodeById(int nodeId) {
if (nodeId >= nodeIndex.length) {
return null;
}
int nodeInd = nodeIndex[nodeId];
return nodeInd >= 0 ? nodes.get(nodeInd) : null;
}
/**
* Returns sort order index of ImmutableNodeInst by its nodeId.
* @param nodeId of ImmutableNodeInst.
* @return sort order index of node
*/
public int getNodeIndexByNodeId(int nodeId) {
return nodeId < nodeIndex.length ? nodeIndex[nodeId] : -1;
}
/**
* Returns maximum nodeId used by nodes of this CellReversion.
* Returns -1 if CellRevsison doesn't contatin nodes
* @return maximum nodeId
*/
public int getMaxNodeId() {
return nodeIndex.length - 1;
}
/**
* Returns ImmutableArcInst by its arcId.
* @param arcId of ImmutableArcInst.
* @return ImmutableArcInst with given arcId
*/
public ImmutableArcInst getArcById(int arcId) {
if (arcId >= arcIndex.length) {
return null;
}
int arcInd = arcIndex[arcId];
return arcInd >= 0 ? arcs.get(arcInd) : null;
}
/**
* Returns sort order index of ImmutableArcInst by its arcId.
* @param arcId of ImmutableArcInst.
* @return sort order index of arc
*/
public int getArcIndexByArcId(int arcId) {
return arcId < arcIndex.length ? arcIndex[arcId] : -1;
}
/**
* Returns maximum arcId used by arcs of this CellReversion.
* Returns -1 if CellRevsison doesn't contatin arcs
* @return maximum arcId
*/
public int getMaxArcId() {
return arcIndex.length - 1;
}
/**
* Returns ImmutableExport by its export id.
* @param exportId id of export.
* @return ImmutableExport with this id or null if node doesn't exist.
*/
public ImmutableExport getExport(ExportId exportId) {
if (exportId.parentId != d.cellId) {
throw new IllegalArgumentException();
}
int chronIndex = exportId.chronIndex;
if (chronIndex >= exportIndex.length) {
return null;
}
int portIndex = exportIndex[chronIndex];
return portIndex >= 0 ? exports.get(portIndex) : null;
}
/**
* Returns sort order index of ImmutableExport by its export id.
* @param exportId id of export.
* @return sort order index of export
*/
public int getExportIndexByExportId(ExportId exportId) {
if (exportId.parentId != d.cellId) {
throw new IllegalArgumentException();
}
int chronIndex = exportId.chronIndex;
return chronIndex < exportIndex.length ? exportIndex[chronIndex] : -1;
}
/**
* Returns subcell instance counts, indexed by CellUsage.indexInParent.
* @return subcell instance counts, indexed by CellUsage.indexInParent.
*/
public int[] getInstCounts() {
int l = cellUsages.length;
while (l > 0 && (cellUsages[l - 1] == null || cellUsages[l - 1].instCount == 0)) {
l--;
}
if (l == 0) {
return NULL_INT_ARRAY;
}
int[] instCounts = new int[l];
for (int indexInParent = 0; indexInParent < l; indexInParent++) {
if (cellUsages[indexInParent] != null) {
instCounts[indexInParent] = cellUsages[indexInParent].instCount;
}
}
return instCounts;
}
/**
* For given CellUsage in this cell returns count of subcell instances.
* @param u CellUsage.
* @return count of subcell instances.
* @throws IllegalArgumentException if CellUsage's parent is not this cell.
*/
public int getInstCount(CellUsage u) {
if (u.parentId != d.cellId) {
throw new IllegalArgumentException();
}
if (u.indexInParent >= cellUsages.length) {
return 0;
}
CellUsageInfo cui = cellUsages[u.indexInParent];
if (cui == null) {
return 0;
}
return cui.instCount;
}
/**
* Returns Set of Technologies used in this CellRevision
*/
public Set getTechUsages() {
LinkedHashSet techUsagesSet = new LinkedHashSet();
for (int techIndex = 0; techIndex < techUsages.length(); techIndex++) {
if (techUsages.get(techIndex)) {
techUsagesSet.add(d.cellId.idManager.getTechId(techIndex));
}
}
return techUsagesSet;
}
/**
* Writes this CellRevision to IdWriter.
* @param writer where to write.
*/
void write(IdWriter writer) throws IOException {
d.write(writer);
writer.writeInt(nodes.size());
for (ImmutableNodeInst n : nodes) {
n.write(writer);
}
writer.writeInt(arcs.size());
for (ImmutableArcInst a : arcs) {
a.write(writer);
}
writer.writeInt(exports.size());
for (ImmutableExport e : exports) {
e.write(writer);
}
}
/**
* Reads CellRevision from SnapshotReader.
* @param reader where to read.
*/
static CellRevision read(IdReader reader) throws IOException {
ImmutableCell d = ImmutableCell.read(reader);
CellRevision revision = new CellRevision(d.withoutVariables());
int nodesLength = reader.readInt();
ImmutableNodeInst[] nodes = new ImmutableNodeInst[nodesLength];
for (int i = 0; i < nodesLength; i++) {
nodes[i] = ImmutableNodeInst.read(reader);
}
int arcsLength = reader.readInt();
ImmutableArcInst[] arcs = new ImmutableArcInst[arcsLength];
for (int i = 0; i < arcsLength; i++) {
arcs[i] = ImmutableArcInst.read(reader);
}
int exportsLength = reader.readInt();
ImmutableExport[] exports = new ImmutableExport[exportsLength];
for (int i = 0; i < exportsLength; i++) {
exports[i] = ImmutableExport.read(reader);
}
revision = revision.with(d, nodes, arcs, exports);
return revision;
}
/**
* Checks invariant of this CellRevision.
* @throws AssertionError if invariant is broken.
*/
public void check() {
d.check();
CellId cellId = d.cellId;
boolean busNamesAllowed = d.busNamesAllowed();
BitSet checkTechUsages = new BitSet();
checkTechUsages.set(d.techId.techIndex);
int[] checkCellUsages = getInstCounts();
// Check nodes
boolean hasCellCenter = false;
if (nodeIndex.length > 0) {
assert nodeIndex[nodeIndex.length - 1] >= 0;
}
ImmutableNodeInst prevN = null;
for (int nodeInd = 0; nodeInd < nodes.size(); nodeInd++) {
ImmutableNodeInst n = nodes.get(nodeInd);
n.check();
assert nodeIndex[n.nodeId] == nodeInd;
assert getNodeById(n.nodeId) == n;
if (ImmutableNodeInst.isCellCenter(n.protoId)) {
assert !hasCellCenter;
hasCellCenter = true;
}
assert busNamesAllowed || !n.name.isBus();
if (prevN != null) {
assert TextUtils.STRING_NUMBER_ORDER.compare(prevN.name.toString(), n.name.toString()) < 0;
}
prevN = n;
if (n.protoId instanceof CellId) {
CellId subCellId = (CellId) n.protoId;
CellUsage u = cellId.getUsageIn(subCellId);
checkCellUsages[u.indexInParent]--;
CellUsageInfo cui = cellUsages[u.indexInParent];
assert cui != null;
for (int j = 0; j < n.ports.length; j++) {
ImmutablePortInst pid = n.ports[j];
if (pid == ImmutablePortInst.EMPTY) {
continue;
}
checkPortInst(n, subCellId.getPortId(j));
}
if (subCellId.isIcon()) {
for (Variable param : n.getDefinedParams()) {
assert cui.usedAttributes.get((Variable.AttrKey) param.getKey()) == param.getUnit();
}
for (Iterator it = n.getVariables(); it.hasNext();) {
Variable.Key varKey = it.next().getKey();
if (varKey.isAttribute()) {
assert cui.usedAttributes.get(varKey) == null;
}
}
}
} else {
TechId techId = ((PrimitiveNodeId) n.protoId).techId;
checkTechUsages.set(techId.techIndex);
}
}
for (int i = 0; i < checkCellUsages.length; i++) {
assert checkCellUsages[i] == 0;
}
// Check arcs
if (arcIndex.length > 0) {
assert arcIndex[arcIndex.length - 1] >= 0;
}
ImmutableArcInst prevA = null;
for (int arcInd = 0; arcInd < arcs.size(); arcInd++) {
ImmutableArcInst a = arcs.get(arcInd);
assert arcIndex[a.arcId] == arcInd;
assert getArcById(a.arcId) == a;
assert busNamesAllowed || !a.name.isBus();
if (prevA != null) {
int cmp = TextUtils.STRING_NUMBER_ORDER.compare(prevA.name.toString(), a.name.toString());
assert cmp <= 0;
if (cmp == 0) {
assert !a.name.isTempname();
assert prevA.arcId < a.arcId;
}
}
prevA = a;
a.check();
checkPortInst(getNodeById(a.tailNodeId), a.tailPortId);
checkPortInst(getNodeById(a.headNodeId), a.headPortId);
checkTechUsages.set(a.protoId.techId.techIndex);
}
// Check exports
if (exportIndex.length > 0) {
assert exportIndex[exportIndex.length - 1] >= 0;
}
assert exportIndex.length == definedExportsLength;
assert definedExports.length() == definedExportsLength;
for (int exportInd = 0; exportInd < exports.size(); exportInd++) {
ImmutableExport e = exports.get(exportInd);
e.check();
assert e.exportId.parentId == cellId;
assert exportIndex[e.exportId.chronIndex] == exportInd;
assert busNamesAllowed || !e.name.isBus();
if (exportInd > 0) {
assert (TextUtils.STRING_NUMBER_ORDER.compare(exports.get(exportInd - 1).name.toString(), e.name.toString()) < 0) : exportInd;
}
checkPortInst(getNodeById(e.originalNodeId), e.originalPortId);
}
int exportCount = 0;
for (int chronIndex = 0; chronIndex < exportIndex.length; chronIndex++) {
int portIndex = exportIndex[chronIndex];
if (portIndex == -1) {
assert !definedExports.get(chronIndex);
continue;
}
assert definedExports.get(chronIndex);
exportCount++;
assert exports.get(portIndex).exportId.chronIndex == chronIndex;
}
assert exports.size() == exportCount;
BitSet checkDeleted = new BitSet();
checkDeleted.set(0, definedExportsLength);
checkDeleted.andNot(definedExports);
assert deletedExports.equals(checkDeleted);
if (definedExports.isEmpty()) {
assert definedExports == EMPTY_BITSET;
}
if (deletedExports.isEmpty()) {
assert deletedExports == EMPTY_BITSET;
}
assert techUsages.equals(checkTechUsages);
if (d.cellId.isIcon()) {
assert cellUsages.length == 0;
}
for (int i = 0; i < cellUsages.length; i++) {
CellUsageInfo cui = cellUsages[i];
if (cui == null) {
continue;
}
cui.check(d.cellId.getUsageIn(i));
}
}
private void checkPortInst(ImmutableNodeInst node, PortProtoId portId) {
assert node != null;
assert portId.getParentId() == node.protoId;
if (portId instanceof ExportId) {
checkExportId((ExportId) portId);
}
}
private void checkExportId(ExportId exportId) {
CellUsage u = d.cellId.getUsageIn(exportId.getParentId());
assert cellUsages[u.indexInParent].usedExports.get(exportId.getChronIndex());
}
public boolean sameExports(CellRevision thatRevision) {
if (thatRevision == this) {
return true;
}
if (exports.size() != thatRevision.exports.size()) {
return false;
}
for (int i = 0; i < exports.size(); i++) {
if (exports.get(i).exportId != thatRevision.exports.get(i).exportId) {
return false;
}
}
return true;
}
static class CellUsageInfo {
final int instCount;
final BitSet usedExports;
final int usedExportsLength;
final TreeMap usedAttributes;
CellUsageInfo(int instCount, BitSet usedExports, TreeMap usedAttributes) {
this.instCount = instCount;
usedExportsLength = usedExports.length();
this.usedExports = usedExportsLength > 0 ? usedExports : EMPTY_BITSET;
this.usedAttributes = usedAttributes;
}
CellUsageInfo with(int instCount, BitSet usedExports, TreeMap usedAttributes) {
usedExports = UsageCollector.bitSetWith(this.usedExports, usedExports);
usedAttributes = UsageCollector.usedAttributesWith(this.usedAttributes, usedAttributes);
if (this.instCount == instCount && this.usedExports == usedExports
&& this.usedAttributes == usedAttributes) {
return this;
}
return new CellUsageInfo(instCount, usedExports, usedAttributes);
}
void checkUsage(CellRevision subCellRevision) {
if (subCellRevision == null) {
throw new IllegalArgumentException("subCell deleted");
}
if (subCellRevision.definedExportsLength < usedExportsLength || subCellRevision.deletedExports.intersects(usedExports)) {
throw new IllegalArgumentException("exportUsages");
}
if (isIcon()) {
for (Map.Entry e : usedAttributes.entrySet()) {
Variable.AttrKey paramKey = e.getKey();
Variable param = subCellRevision.d.getParameter(paramKey);
TextDescriptor.Unit unit = e.getValue();
if (unit != null) {
if (param == null || param.getUnit() != unit) {
throw new IllegalArgumentException("param " + paramKey);
}
} else {
if (param != null) {
throw new IllegalArgumentException("param " + paramKey);
}
}
}
}
}
private boolean isIcon() {
return usedAttributes != null;
}
private void check(CellUsage u) {
assert instCount > 0;
assert usedExportsLength == usedExports.length();
if (usedExportsLength == 0) {
assert usedExports == EMPTY_BITSET;
}
assert isIcon() == u.protoId.isIcon();
assert !u.parentId.isIcon();
}
}
@Override
public String toString() {
return d.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy