📄 cellrevision.java
字号:
* 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; int portIndex = chronIndex < exportIndex.length ? exportIndex[chronIndex] : -1; return portIndex >= 0 ? exports.get(portIndex) : null; } /** * 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<TechId> getTechUsages() { LinkedHashSet<TechId> techUsagesSet = new LinkedHashSet<TechId>(); 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(); boolean hasCellCenter = false; ArrayList<ImmutableNodeInst> nodesById = new ArrayList<ImmutableNodeInst>(); ImmutableNodeInst prevN = null; for (ImmutableNodeInst n: nodes) { n.check(); if (ImmutableNodeInst.isCellCenter(n.protoId)) { assert !hasCellCenter; hasCellCenter = true; } while (n.nodeId >= nodesById.size()) nodesById.add(null); ImmutableNodeInst oldNode = nodesById.set(n.nodeId, n); assert oldNode == null; 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<Variable> 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; BitSet arcIds = new BitSet(); ImmutableArcInst prevA = null; for (ImmutableArcInst a: arcs) { assert !arcIds.get(a.arcId); arcIds.set(a.arcId); 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(nodesById.get(a.tailNodeId), a.tailPortId); checkPortInst(nodesById.get(a.headNodeId), a.headPortId); checkTechUsages.set(a.protoId.techId.techIndex); } if (exportIndex.length > 0) assert exportIndex[exportIndex.length - 1] >= 0; assert exportIndex.length == definedExportsLength; assert definedExports.length() == definedExportsLength; for (int i = 0; i < exports.size(); i++) { ImmutableExport e = exports.get(i); e.check(); assert e.exportId.parentId == cellId; assert exportIndex[e.exportId.chronIndex] == i; if (!busNamesAllowed) assert e.name.busWidth() == 1; if (i > 0) assert(TextUtils.STRING_NUMBER_ORDER.compare(exports.get(i - 1).name.toString(), e.name.toString()) < 0) : i; checkPortInst(nodesById.get(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<Variable.AttrKey,TextDescriptor.Unit> usedAttributes; CellUsageInfo(int instCount, BitSet usedExports, TreeMap<Variable.AttrKey,TextDescriptor.Unit> usedAttributes) { this.instCount = instCount; usedExportsLength = usedExports.length(); this.usedExports = usedExportsLength > 0 ? usedExports : EMPTY_BITSET; this.usedAttributes = usedAttributes; } CellUsageInfo with(int instCount, BitSet usedExports, TreeMap<Variable.AttrKey,TextDescriptor.Unit> 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<Variable.AttrKey,TextDescriptor.Unit> 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(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -