54
54
* This representation should be technology-independent
56
56
public class CellRevision {
57
58
public static final CellRevision[] NULL_ARRAY = {};
58
59
public static final ImmutableArrayList<CellRevision> EMPTY_LIST = new ImmutableArrayList<CellRevision>(NULL_ARRAY);
60
60
private static final int[] NULL_INT_ARRAY = {};
61
61
static final CellUsageInfo[] NULL_CELL_USAGE_INFO_ARRAY = {};
62
62
static int cellRevisionsCreated = 0;
63
/** Cell persistent data. */ public final ImmutableCell d;
64
/** An array of Exports on the Cell by chronological index. */ public final ImmutableArrayList<ImmutableExport> exports;
65
/** A list of NodeInsts in this Cell. */ public final ImmutableArrayList<ImmutableNodeInst> nodes;
66
/** A list of ArcInsts in this Cell. */ public final ImmutableArrayList<ImmutableArcInst> arcs;
67
/** TechId usage counts. */ final BitSet techUsages;
68
/** CellUsageInfos indexed by CellUsage.indefInParent */ final CellUsageInfo[] cellUsages;
63
/** Cell persistent data. */
64
public final ImmutableCell d;
65
/** An array of Exports on the Cell by chronological index. */
66
public final ImmutableArrayList<ImmutableExport> exports;
67
/** A list of NodeInsts in this Cell. */
68
public final ImmutableArrayList<ImmutableNodeInst> nodes;
69
/** A list of ArcInsts in this Cell. */
70
public final ImmutableArrayList<ImmutableArcInst> arcs;
71
/** TechId usage counts. */
72
final BitSet techUsages;
73
/** CellUsageInfos indexed by CellUsage.indefInParent */
74
final CellUsageInfo[] cellUsages;
69
75
/** definedExport == [0..definedExportLength) - deletedExports . */
70
/** Map from chronIndex of Exports to sortIndex. */ final int exportIndex[];
71
/** Bitmap of defined exports. */ final BitSet definedExports;
72
/** Length of defined exports. */ final int definedExportsLength;
73
/** Bitmap of deleted exports. */ final BitSet deletedExports;
76
/** Map from chronIndex of Exports to sortIndex. */
77
final int exportIndex[];
78
/** Bitmap of defined exports. */
79
final BitSet definedExports;
80
/** Length of defined exports. */
81
final int definedExportsLength;
82
/** Bitmap of deleted exports. */
83
final BitSet deletedExports;
75
85
/** Creates a new instance of CellRevision */
76
86
private CellRevision(ImmutableCell d,
112
123
* @return new CellRevision which differs from this CellRevision by revision date.
114
125
public CellRevision withRevisionDate(long revisionDate) {
115
if (d.revisionDate == revisionDate) return this;
126
if (d.revisionDate == revisionDate) {
116
129
return new CellRevision(this.d.withRevisionDate(revisionDate), this.nodes, this.arcs, this.exports,
117
130
this.techUsages, this.cellUsages, this.exportIndex,
118
131
this.definedExports, this.definedExportsLength, this.deletedExports);
163
178
for (int i = 0; i < nodes.size(); i++) {
164
179
ImmutableNodeInst n = nodes.get(i);
165
180
if (ImmutableNodeInst.isCellCenter(n.protoId)) {
167
182
throw new IllegalArgumentException("Duplicate cell center");
168
184
hasCellCenter = true;
170
if (prevN != null && TextUtils.STRING_NUMBER_ORDER.compare(prevN.name.toString(), n.name.toString()) >= 0)
186
if (!busNamesAllowed && n.name.isBus()) {
187
throw new IllegalArgumentException("arrayedName " + n.name);
189
if (prevN != null && TextUtils.STRING_NUMBER_ORDER.compare(prevN.name.toString(), n.name.toString()) >= 0) {
171
190
throw new IllegalArgumentException("nodes order");
196
if (arcs != this.arcs && !arcs.isEmpty()) {
197
ImmutableArcInst prevA = null;
198
for (int i = 0; i < arcs.size(); i++) {
199
ImmutableArcInst a = arcs.get(i);
200
if (!busNamesAllowed && a.name.isBus()) {
201
throw new IllegalArgumentException("arrayedName " + a.name);
204
int cmp = TextUtils.STRING_NUMBER_ORDER.compare(prevA.name.toString(), a.name.toString());
205
if (cmp > 0 || cmp == 0 && (a.name.isTempname() || prevA.arcId >= a.arcId))
206
throw new IllegalArgumentException("arcs order");
176
212
int[] exportIndex = this.exportIndex;
177
213
BitSet definedExports = this.definedExports;
178
214
int definedExportsLength = this.definedExportsLength;
180
216
if (exports != this.exports) {
181
217
int exportIndexLength = 0;
182
218
String prevExportName = null;
183
for (ImmutableExport e: exports) {
184
if (e.exportId.parentId != cellId)
219
for (ImmutableExport e : exports) {
220
if (e.exportId.parentId != cellId) {
185
221
throw new IllegalArgumentException("exportId");
186
223
String exportName = e.name.toString();
187
if (!busNamesAllowed && e.name.busWidth() != 1)
224
if (!busNamesAllowed && e.name.isBus()) {
188
225
throw new IllegalArgumentException("arrayedName " + e.name);
189
if (prevExportName != null && TextUtils.STRING_NUMBER_ORDER.compare(prevExportName, exportName) >= 0)
227
if (prevExportName != null && TextUtils.STRING_NUMBER_ORDER.compare(prevExportName, exportName) >= 0) {
190
228
throw new IllegalArgumentException("exportName");
191
230
prevExportName = exportName;
192
231
int chronIndex = e.exportId.chronIndex;
193
232
exportIndexLength = Math.max(exportIndexLength, chronIndex + 1);
270
316
ImmutableExport newExport = oldExport.withRenamedIds(idMapper);
271
317
if (newExport != oldExport && exportsArray == null) {
272
318
exportsArray = new ImmutableExport[exports.size()];
273
for (int j = 0; j < i; j++)
319
for (int j = 0; j < i; j++) {
274
320
exportsArray[j] = exports.get(j);
276
if (exportsArray != null)
323
if (exportsArray != null) {
277
324
exportsArray[i] = newExport;
280
if (this.d == d && nodesArray == null && arcsArray == null && exportsArray == null) return this;
328
if (this.d == d && nodesArray == null && arcsArray == null && exportsArray == null) {
281
331
CellRevision newRevision = with(d, nodesArray, arcsArray, exportsArray);
282
332
newRevision.check();
283
333
return newRevision;
287
* Returns ImmutableNodeInst by its node id.
288
* @param nodeId id of node.
289
* @return ImmutableNodeInst with this id or null if node doesn't exist.
292
public ImmutableNodeInst getNode(int nodeId) { return nodeId < nodes.size() ? nodes.get(nodeId) : null; }
295
* Returns ImmutableArcInst by its arc id.
296
* @param arcId id of node.
297
* @return ImmutableArcInst with this id or null if node doesn't exist.
300
public ImmutableArcInst getArc(int arcId) { return arcId < arcs.size() ? arcs.get(arcId) : null; }
303
337
* Returns ImmutableExport by its export id.
304
338
* @param exportId id of export.
305
339
* @return ImmutableExport with this id or null if node doesn't exist.
307
341
public ImmutableExport getExport(ExportId exportId) {
308
if (exportId.parentId != d.cellId)
342
if (exportId.parentId != d.cellId) {
309
343
throw new IllegalArgumentException();
310
345
int chronIndex = exportId.chronIndex;
311
346
int portIndex = chronIndex < exportIndex.length ? exportIndex[chronIndex] : -1;
312
347
return portIndex >= 0 ? exports.get(portIndex) : null;
350
public int getExportIndexByExportId(ExportId exportId) {
351
if (exportId.parentId != d.cellId) {
352
throw new IllegalArgumentException();
354
int chronIndex = exportId.chronIndex;
355
return chronIndex < exportIndex.length ? exportIndex[chronIndex] : -1;
316
359
* Returns subcell instance counts, indexed by CellUsage.indexInParent.
317
360
* @return subcell instance counts, indexed by CellUsage.indexInParent.
319
362
public int[] getInstCounts() {
320
363
int l = cellUsages.length;
321
while (l > 0 && (cellUsages[l - 1] == null || cellUsages[l - 1].instCount == 0)) l--;
322
if (l == 0) return NULL_INT_ARRAY;
364
while (l > 0 && (cellUsages[l - 1] == null || cellUsages[l - 1].instCount == 0)) {
368
return NULL_INT_ARRAY;
323
370
int[] instCounts = new int[l];
324
371
for (int indexInParent = 0; indexInParent < l; indexInParent++) {
325
if (cellUsages[indexInParent] != null)
372
if (cellUsages[indexInParent] != null) {
326
373
instCounts[indexInParent] = cellUsages[indexInParent].instCount;
328
376
return instCounts;
383
440
int nodesLength = reader.readInt();
384
441
ImmutableNodeInst[] nodes = new ImmutableNodeInst[nodesLength];
385
for (int i = 0; i < nodesLength; i++)
442
for (int i = 0; i < nodesLength; i++) {
386
443
nodes[i] = ImmutableNodeInst.read(reader);
388
446
int arcsLength = reader.readInt();
389
447
ImmutableArcInst[] arcs = new ImmutableArcInst[arcsLength];
390
for (int i = 0; i < arcsLength; i++)
448
for (int i = 0; i < arcsLength; i++) {
391
449
arcs[i] = ImmutableArcInst.read(reader);
393
452
int exportsLength = reader.readInt();
394
453
ImmutableExport[] exports = new ImmutableExport[exportsLength];
395
for (int i = 0; i < exportsLength; i++)
454
for (int i = 0; i < exportsLength; i++) {
396
455
exports[i] = ImmutableExport.read(reader);
398
458
revision = revision.with(d, nodes, arcs, exports);
403
* Checks invariant of this CellRevision.
404
* @throws AssertionError if invariant is broken.
463
* Checks invariant of this CellRevision.
464
* @throws AssertionError if invariant is broken.
406
466
public void check() {
408
468
CellId cellId = d.cellId;
413
473
boolean hasCellCenter = false;
414
474
ArrayList<ImmutableNodeInst> nodesById = new ArrayList<ImmutableNodeInst>();
415
475
ImmutableNodeInst prevN = null;
416
for (ImmutableNodeInst n: nodes) {
476
for (ImmutableNodeInst n : nodes) {
418
478
if (ImmutableNodeInst.isCellCenter(n.protoId)) {
419
479
assert !hasCellCenter;
420
480
hasCellCenter = true;
422
while (n.nodeId >= nodesById.size()) nodesById.add(null);
482
while (n.nodeId >= nodesById.size()) {
423
485
ImmutableNodeInst oldNode = nodesById.set(n.nodeId, n);
424
486
assert oldNode == null;
426
assert TextUtils.STRING_NUMBER_ORDER.compare(prevN.name.toString(), n.name.toString()) < 0;
487
assert busNamesAllowed || !n.name.isBus();
489
assert TextUtils.STRING_NUMBER_ORDER.compare(prevN.name.toString(), n.name.toString()) < 0;
428
492
if (n.protoId instanceof CellId) {
429
CellId subCellId = (CellId)n.protoId;
493
CellId subCellId = (CellId) n.protoId;
430
494
CellUsage u = cellId.getUsageIn(subCellId);
431
495
checkCellUsages[u.indexInParent]--;
432
496
CellUsageInfo cui = cellUsages[u.indexInParent];
433
497
assert cui != null;
434
498
for (int j = 0; j < n.ports.length; j++) {
435
499
ImmutablePortInst pid = n.ports[j];
436
if (pid == ImmutablePortInst.EMPTY) continue;
500
if (pid == ImmutablePortInst.EMPTY) {
437
503
checkPortInst(n, subCellId.getPortId(j));
439
505
if (subCellId.isIcon()) {
440
for (Variable param: n.getDefinedParams())
441
assert cui.usedAttributes.get((Variable.AttrKey)param.getKey()) == param.getUnit();
442
for (Iterator<Variable> it = n.getVariables(); it.hasNext(); ) {
506
for (Variable param : n.getDefinedParams()) {
507
assert cui.usedAttributes.get((Variable.AttrKey) param.getKey()) == param.getUnit();
509
for (Iterator<Variable> it = n.getVariables(); it.hasNext();) {
443
510
Variable.Key varKey = it.next().getKey();
444
if (varKey.isAttribute())
511
if (varKey.isAttribute()) {
445
512
assert cui.usedAttributes.get(varKey) == null;
449
TechId techId = ((PrimitiveNodeId)n.protoId).techId;
517
TechId techId = ((PrimitiveNodeId) n.protoId).techId;
450
518
checkTechUsages.set(techId.techIndex);
453
for (int i = 0; i < checkCellUsages.length; i++)
521
for (int i = 0; i < checkCellUsages.length; i++) {
454
522
assert checkCellUsages[i] == 0;
455
524
BitSet arcIds = new BitSet();
456
525
ImmutableArcInst prevA = null;
457
for (ImmutableArcInst a: arcs) {
526
for (ImmutableArcInst a : arcs) {
458
527
assert !arcIds.get(a.arcId);
459
528
arcIds.set(a.arcId);
461
int cmp = TextUtils.STRING_NUMBER_ORDER.compare(prevA.name.toString(), a.name.toString());
529
assert busNamesAllowed || !a.name.isBus();
531
int cmp = TextUtils.STRING_NUMBER_ORDER.compare(prevA.name.toString(), a.name.toString());
464
534
assert !a.name.isTempname();
465
assert prevA.arcId < a.arcId;
535
assert prevA.arcId < a.arcId;
505
576
checkDeleted.set(0, definedExportsLength);
506
577
checkDeleted.andNot(definedExports);
507
578
assert deletedExports.equals(checkDeleted);
508
if (definedExports.isEmpty())
579
if (definedExports.isEmpty()) {
509
580
assert definedExports == EMPTY_BITSET;
510
if (deletedExports.isEmpty())
582
if (deletedExports.isEmpty()) {
511
583
assert deletedExports == EMPTY_BITSET;
512
585
assert techUsages.equals(checkTechUsages);
514
if (d.cellId.isIcon())
587
if (d.cellId.isIcon()) {
515
588
assert cellUsages.length == 0;
516
590
for (int i = 0; i < cellUsages.length; i++) {
517
591
CellUsageInfo cui = cellUsages[i];
518
if (cui == null) continue;
519
595
cui.check(d.cellId.getUsageIn(i));
535
612
public boolean sameExports(CellRevision thatRevision) {
536
if (thatRevision == this) return true;
537
if (exports.size() != thatRevision.exports.size())
613
if (thatRevision == this) {
616
if (exports.size() != thatRevision.exports.size()) {
539
619
for (int i = 0; i < exports.size(); i++) {
540
if (exports.get(i).exportId != thatRevision.exports.get(i).exportId)
620
if (exports.get(i).exportId != thatRevision.exports.get(i).exportId) {
546
627
static class CellUsageInfo {
547
629
final int instCount;
548
630
final BitSet usedExports;
549
631
final int usedExportsLength;
550
final TreeMap<Variable.AttrKey,TextDescriptor.Unit> usedAttributes;
632
final TreeMap<Variable.AttrKey, TextDescriptor.Unit> usedAttributes;
552
CellUsageInfo(int instCount, BitSet usedExports, TreeMap<Variable.AttrKey,TextDescriptor.Unit> usedAttributes) {
634
CellUsageInfo(int instCount, BitSet usedExports, TreeMap<Variable.AttrKey, TextDescriptor.Unit> usedAttributes) {
553
635
this.instCount = instCount;
554
636
usedExportsLength = usedExports.length();
555
637
this.usedExports = usedExportsLength > 0 ? usedExports : EMPTY_BITSET;
556
638
this.usedAttributes = usedAttributes;
559
CellUsageInfo with(int instCount, BitSet usedExports, TreeMap<Variable.AttrKey,TextDescriptor.Unit> usedAttributes) {
641
CellUsageInfo with(int instCount, BitSet usedExports, TreeMap<Variable.AttrKey, TextDescriptor.Unit> usedAttributes) {
560
642
usedExports = UsageCollector.bitSetWith(this.usedExports, usedExports);
561
643
usedAttributes = UsageCollector.usedAttributesWith(this.usedAttributes, usedAttributes);
562
if (this.instCount == instCount && this.usedExports == usedExports &&
563
this.usedAttributes == usedAttributes) return this;
644
if (this.instCount == instCount && this.usedExports == usedExports
645
&& this.usedAttributes == usedAttributes) {
564
648
return new CellUsageInfo(instCount, usedExports, usedAttributes);
567
651
void checkUsage(CellRevision subCellRevision) {
568
if (subCellRevision == null)
652
if (subCellRevision == null) {
569
653
throw new IllegalArgumentException("subCell deleted");
570
if (subCellRevision.definedExportsLength < usedExportsLength || subCellRevision.deletedExports.intersects(usedExports))
655
if (subCellRevision.definedExportsLength < usedExportsLength || subCellRevision.deletedExports.intersects(usedExports)) {
571
656
throw new IllegalArgumentException("exportUsages");
573
for (Map.Entry<Variable.AttrKey,TextDescriptor.Unit> e: usedAttributes.entrySet()) {
659
for (Map.Entry<Variable.AttrKey, TextDescriptor.Unit> e : usedAttributes.entrySet()) {
574
660
Variable.AttrKey paramKey = e.getKey();
575
661
Variable param = subCellRevision.d.getParameter(paramKey);
576
662
TextDescriptor.Unit unit = e.getValue();
577
663
if (unit != null) {
578
if (param == null || param.getUnit() != unit)
664
if (param == null || param.getUnit() != unit) {
579
665
throw new IllegalArgumentException("param " + paramKey);
582
669
throw new IllegalArgumentException("param " + paramKey);
588
private boolean isIcon() { return usedAttributes != null; }
676
private boolean isIcon() {
677
return usedAttributes != null;
590
680
private void check(CellUsage u) {
591
assert instCount >= 0;
681
assert instCount > 0;
592
682
assert usedExportsLength == usedExports.length();
593
if (usedExportsLength == 0)
683
if (usedExportsLength == 0) {
594
684
assert usedExports == EMPTY_BITSET;
595
686
assert isIcon() == u.protoId.isIcon();
596
687
assert !u.parentId.isIcon();
601
public String toString() { return d.toString(); }
692
public String toString() {