327
344
* @param cell the Cell in question.
328
345
* @return true if the Cell is in this CellGroup.
330
public boolean containsCell(Cell cell) { return cell != null && cells.contains(cell); }
333
* Returns a printable version of this CellGroup.
334
* @return a printable version of this CellGroup.
336
public String toString() { return "CellGroup " + getName(); }
339
* Method to compare two CellGroups.
340
* Because CellGroups seem to be ephemeral, and are created dynamically,
341
* it is not possible to compare them by equating the object.
342
* Therefore, this override compares the group names.
343
* Although not accurate, it is better than simple object equality.
345
public boolean equals(Object obj)
347
if (obj instanceof CellGroup && groupName != null)
349
return groupName.equals(((CellGroup)obj).groupName);
347
public boolean containsCell(Cell cell) {
348
return cell != null && cells.contains(cell);
352
* Returns a printable version of this CellGroup.
353
* @return a printable version of this CellGroup.
355
public String toString() {
356
return "CellGroup " + getName();
360
* Method to compare two CellGroups.
361
* Because CellGroups seem to be ephemeral, and are created dynamically,
362
* it is not possible to compare them by equating the object.
363
* Therefore, this override compares the group names.
364
* Although not accurate, it is better than simple object equality.
366
public boolean equals(Object obj) {
367
if (obj instanceof CellGroup && groupName != null) {
368
return groupName.equals(((CellGroup) obj).groupName);
355
374
* Returns a string representing the name of the cell group
357
public String getName() { return groupName != null ? groupName.getName() : null; }
359
public EDatabase getDatabase() { return lib.getDatabase(); }
362
* Method to check invariants in this CellGroup.
363
* @exception AssertionError if invariants are not valid
367
for (Cell cell : cells)
369
assert lib.cells.get(cell.getCellName()) == cell;
370
assert cell.cellGroup == this;
376
public String getName() {
377
return groupName != null ? groupName.getName() : null;
380
public EDatabase getDatabase() {
381
return lib.getDatabase();
385
* Method to check invariants in this CellGroup.
386
* @exception AssertionError if invariants are not valid
389
for (Cell cell : cells) {
390
assert lib.cells.get(cell.getCellName()) == cell;
391
assert cell.cellGroup == this;
371
392
assert cell.d.groupName.equals(groupName);
373
if (mainSchematic != null)
375
assert containsCell(mainSchematic);
376
assert mainSchematic.getNewestVersion() == mainSchematic;
380
* Method to set the main schematics Cell in ths CellGroup.
381
* The main schematic is the one that is shown when descending into an icon.
382
* Other schematic views may exist in the group, but they are "alternates".
394
if (mainSchematic != null) {
395
assert containsCell(mainSchematic);
396
assert mainSchematic.getNewestVersion() == mainSchematic;
401
* Method to set the main schematics Cell in ths CellGroup.
402
* The main schematic is the one that is shown when descending into an icon.
403
* Other schematic views may exist in the group, but they are "alternates".
383
404
* Only one schematic view should be in cell group.
384
405
* If many schematic views exists then main schematics is the newest version of first in alpahabetical order schematic cell.
386
private void setMainSchematics(boolean undo)
407
private void setMainSchematics(boolean undo) {
388
408
if (cells.isEmpty()) {
389
409
groupName = null;
390
410
mainSchematic = null;
393
// not set: see if it is obvious
413
// not set: see if it is obvious
394
414
List<CellName> cellNames = new ArrayList<CellName>();
395
415
// String bestName = null;
396
416
Cell mainSchematic = null;
397
for (Cell cell: cells) {
398
if (cell.isSchematic() && mainSchematic == null)
417
for (Cell cell : cells) {
418
if (cell.isSchematic() && mainSchematic == null) {
399
419
mainSchematic = cell;
400
421
cellNames.add(cell.getCellName());
402
423
groupName = Snapshot.makeCellGroupName(cellNames);
403
424
this.mainSchematic = mainSchematic;
404
for (Cell cell: cells) {
425
for (Cell cell : cells) {
406
427
assert cell.d.groupName.equals(groupName);
408
429
cell.setD(cell.d.withGroupName(groupName));
414
private class MaxSuffix { int v = 0; }
416
// -------------------------- private data ---------------------------------
418
/** Variable key for characteristic spacing for a cell. */ public static final Variable.Key CHARACTERISTIC_SPACING = Variable.newKey("FACET_characteristic_spacing");
419
/** Variable key for text cell contents. */ public static final Variable.Key CELL_TEXT_KEY = Variable.newKey("FACET_message");
420
/** Variable key for number of multipage pages. */ public static final Variable.Key MULTIPAGE_COUNT_KEY = Variable.newKey("CELL_page_count");
421
/** Variable key for font of text in textual cells. */ public static final Variable.Key TEXT_CELL_FONT_NAME = Variable.newKey("CELL_text_font");
422
/** Variable key for size of text in textual cells. */ public static final Variable.Key TEXT_CELL_FONT_SIZE = Variable.newKey("CELL_text_size");
435
private class MaxSuffix {
439
// -------------------------- private data ---------------------------------
440
/** Variable key for characteristic spacing for a cell. */
441
public static final Variable.Key CHARACTERISTIC_SPACING = Variable.newKey("FACET_characteristic_spacing");
442
/** Variable key for text cell contents. */
443
public static final Variable.Key CELL_TEXT_KEY = Variable.newKey("FACET_message");
444
/** Variable key for number of multipage pages. */
445
public static final Variable.Key MULTIPAGE_COUNT_KEY = Variable.newKey("CELL_page_count");
446
/** Variable key for font of text in textual cells. */
447
public static final Variable.Key TEXT_CELL_FONT_NAME = Variable.newKey("CELL_text_font");
448
/** Variable key for size of text in textual cells. */
449
public static final Variable.Key TEXT_CELL_FONT_SIZE = Variable.newKey("CELL_text_size");
424
450
private static final int[] NULL_INT_ARRAY = {};
425
private static final Export[] NULL_EXPORT_ARRAY = {};
427
/** set if instances should be expanded */ public static final int WANTNEXPAND = 02;
428
// /** set if cell is modified */ private static final int MODIFIED = 01000000;
429
/** set if everything in cell is locked */ public static final int NPLOCKED = 04000000;
430
/** set if instances in cell are locked */ public static final int NPILOCKED = 010000000;
431
/** set if cell is part of a "cell library" */ public static final int INCELLLIBRARY = 020000000;
432
/** set if cell is from a technology-library */ public static final int TECEDITCELL = 040000000;
433
/** set if cell is a multi-page schematic */ private static final int MULTIPAGE = 017600000000;
435
/** Length of base name for autonaming. */ private static final int ABBREVLEN = 8;
436
/** zero rectangle */ private static final Rectangle2D CENTERRECT = new Rectangle2D.Double(0, 0, 0, 0);
438
/** Bounds are correct */ private static final byte BOUNDS_CORRECT = 0;
439
/** Bounds are correct if all subcells have correct bounds. */ private static final byte BOUNDS_CORRECT_SUB = 1;
440
/** Bounds are correct if all geoms have correct bounds. */ private static final byte BOUNDS_CORRECT_GEOM = 2;
441
/** Bounds need to be recomputed. */ private static final byte BOUNDS_RECOMPUTE = 3;
443
/** Database to which this Library belongs. */ private final EDatabase database;
444
/** Persistent data of this Cell. */ private ImmutableCell d;
445
/** The CellGroup this Cell belongs to. */ private CellGroup cellGroup;
446
/** The library this Cell belongs to. */ private Library lib;
447
/** The technology of this Cell. */ private Technology tech;
448
/** The newest version of this Cell. */ Cell newestVersion;
449
/** An array of Exports on the Cell by chronological index. */ private Export[] chronExports = new Export[2];
450
/** A sorted array of Exports on the Cell. */ private Export[] exports = NULL_EXPORT_ARRAY;
451
/** Cell's topology. */ private final Topology topology = new Topology(this, false);
452
/** The Cell's essential-bounds. */ private final List<NodeInst> essenBounds = new ArrayList<NodeInst>();
453
/** Chronological list of NodeInsts in this Cell. */ private final List<NodeInst> chronNodes = new ArrayList<NodeInst>();
454
/** Set containing nodeIds of expanded cells. */ private final BitSet expandedNodes = new BitSet();
455
/** A list of NodeInsts in this Cell. */ private final List<NodeInst> nodes = new ArrayList<NodeInst>();
456
/** Counts of NodeInsts for each CellUsage. */ private int[] cellUsages = NULL_INT_ARRAY;
457
/** A map from canonic String to Integer maximal numeric suffix */private final Map<String,MaxSuffix> maxSuffix = new HashMap<String,MaxSuffix>();
458
/** The bounds of the Cell. */ private ERectangle cellBounds;
459
/** Whether the bounds need to be recomputed.
460
* BOUNDS_CORRECT - bounds are correct.
461
* BOUNDS_CORRECT_SUB - bounds are correct provided that bounds of subcells are correct.
462
* BOUNDS_CORRECT_GEOM - bounds are correct proveded that bounds of nodes and arcs are correct.
463
* BOUNDS_RECOMPUTE - bounds need to be recomputed. */ private byte boundsDirty = BOUNDS_RECOMPUTE;
464
/** The temporary integer value. */ private int tempInt;
465
/** Set if expanded status of subcell instances is modified. */ private boolean expandStatusModified;
466
/** Last backup of this Cell */ CellBackup backup;
467
/** True if cell together with contents matches cell backup. */ boolean cellBackupFresh;
468
/** True if cell contents matches cell backup. */ private boolean cellContentsFresh;
469
/** True if cell revision date is just set by lowLevelSetRevisionDate*/private boolean revisionDateFresh;
472
// ------------------ protected and private methods -----------------------
475
* This constructor should not be called.
476
* Use the factory "newInstance" to create a Cell.
478
Cell(EDatabase database, ImmutableCell d) {
451
private static final Export[] NULL_EXPORT_ARRAY = {};
452
/** set if instances should be expanded */
453
public static final int WANTNEXPAND = 02;
454
// /** set if cell is modified */ private static final int MODIFIED = 01000000;
455
/** set if everything in cell is locked */
456
public static final int NPLOCKED = 04000000;
457
/** set if instances in cell are locked */
458
public static final int NPILOCKED = 010000000;
459
/** set if cell is part of a "cell library" */
460
public static final int INCELLLIBRARY = 020000000;
461
/** set if cell is from a technology-library */
462
public static final int TECEDITCELL = 040000000;
463
/** set if cell is a multi-page schematic */
464
private static final int MULTIPAGE = 017600000000;
465
/** Length of base name for autonaming. */
466
private static final int ABBREVLEN = 8;
467
/** zero rectangle */
468
private static final Rectangle2D CENTERRECT = new Rectangle2D.Double(0, 0, 0, 0);
469
/** Database to which this Library belongs. */
470
private final EDatabase database;
471
/** Persistent data of this Cell. */
472
private ImmutableCell d;
473
/** The CellGroup this Cell belongs to. */
474
private CellGroup cellGroup;
475
/** The library this Cell belongs to. */
477
/** The technology of this Cell. */
478
private Technology tech;
479
/** The newest version of this Cell. */
481
/** An array of Exports on the Cell by chronological index. */
482
private Export[] chronExports = new Export[2];
483
/** A sorted array of Exports on the Cell. */
484
private Export[] exports = NULL_EXPORT_ARRAY;
485
/** Cell's topology. */
486
private Reference<Topology> topologyRef;
487
/** Cell's topology. */
488
private Topology strongTopology;
489
/** Set containing nodeIds of expanded cells. */
490
private final BitSet expandedNodes = new BitSet();
491
/** Counts of NodeInsts for each CellUsage. */
492
private int[] cellUsages = NULL_INT_ARRAY;
493
/** A map from canonic String to Integer maximal numeric suffix */
494
private final Map<String, MaxSuffix> maxSuffix = new HashMap<String, MaxSuffix>();
495
/** The temporary integer value. */
497
/** Set if expanded status of subcell instances is modified. */
498
private boolean expandStatusModified;
499
/** Last CellTree of this Cell */
501
/** True if cell together with subcells matches cell tree. */
502
boolean cellTreeFresh;
503
/** Last backup of this Cell */
505
/** True if cell together with contents matches cell backup. */
506
boolean cellBackupFresh;
507
/** True if cell contents matches cell backup. */
508
private boolean cellContentsFresh;
509
/** True if cell revision date is just set by lowLevelSetRevisionDate*/
510
private boolean revisionDateFresh;
511
/** A weak reference to NetCell object with Netlists */
512
private Reference<NetCell> netCellRef;
514
// ------------------ protected and private methods -----------------------
516
* This constructor should not be called.
517
* Use the factory "newInstance" to create a Cell.
519
Cell(EDatabase database, ImmutableCell d) {
479
520
this.database = database;
481
522
lib = database.getLib(d.getLibId());
482
523
assert lib != null;
483
if (d.techId != null)
524
if (d.techId != null) {
484
525
tech = database.getTech(d.techId);
527
if (!LAZY_TOPOLOGY || !Job.isThreadSafe()) {
528
strongTopology = new Topology(this, false);
530
setTopologyRef(strongTopology);
531
if (NetworkTool.isLazy()) {
487
private Object writeReplace() { return new CellKey(this); }
536
private Object writeReplace() {
537
return new CellKey(this);
489
540
private static class CellKey extends EObjectInputStream.Key<Cell> {
491
private CellKey(Cell cell) { super(cell); }
545
private CellKey(Cell cell) {
494
550
public void writeExternal(EObjectOutputStream out, Cell cell) throws IOException {
495
551
CellId cellId = cell.getId();
496
if (cell.getDatabase() != out.getDatabase() || !cell.isLinked())
552
if (cell.getDatabase() != out.getDatabase() || !cell.isLinked()) {
497
553
throw new NotSerializableException(cell + " not linked");
498
555
out.writeObject(cellId);
502
559
public Cell readExternal(EObjectInputStream in) throws IOException, ClassNotFoundException {
503
CellId cellId = (CellId)in.readObject();
560
CellId cellId = (CellId) in.readObject();
504
561
Cell cell = cellId.inDatabase(in.getDatabase());
506
563
throw new InvalidObjectException(cellId + " not linked");
511
/****************************** CREATE, DELETE ******************************/
514
* Factory method to create a new Cell.
515
* Also does auxiliary things to create the Cell, such as placing a cell-center if requested.
516
* @param lib the Library in which to place this cell.
517
* @param name the name of this cell.
518
* Cell names may not contain unprintable characters, spaces, tabs, a colon (:), semicolon (;) or curly braces ({}).
519
* However, the name can be fully qualified with version and view information.
520
* For example, "foo;2{sch}".
521
* @return the newly created cell (null on error).
523
public static Cell makeInstance(Library lib, String name)
525
Cell cell = newInstance(lib, name);
527
// add cell-center if requested
528
if (User.isPlaceCellCenter())
530
NodeProto cellCenterProto = Generic.tech().cellCenterNode;
531
NodeInst cellCenter = NodeInst.newInstance(cellCenterProto, new Point2D.Double(0, 0),
532
cellCenterProto.getDefWidth(), cellCenterProto.getDefHeight(), cell);
533
if (cellCenter != null)
569
/****************************** CREATE, DELETE ******************************/
571
* Factory method to create a new Cell.
572
* Also does auxiliary things to create the Cell, such as placing a cell-center if requested.
573
* @param lib the Library in which to place this cell.
574
* @param name the name of this cell.
575
* Cell names may not contain unprintable characters, spaces, tabs, a colon (:), semicolon (;) or curly braces ({}).
576
* However, the name can be fully qualified with version and view information.
577
* For example, "foo;2{sch}".
578
* @return the newly created cell (null on error).
580
public static Cell makeInstance(Library lib, String name) {
581
Cell cell = newInstance(lib, name);
583
// add cell-center if requested
584
if (User.isPlaceCellCenter()) {
585
NodeProto cellCenterProto = Generic.tech().cellCenterNode;
586
NodeInst cellCenter = NodeInst.newInstance(cellCenterProto, new Point2D.Double(0, 0),
587
cellCenterProto.getDefWidth(), cellCenterProto.getDefHeight(), cell);
588
if (cellCenter != null) {
535
589
cellCenter.setVisInside();
536
cellCenter.setHardSelect();
590
cellCenter.setHardSelect();
543
* Factory method to create a new Cell.
544
* @param lib the Library in which to place this cell.
545
* @param name the name of this cell.
546
* Cell names may not contain unprintable characters, spaces, tabs, a colon (:), semicolon (;) or curly braces ({}).
547
* However, the name can be fully qualified with version and view information.
548
* For example, "foo;2{sch}".
549
* @return the newly created cell (null on error).
551
public static Cell newInstance(Library lib, String name)
597
* Factory method to create a new Cell.
598
* @param lib the Library in which to place this cell.
599
* @param name the name of this cell.
600
* Cell names may not contain unprintable characters, spaces, tabs, a colon (:), semicolon (;) or curly braces ({}).
601
* However, the name can be fully qualified with version and view information.
602
* For example, "foo;2{sch}".
603
* @return the newly created cell (null on error).
605
public static Cell newInstance(Library lib, String name) {
554
607
EDatabase database = lib.getDatabase();
556
CellName cellName = CellName.parseName(name);
557
if (cellName == null) return null;
609
CellName cellName = CellName.parseName(name);
610
if (cellName == null) {
559
// check name for legal characters
560
String protoName = cellName.getName();
561
String original = null;
562
for(int i=0; i<protoName.length(); i++)
564
char chr = protoName.charAt(i);
565
if (Character.isWhitespace(chr) || chr == ':' || chr == ';' || chr == '{' || chr == '}')
567
if (original == null) original = protoName;
568
protoName = protoName.substring(0, i) + '_' + protoName.substring(i+1);
571
if (original != null)
573
System.out.println("Cell name changed from '" + original + "' to '" + protoName + "'");
574
cellName = CellName.newName(protoName, cellName.getView(), cellName.getVersion());
614
// check name for legal characters
615
String protoName = cellName.getName();
616
String original = null;
617
for (int i = 0; i < protoName.length(); i++) {
618
char chr = protoName.charAt(i);
619
if (Character.isWhitespace(chr) || chr == ':' || chr == ';' || chr == '{' || chr == '}') {
620
if (original == null) {
621
original = protoName;
623
protoName = protoName.substring(0, i) + '_' + protoName.substring(i + 1);
626
if (original != null) {
627
System.out.println("Cell name changed from '" + original + "' to '" + protoName + "'");
628
cellName = CellName.newName(protoName, cellName.getView(), cellName.getVersion());
576
630
cellName = makeUnique(lib, cellName);
578
632
Date creationDate = new Date();
579
633
CellId cellId = lib.getId().newCellId(cellName);
580
Cell cell = new Cell(lib.getDatabase(), ImmutableCell.newInstance(cellId, creationDate.getTime()));
634
Cell cell = new Cell(lib.getDatabase(), ImmutableCell.newInstance(cellId, creationDate.getTime()));
583
637
database.addCell(cell);
584
// add ourselves to the library
638
// add ourselves to the library
585
639
lib.addCell(cell);
587
// add ourselves to cell group
588
cell.lowLevelLinkCellName();
641
// add ourselves to cell group
642
cell.lowLevelLinkCellName();
590
// handle change control, constraint, and broadcast
644
// handle change control, constraint, and broadcast
591
645
database.unfreshSnapshot();
592
Constraints.getCurrent().newObject(cell);
596
private void lowLevelLinkCellName()
598
// determine the cell group
599
for (Iterator<Cell> it = getViewsTail(); it.hasNext(); )
602
if (c.getName().equals(getName()))
603
cellGroup = c.cellGroup;
605
// still none: make a new one
606
if (cellGroup == null) cellGroup = new CellGroup(lib);
608
// add ourselves to cell group
613
* Method to remove this node from all lists.
619
System.out.println("Cell already killed");
624
// remove ourselves from the cellGroup.
625
lib.removeCell(this);
626
cellGroup.remove(this);
646
Constraints.getCurrent().newObject(cell);
650
private void lowLevelLinkCellName() {
651
// determine the cell group
652
for (Iterator<Cell> it = getViewsTail(); it.hasNext();) {
654
if (c.getName().equals(getName())) {
655
cellGroup = c.cellGroup;
658
// still none: make a new one
659
if (cellGroup == null) {
660
cellGroup = new CellGroup(lib);
663
// add ourselves to cell group
668
* Method to remove this node from all lists.
672
System.out.println("Cell already killed");
677
List<NodeInst> nodesToKill = new ArrayList<NodeInst>();
678
for (Iterator<NodeInst> it = getInstancesOf(); it.hasNext();) {
679
nodesToKill.add(it.next());
681
for (NodeInst ni : nodesToKill) {
684
assert !getUsagesOf().hasNext();
686
// remove ourselves from the cellGroup.
687
lib.removeCell(this);
688
cellGroup.remove(this);
627
689
database.removeCell(getId());
629
// handle change control, constraint, and broadcast
691
// handle change control, constraint, and broadcast
630
692
database.unfreshSnapshot();
631
693
// lib.setChanged();
632
Constraints.getCurrent().killObject(this);
636
* Method to copy a Cell to any Library.
637
* @param fromCell the Cell to copy.
638
* @param toLib the Library to copy it to.
639
* @param toName the name of the Cell in the destination Library.
640
* If the destination library is the same as the original Cell's library and the new name is the same
641
* as the old name, a new version is made.
642
* @param useExisting true to use existing subcell instances if they exist in the destination Library.
643
* @return the new Cell in the destination Library.
645
public static Cell copyNodeProto(Cell fromCell, Library toLib, String toName, boolean useExisting)
647
return copyNodeProto(fromCell, toLib, toName, useExisting, null);
651
* Method to copy a Cell to any Library.
652
* @param fromCell the Cell to copy.
653
* @param toLib the Library to copy it to.
654
* @param toName the name of the Cell in the destination Library.
655
* If the destination library is the same as the original Cell's library and the new name is the same
656
* as the old name, a new version is made.
657
* @param useExisting true to use existing subcell instances if they exist in the destination Library.
658
* @param cellNamesToUse a map that disambiguates cell names when they clash in different original libraries.
659
* The main key is an old cell name, and the value for that key is a map of library names to new cell names.
660
* So, for example, if libraries "A" and "B" both have a cell called "X", then existing.get("X").get("A") is "X" but
661
* existing.get(X").get("B") is "X_1" which disambiguates the cell names in the destination library. The map may be null.
662
* @return the new Cell in the destination Library.
664
public static Cell copyNodeProto(Cell fromCell, Library toLib, String toName, boolean useExisting,
665
Map<String,Map<String,String>> cellNamesToUse)
667
// check for validity
668
if (fromCell == null) return null;
669
if (toLib == null) return null;
671
// make sure name of new cell is valid
672
for(int i=0; i<toName.length(); i++)
674
char ch = toName.charAt(i);
675
if (ch <= ' ' || ch == ':' || ch >= 0177)
694
Constraints.getCurrent().killObject(this);
698
* Method to copy a Cell to any Library.
699
* @param fromCell the Cell to copy.
700
* @param toLib the Library to copy it to.
701
* @param toName the name of the Cell in the destination Library.
702
* If the destination library is the same as the original Cell's library and the new name is the same
703
* as the old name, a new version is made.
704
* @param useExisting true to use existing subcell instances if they exist in the destination Library.
705
* @return the new Cell in the destination Library.
707
public static Cell copyNodeProto(Cell fromCell, Library toLib, String toName, boolean useExisting) {
708
return copyNodeProto(fromCell, toLib, toName, useExisting, null);
712
* Method to copy a Cell to any Library.
713
* @param fromCell the Cell to copy.
714
* @param toLib the Library to copy it to.
715
* @param toName the name of the Cell in the destination Library.
716
* If the destination library is the same as the original Cell's library and the new name is the same
717
* as the old name, a new version is made.
718
* @param useExisting true to use existing subcell instances if they exist in the destination Library.
719
* @param cellNamesToUse a map that disambiguates cell names when they clash in different original libraries.
720
* The main key is an old cell name, and the value for that key is a map of library names to new cell names.
721
* So, for example, if libraries "A" and "B" both have a cell called "X", then existing.get("X").get("A") is "X" but
722
* existing.get(X").get("B") is "X_1" which disambiguates the cell names in the destination library. The map may be null.
723
* @return the new Cell in the destination Library.
725
public static Cell copyNodeProto(Cell fromCell, Library toLib, String toName, boolean useExisting,
726
Map<String, Map<String, String>> cellNamesToUse) {
727
// check for validity
728
if (fromCell == null) {
735
// make sure name of new cell is valid
736
for (int i = 0; i < toName.length(); i++) {
737
char ch = toName.charAt(i);
738
if (ch <= ' ' || ch == ':' || ch >= 0177) {
677
739
System.out.println("invalid name of new cell");
682
// determine whether this copy is to a different library
683
Library destLib = toLib;
684
if (toLib == fromCell.getLibrary()) destLib = null;
686
// mark the proper prototype to use for each node
687
Map<NodeInst,NodeProto> nodePrototypes = new HashMap<NodeInst,NodeProto>();
689
// if doing a cross-library copy and can use existing ones from new library, do it
692
// scan all subcells to see if they are found in the new library
693
for(Iterator<NodeInst> it = fromCell.getNodes(); it.hasNext(); )
695
NodeInst ni = it.next();
696
if (!ni.isCellInstance()) continue;
697
Cell niProto = (Cell)ni.getProto();
699
boolean maySubstitute = useExisting;
702
// force substitution for documentation icons
703
if (niProto.isIcon())
705
if (niProto.isIconOf(fromCell)) maySubstitute = true;
708
if (!maySubstitute) continue;
710
// switch cell names if disambiguating
711
String oldCellName = niProto.getName();
712
if (cellNamesToUse != null)
714
Map<String,String> libToNameMap = cellNamesToUse.get(oldCellName);
715
if (libToNameMap != null)
717
String newCellName = libToNameMap.get(niProto.getLibrary().getName());
718
if (newCellName != null) oldCellName = newCellName;
722
// search for cell with same name and view in new library
724
for(Iterator<Cell> cIt = toLib.getCells(); cIt.hasNext(); )
727
if (lnt.getName().equals(oldCellName) &&
728
// if (lnt.getName().equalsIgnoreCase(oldCellName) &&
729
lnt.getView() == niProto.getView()) break;
732
if (lnt == null) continue;
734
// make sure all used ports can be found on the uncopied cell
735
boolean validPorts = true;
736
for(Iterator<PortInst> pIt = ni.getPortInsts(); pIt.hasNext(); )
738
PortInst pi = pIt.next();
739
PortProto pp = pi.getPortProto();
740
PortProto ppt = lnt.findPortProto(pp.getName());
744
// determine whether this copy is to a different library
745
Library destLib = toLib;
746
if (toLib == fromCell.getLibrary()) {
750
// mark the proper prototype to use for each node
751
Map<NodeInst, NodeProto> nodePrototypes = new HashMap<NodeInst, NodeProto>();
753
// if doing a cross-library copy and can use existing ones from new library, do it
754
if (destLib != null) {
755
// scan all subcells to see if they are found in the new library
756
for (Iterator<NodeInst> it = fromCell.getNodes(); it.hasNext();) {
757
NodeInst ni = it.next();
758
if (!ni.isCellInstance()) {
761
Cell niProto = (Cell) ni.getProto();
763
boolean maySubstitute = useExisting;
764
if (!maySubstitute) {
765
// force substitution for documentation icons
766
if (niProto.isIcon()) {
767
if (niProto.isIconOf(fromCell)) {
768
maySubstitute = true;
772
if (!maySubstitute) {
776
// switch cell names if disambiguating
777
String oldCellName = niProto.getName();
778
if (cellNamesToUse != null) {
779
Map<String, String> libToNameMap = cellNamesToUse.get(oldCellName);
780
if (libToNameMap != null) {
781
String newCellName = libToNameMap.get(niProto.getLibrary().getName());
782
if (newCellName != null) {
783
oldCellName = newCellName;
788
// search for cell with same name and view in new library
790
for (Iterator<Cell> cIt = toLib.getCells(); cIt.hasNext();) {
792
if (lnt.getName().equals(oldCellName)
793
&& // if (lnt.getName().equalsIgnoreCase(oldCellName) &&
794
lnt.getView() == niProto.getView()) {
803
// make sure all used ports can be found on the uncopied cell
804
boolean validPorts = true;
805
for (Iterator<PortInst> pIt = ni.getPortInsts(); pIt.hasNext();) {
806
PortInst pi = pIt.next();
807
PortProto pp = pi.getPortProto();
808
PortProto ppt = lnt.findPortProto(pp.getName());
741
809
// if (ppt != null)
743
811
// // the connections must match, too
744
812
// if (pp->connects != ppt->connects) ppt = null;
748
System.out.println("Cannot use subcell " + lnt.noLibDescribe() + " in " + destLib +
749
": exports don't match");
754
if (!validPorts) continue;
756
// match found: use the prototype from the destination library
757
nodePrototypes.put(ni, lnt);
760
return copyNodeProtoUsingMapping(fromCell, toLib, toName, nodePrototypes);
764
* Method to copy a Cell to any Library, using a preset mapping of node prototypes.
765
* @param fromCell the Cell to copy.
766
* @param toLib the Library to copy it to.
767
* If the destination library is the same as the original Cell's library, a new version is made.
768
* @param toName the name of the Cell in the destination Library.
769
* @param nodePrototypes a HashMap from NodeInsts in the source Cell to proper NodeProtos to use in the new Cell.
770
* @return the new Cell in the destination Library.
772
public static Cell copyNodeProtoUsingMapping(Cell fromCell, Library toLib, String toName,
773
Map<NodeInst,NodeProto> nodePrototypes)
775
// create the nodeproto
776
String cellName = toName;
777
if (toName.indexOf('{') < 0 && fromCell.getView() != View.UNKNOWN)
779
cellName = toName + fromCell.getView().getAbbreviationExtension();
781
Cell newCell = Cell.newInstance(toLib, cellName);
782
if (newCell == null) return(null);
783
newCell.lowLevelSetUserbits(fromCell.lowLevelGetUserbits());
786
Map<NodeInst,NodeInst> newNodes = new HashMap<NodeInst,NodeInst>();
787
for(Iterator<NodeInst> it = fromCell.getNodes(); it.hasNext(); )
789
// create the new nodeinst
790
NodeInst ni = it.next();
791
NodeProto lnt = nodePrototypes.get(ni);
792
if (lnt == null) lnt = ni.getProto();
793
double scaleX = ni.getXSize(); //if (ni.isXMirrored()) scaleX = -scaleX;
794
double scaleY = ni.getYSize(); //if (ni.isYMirrored()) scaleY = -scaleY;
795
NodeInst toNi = NodeInst.newInstance(lnt, new Point2D.Double(ni.getAnchorCenterX(), ni.getAnchorCenterY()),
796
scaleX, scaleY, newCell, ni.getOrient(), ni.getName());
797
if (toNi == null) return null;
799
// save the new nodeinst address in the old nodeinst
800
newNodes.put(ni, toNi);
802
// copy miscellaneous information
803
toNi.copyTextDescriptorFrom(ni, NodeInst.NODE_PROTO);
804
toNi.copyTextDescriptorFrom(ni, NodeInst.NODE_NAME);
805
toNi.copyStateBits(ni);
808
// now copy the variables on the nodes
809
for(Iterator<NodeInst> it = fromCell.getNodes(); it.hasNext(); )
811
NodeInst ni = it.next();
812
NodeInst toNi = newNodes.get(ni);
813
toNi.copyVarsFrom(ni);
815
System.out.println("Cannot use subcell " + lnt.noLibDescribe() + " in " + destLib
816
+ ": exports don't match");
825
// match found: use the prototype from the destination library
826
nodePrototypes.put(ni, lnt);
829
return copyNodeProtoUsingMapping(fromCell, toLib, toName, nodePrototypes);
833
* Method to copy a Cell to any Library, using a preset mapping of node prototypes.
834
* @param fromCell the Cell to copy.
835
* @param toLib the Library to copy it to.
836
* If the destination library is the same as the original Cell's library, a new version is made.
837
* @param toName the name of the Cell in the destination Library.
838
* @param nodePrototypes a HashMap from NodeInsts in the source Cell to proper NodeProtos to use in the new Cell.
839
* @return the new Cell in the destination Library.
841
public static Cell copyNodeProtoUsingMapping(Cell fromCell, Library toLib, String toName,
842
Map<NodeInst, NodeProto> nodePrototypes) {
843
// create the nodeproto
844
String cellName = toName;
845
if (toName.indexOf('{') < 0 && fromCell.getView() != View.UNKNOWN) {
846
cellName = toName + fromCell.getView().getAbbreviationExtension();
848
Cell newCell = Cell.newInstance(toLib, cellName);
849
if (newCell == null) {
852
newCell.lowLevelSetUserbits(fromCell.lowLevelGetUserbits());
855
Map<NodeInst, NodeInst> newNodes = new HashMap<NodeInst, NodeInst>();
856
for (Iterator<NodeInst> it = fromCell.getNodes(); it.hasNext();) {
857
// create the new nodeinst
858
NodeInst ni = it.next();
859
NodeProto lnt = nodePrototypes.get(ni);
863
double scaleX = ni.getXSize(); //if (ni.isXMirrored()) scaleX = -scaleX;
864
double scaleY = ni.getYSize(); //if (ni.isYMirrored()) scaleY = -scaleY;
865
NodeInst toNi = NodeInst.newInstance(lnt, new Point2D.Double(ni.getAnchorCenterX(), ni.getAnchorCenterY()),
866
scaleX, scaleY, newCell, ni.getOrient(), ni.getName());
871
// save the new nodeinst address in the old nodeinst
872
newNodes.put(ni, toNi);
874
// copy miscellaneous information
875
toNi.copyTextDescriptorFrom(ni, NodeInst.NODE_PROTO);
876
toNi.copyTextDescriptorFrom(ni, NodeInst.NODE_NAME);
877
toNi.copyStateBitsAndExpandedFlag(ni);
880
// now copy the variables on the nodes
881
for (Iterator<NodeInst> it = fromCell.getNodes(); it.hasNext();) {
882
NodeInst ni = it.next();
883
NodeInst toNi = newNodes.get(ni);
884
toNi.copyVarsFrom(ni);
815
886
// if this is an icon, and this nodeinst is the box with the name of the cell on it,
816
887
// then change the name from the old to the new
817
888
if (newCell.isIcon()) {
818
889
String name = toNi.getVarValue(Schematics.SCHEM_FUNCTION, String.class);
819
if (fromCell.getName().equals(name))
890
if (fromCell.getName().equals(name)) {
820
891
toNi.updateVar(Schematics.SCHEM_FUNCTION, newCell.getName());
825
for(Iterator<ArcInst> it = fromCell.getArcs(); it.hasNext(); )
827
ArcInst ai = it.next();
829
// find the nodeinst and portinst connections for this arcinst
830
PortInst [] opi = new PortInst[2];
831
Point2D [] oLoc = new Point2D[2];
832
for(int i=0; i<2; i++)
835
NodeInst ono = newNodes.get(ai.getPortInst(i).getNodeInst());
836
PortProto pp = ai.getPortInst(i).getPortProto();
837
if (!ono.isCellInstance())
839
// primitives associate ports directly
840
opi[i] = ono.findPortInstFromProto(pp);
843
// cells associate ports by name
844
PortProto ppt = ono.getProto().findPortProto(pp.getName());
845
if (ppt != null) opi[i] = ono.findPortInstFromProto(ppt);
848
System.out.println("Error: no port for " + ai.getProto() +
849
" arc on " + ono.getProto());
850
oLoc[i] = ai.getLocation(i);
851
Poly poly = opi[i].getPoly();
852
if (!poly.isInside(oLoc[i])) oLoc[i] = poly.getCenter();
854
if (opi[0] == null || opi[1] == null) return null;
856
// create the arcinst
857
ArcInst toAi = ArcInst.newInstanceBase(ai.getProto(), ai.getLambdaBaseWidth(), opi[ArcInst.HEADEND], opi[ArcInst.TAILEND],
858
oLoc[ArcInst.HEADEND], oLoc[ArcInst.TAILEND], ai.getName(), ai.getAngle());
859
if (toAi == null) return null;
861
// copy arcinst information
862
toAi.copyPropertiesFrom(ai);
866
for(Iterator<Export> it = fromCell.getExports(); it.hasNext(); )
868
Export pp = it.next();
870
// match sub-portproto in old nodeinst to sub-portproto in new one
871
NodeInst ni = newNodes.get(pp.getOriginalPort().getNodeInst());
872
PortInst pi = ni.findPortInst(pp.getOriginalPort().getPortProto().getName());
875
System.out.println("Error: no port on " + pp.getOriginalPort().getNodeInst().getProto());
879
// create the nodeinst portinst
880
Export ppt = Export.newInstance(newCell, pi, pp.getName());
881
if (ppt == null) return null;
883
// copy portproto variables
884
ppt.copyVarsFrom(pp);
886
// copy miscellaneous information
887
ppt.copyStateBits(pp);
888
ppt.copyTextDescriptorFrom(pp, Export.EXPORT_NAME);
891
// copy cell variables
892
for (Iterator<Variable> it = fromCell.getParametersAndVariables(); it.hasNext(); ) {
897
for (Iterator<ArcInst> it = fromCell.getArcs(); it.hasNext();) {
898
ArcInst ai = it.next();
900
// find the nodeinst and portinst connections for this arcinst
901
PortInst[] opi = new PortInst[2];
902
Point2D[] oLoc = new Point2D[2];
903
for (int i = 0; i < 2; i++) {
905
NodeInst ono = newNodes.get(ai.getPortInst(i).getNodeInst());
906
PortProto pp = ai.getPortInst(i).getPortProto();
907
if (!ono.isCellInstance()) {
908
// primitives associate ports directly
909
opi[i] = ono.findPortInstFromProto(pp);
911
// cells associate ports by name
912
PortProto ppt = ono.getProto().findPortProto(pp.getName());
914
opi[i] = ono.findPortInstFromProto(ppt);
917
if (opi[i] == null) {
918
System.out.println("Error: no port for " + ai.getProto()
919
+ " arc on " + ono.getProto());
921
oLoc[i] = ai.getLocation(i);
922
Poly poly = opi[i].getPoly();
923
if (!poly.isInside(oLoc[i])) {
924
oLoc[i] = poly.getCenter();
927
if (opi[0] == null || opi[1] == null) {
931
// create the arcinst
932
ArcInst toAi = ArcInst.newInstanceBase(ai.getProto(), ai.getLambdaBaseWidth(), opi[ArcInst.HEADEND], opi[ArcInst.TAILEND],
933
oLoc[ArcInst.HEADEND], oLoc[ArcInst.TAILEND], ai.getName(), ai.getAngle());
938
// copy arcinst information
939
toAi.copyPropertiesFrom(ai);
943
for (Iterator<Export> it = fromCell.getExports(); it.hasNext();) {
944
Export pp = it.next();
946
// match sub-portproto in old nodeinst to sub-portproto in new one
947
NodeInst ni = newNodes.get(pp.getOriginalPort().getNodeInst());
948
PortInst pi = ni.findPortInst(pp.getOriginalPort().getPortProto().getName());
950
System.out.println("Error: no port on " + pp.getOriginalPort().getNodeInst().getProto());
954
// create the nodeinst portinst
955
Export ppt = Export.newInstance(newCell, pi, pp.getName());
960
// copy portproto variables
961
ppt.copyVarsFrom(pp);
963
// copy miscellaneous information
964
ppt.copyStateBits(pp);
965
ppt.copyTextDescriptorFrom(pp, Export.EXPORT_NAME);
968
// copy cell variables
969
for (Iterator<Variable> it = fromCell.getParametersAndVariables(); it.hasNext();) {
893
970
Variable fromVar = it.next();
894
971
if (newCell.isParam(fromVar.getKey())) {
895
972
newCell.setTextDescriptor(fromVar.getKey(), fromVar.getTextDescriptor());
1304
1438
assert exportCount == exports.length;
1306
if (newBackup != null) {
1309
backup = backup.withTechPool(getTechPool());
1442
cellTreeFresh = true;
1311
1443
cellBackupFresh = true;
1312
1444
cellContentsFresh = true;
1445
if (LAZY_TOPOLOGY && Job.isThreadSafe()) {
1446
strongTopology = null;
1313
1448
revisionDateFresh = true;
1316
boundsDirty = BOUNDS_RECOMPUTE;
1317
if (newBackup != null) {
1318
ERectangle newBounds = computeBounds();
1319
assert newBounds == cellBounds;
1321
cellBounds = computeBounds();
1323
boundsDirty = BOUNDS_CORRECT;
1324
topology.rebuildRTree();
1325
assert boundsDirty == BOUNDS_CORRECT;
1328
private void updateSubCells(BitSet exportsModified, BitSet boundsModified) {
1331
if (boundsModified != null)
1332
boundsDirty = BOUNDS_RECOMPUTE;
1333
for (int i = 0; i < nodes.size(); i++) {
1334
NodeInst ni = nodes.get(i);
1335
if (!ni.isCellInstance()) continue;
1336
int subCellIndex = ((Cell)ni.getProto()).getCellIndex();
1337
if (exportsModified != null && exportsModified.get(subCellIndex)) {
1338
ni.updatePortInsts(false);
1340
if (boundsModified != null && boundsModified.get(subCellIndex))
1343
if (boundsModified != null) {
1344
assert boundsDirty == BOUNDS_RECOMPUTE;
1345
ERectangle newBounds = computeBounds();
1346
assert newBounds == cellBounds;
1347
boundsDirty = BOUNDS_CORRECT;
1349
assert boundsDirty == BOUNDS_CORRECT;
1350
topology.rebuildRTree();
1351
assert boundsDirty == BOUNDS_CORRECT;
1354
/****************************** GRAPHICS ******************************/
1357
* Method to get the width of this Cell.
1358
* @return the width of this Cell.
1360
public double getDefWidth() { return getBounds().getWidth(); }
1363
* Method to the height of this Cell.
1364
* @return the height of this Cell.
1366
public double getDefHeight() { return getBounds().getHeight(); }
1369
* Method to get the size offset of this Cell.
1370
* @return the size offset of this Cell. It is always zero for cells.
1372
public SizeOffset getProtoSizeOffset() { return SizeOffset.ZERO_OFFSET; }
1375
* Method to get the characteristic spacing for this Cell.
1376
* The characteristic spacing is used by the Array command to space these cells sensibly.
1377
* @return a dimension that is the characteristic spacing for this cell.
1378
* Returns null if there is no spacing defined.
1380
// public Dimension2D getCharacteristicSpacing()
1382
// Variable var = getVar(CHARACTERISTIC_SPACING);
1385
// Object obj = var.getObject();
1386
// if (obj instanceof Integer[])
1388
// Integer [] iSpac = (Integer [])obj;
1389
// Dimension2D spacing = new Dimension2D.Double(iSpac[0].intValue(), iSpac[1].intValue());
1391
// } else if (obj instanceof Double[])
1393
// Double [] dSpac = (Double [])obj;
1394
// Dimension2D spacing = new Dimension2D.Double(dSpac[0].doubleValue(), dSpac[1].doubleValue());
1402
* Method to set the characteristic spacing for this Cell.
1403
* The characteristic spacing is used by the Array command to space these cells sensibly.
1404
* @param x the characteristic width.
1405
* @param y the characteristic height.
1407
// public void setCharacteristicSpacing(double x, double y)
1409
// Double [] newVals = new Double[2];
1410
// newVals[0] = new Double(x);
1411
// newVals[1] = new Double(y);
1412
// newVar(CHARACTERISTIC_SPACING, newVals);
1416
* Method to indicate that the bounds of this Cell are incorrect because
1417
* a node or arc has been created, deleted, or modified.
1419
public void setDirty() { setDirty(BOUNDS_RECOMPUTE); }
1422
* Method to indicate that the bounds of this Cell are incorrect because
1423
* a node or arc may have been modified.
1425
public void setGeomDirty() { setDirty(BOUNDS_CORRECT_GEOM); }
1428
* Debug method to check that bound dirty flag is clear
1430
void checkBoundsCorrect() {
1431
assert boundsDirty == BOUNDS_CORRECT;
1432
for (NodeInst ni: nodes) {
1433
if (ni.isCellInstance()) {
1434
Cell subCell = (Cell)ni.getProto();
1435
assert subCell.boundsDirty == BOUNDS_CORRECT;
1441
* Method to indicate that the bounds of this Cell are incorrect because
1442
* a node or arc has been created, deleted, or modified.
1444
private void setDirty(byte boundsLevel)
1447
if (boundsDirty == BOUNDS_CORRECT) {
1448
boundsDirty = boundsLevel;
1449
for (Iterator<CellUsage> it = getUsagesOf(); it.hasNext(); ) {
1450
CellUsage u = it.next();
1451
u.getParent(database).setDirty(BOUNDS_CORRECT_SUB);
1453
} else if (boundsDirty < boundsLevel)
1454
boundsDirty = boundsLevel;
1458
* Method to return an interator over all RTBounds objects in a given area of this Cell.
1459
* @param bounds the specified area to search.
1460
* @return an iterator over all of the RTBounds objects in that area.
1462
public Iterator<RTBounds> searchIterator(Rectangle2D bounds) { return searchIterator(bounds, true); }
1465
* Method to return an interator over all RTBounds objects in a given area of this Cell that allows
1451
/****************************** GRAPHICS ******************************/
1453
* Method to get the width of this Cell.
1454
* @return the width of this Cell.
1456
public double getDefWidth() {
1457
return getBounds().getWidth();
1461
* Method to the height of this Cell.
1462
* @return the height of this Cell.
1464
public double getDefHeight() {
1465
return getBounds().getHeight();
1469
* Method to get the size offset of this Cell.
1470
* @return the size offset of this Cell. It is always zero for cells.
1472
public SizeOffset getProtoSizeOffset() {
1473
return SizeOffset.ZERO_OFFSET;
1477
* Method to return an interator over all RTBounds objects in a given area of this Cell.
1478
* @param bounds the specified area to search.
1479
* @return an iterator over all of the RTBounds objects in that area.
1481
public Iterator<RTBounds> searchIterator(Rectangle2D bounds) {
1482
return searchIterator(bounds, true);
1486
* Method to return an interator over all RTBounds objects in a given area of this Cell that allows
1466
1487
* to ignore elements touching the area.
1467
* @param bounds the specified area to search.
1488
* @param bounds the specified area to search.
1468
1489
* @param includeEdges true if RTBounds objects along edges are considered in.
1469
* @return an iterator over all of the RTBounds objects in that area.
1490
* @return an iterator over all of the RTBounds objects in that area.
1471
1492
public Iterator<RTBounds> searchIterator(Rectangle2D bounds, boolean includeEdges) {
1472
return topology.searchIterator(bounds, includeEdges);
1476
* Method to return the bounds of this Cell.
1477
* @return an ERectangle with the bounds of this cell's contents
1479
public ERectangle getBounds()
1481
if (boundsDirty == BOUNDS_CORRECT || !database.canComputeBounds())
1485
if (boundsDirty == BOUNDS_CORRECT_SUB) {
1486
boundsDirty = BOUNDS_CORRECT;
1487
// Recalculate bounds of subcells.
1488
for (Iterator<CellUsage> it = getUsagesIn(); it.hasNext(); ) {
1489
CellUsage u = it.next();
1490
u.getProto(database).getBounds();
1492
if (boundsDirty == BOUNDS_CORRECT)
1495
if (boundsDirty == BOUNDS_CORRECT_GEOM) {
1496
boundsDirty = BOUNDS_CORRECT;
1497
for (NodeInst ni: nodes)
1499
for (Iterator<ArcInst> it = topology.getArcs(); it.hasNext(); )
1500
it.next().getBounds();
1501
if (boundsDirty == BOUNDS_CORRECT)
1507
assert boundsDirty != BOUNDS_CORRECT;
1508
ERectangle newBounds = computeBounds();
1509
if (newBounds != cellBounds) {
1510
cellBounds = newBounds;
1511
for (Iterator<NodeInst> it = getInstancesOf(); it.hasNext(); ) {
1512
NodeInst ni = it.next();
1513
// Fake modify to recalcualte bounds and RTree
1517
boundsDirty = BOUNDS_CORRECT;
1521
ERectangle computeBounds() {
1522
double cellLowX, cellHighX, cellLowY, cellHighY;
1523
boolean boundsEmpty = true;
1524
cellLowX = cellHighX = cellLowY = cellHighY = 0;
1526
// Ensure that all subcells have correct bounds
1527
for (Iterator<CellUsage> it = getUsagesIn(); it.hasNext(); ) {
1528
CellUsage u = it.next();
1529
u.getProto(database).getBounds();
1532
for(int i = 0; i < nodes.size(); i++ ) {
1533
NodeInst ni = nodes.get(i);
1534
NodeProto np = ni.getProto();
1535
Rectangle2D bounds = ni.getBounds();
1537
// special case: do not include "cell center" primitives from Generic
1538
if (np == Generic.tech().cellCenterNode) continue;
1540
// special case for invisible pins: do not include if inheritable or interior-only
1541
if (np == Generic.tech().invisiblePinNode) {
1542
boolean found = false;
1543
for(Iterator<Variable> it = ni.getVariables(); it.hasNext(); ) {
1544
Variable var = it.next();
1545
if (var.isDisplay()) {
1546
TextDescriptor td = var.getTextDescriptor();
1547
if (td.isInterior() || td.isInherit()) { found = true; break; }
1550
if (found) continue;
1553
double lowx = bounds.getMinX();
1554
double highx = bounds.getMaxX();
1555
double lowy = bounds.getMinY();
1556
double highy = bounds.getMaxY();
1558
boundsEmpty = false;
1559
cellLowX = lowx; cellHighX = highx;
1560
cellLowY = lowy; cellHighY = highy;
1562
if (lowx < cellLowX) cellLowX = lowx;
1563
if (highx > cellHighX) cellHighX = highx;
1564
if (lowy < cellLowY) cellLowY = lowy;
1565
if (highy > cellHighY) cellHighY = highy;
1568
long gridMinX = DBMath.lambdaToGrid(cellLowX);
1569
long gridMinY = DBMath.lambdaToGrid(cellLowY);
1570
long gridMaxX = DBMath.lambdaToGrid(cellHighX);
1571
long gridMaxY = DBMath.lambdaToGrid(cellHighY);
1573
topology.computeArcBounds();
1574
ERectangle primitiveBounds = backup().getPrimitiveBounds();
1575
if (primitiveBounds != null) {
1576
assert !boundsEmpty;
1577
gridMinX = Math.min(gridMinX, primitiveBounds.getGridMinX());
1578
gridMaxX = Math.max(gridMaxX, primitiveBounds.getGridMaxX());
1579
gridMinY = Math.min(gridMinY, primitiveBounds.getGridMinY());
1580
gridMaxY = Math.max(gridMaxY, primitiveBounds.getGridMaxY());
1582
if (cellBounds != null && gridMinX == cellBounds.getGridMinX() && gridMinY == cellBounds.getGridMinY() &&
1583
gridMaxX == cellBounds.getGridMaxX() && gridMaxY == cellBounds.getGridMaxY())
1585
return ERectangle.fromGrid(gridMinX, gridMinY, gridMaxX - gridMinX, gridMaxY - gridMinY);
1589
* Method to compute the "essential bounds" of this Cell.
1590
* It looks for NodeInst objects in the cell that are of the type
1591
* "generic:Essential-Bounds" and builds a rectangle from their locations.
1592
* @return the bounding area of the essential bounds.
1593
* Returns null if an essential bounds cannot be determined.
1595
public Rectangle2D findEssentialBounds()
1597
if (essenBounds.size() < 2)
1599
double minX = Double.MAX_VALUE;
1600
double maxX = Double.MIN_VALUE;
1601
double minY = Double.MAX_VALUE;
1602
double maxY = Double.MIN_VALUE;
1604
for (int i = 0; i < essenBounds.size(); i++)
1606
NodeInst ni = essenBounds.get(i);
1607
minX = Math.min(minX, ni.getTrueCenterX());
1608
maxX = Math.max(maxX, ni.getTrueCenterX());
1609
minY = Math.min(minY, ni.getTrueCenterY());
1610
maxY = Math.max(maxY, ni.getTrueCenterY());
1613
return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
1493
return getTopology().searchIterator(bounds, includeEdges);
1497
* Method to return the bounds of this Cell.
1498
* @return an ERectangle with the bounds of this cell's contents
1500
public ERectangle getBounds() {
1501
return treeUnsafe().getBounds();
1505
* Method to compute the "essential bounds" of this Cell.
1506
* It looks for NodeInst objects in the cell that are of the type
1507
* "generic:Essential-Bounds" and builds a rectangle from their locations.
1508
* @return the bounding area of the essential bounds.
1509
* Returns null if an essential bounds cannot be determined.
1511
public Rectangle2D findEssentialBounds() {
1512
return getTopology().findEssentialBounds();
1617
1516
* Method to determine whether this Cell has a cell center in it.
1618
1517
* @return true if this Cell has a Cell-center node in it.
1620
public boolean alreadyCellCenter()
1622
for(Iterator<NodeInst> it = getNodes(); it.hasNext(); )
1519
public boolean alreadyCellCenter() {
1520
for (Iterator<NodeInst> it = getNodes(); it.hasNext();) {
1624
1521
NodeInst ni = it.next();
1625
if (ni.getProto() == Generic.tech().cellCenterNode) return true;
1522
if (ni.getProto() == Generic.tech().cellCenterNode) {
1631
* Method adjust this cell when the reference point moves.
1632
* This requires renumbering all coordinate values in the Cell.
1633
* @param cX coordinate X of new center.
1530
* Method adjust this cell when the reference point moves.
1531
* This requires renumbering all coordinate values in the Cell.
1532
* @param cX coordinate X of new center.
1634
1533
* @param cY coordinate Y of new center.
1636
public void adjustReferencePoint(double cX, double cY)
1640
// if there is no change, stop now
1641
if (cX == 0 && cY == 0) return;
1643
// move reference point by (dx,dy)
1535
public void adjustReferencePoint(double cX, double cY) {
1538
// if there is no change, stop now
1539
if (cX == 0 && cY == 0) {
1543
// move reference point by (dx,dy)
1644
1544
// referencePointNode.modifyInstance(-cX, -cY, 0, 0, 0);
1646
// must adjust all nodes by (dx,dy)
1647
for(Iterator<NodeInst> it = getNodes(); it.hasNext(); )
1649
NodeInst ni = it.next();
1650
if (ni.getProto() == Generic.tech().cellCenterNode) continue;
1652
// move NodeInst "ni" by (dx,dy)
1655
for(Iterator<ArcInst> it = getArcs(); it.hasNext(); )
1657
ArcInst ai = it.next();
1659
// move NodeInst "ni" by (dx,dy)
1660
ai.modify(-cX, -cY, -cX, -cY);
1663
// adjust all instances of this cell
1664
for(Iterator<NodeInst> it = getInstancesOf(); it.hasNext(); )
1666
NodeInst ni = it.next();
1546
// must adjust all nodes by (dx,dy)
1547
for (Iterator<NodeInst> it = getNodes(); it.hasNext();) {
1548
NodeInst ni = it.next();
1549
if (ni.getProto() == Generic.tech().cellCenterNode) {
1553
// move NodeInst "ni" by (dx,dy)
1556
for (Iterator<ArcInst> it = getArcs(); it.hasNext();) {
1557
ArcInst ai = it.next();
1559
// move NodeInst "ni" by (dx,dy)
1560
ai.modify(-cX, -cY, -cX, -cY);
1563
// adjust all instances of this cell
1564
for (Iterator<NodeInst> it = getInstancesOf(); it.hasNext();) {
1565
NodeInst ni = it.next();
1667
1566
// Undo.redrawObject(ni);
1668
1567
AffineTransform trans = ni.getOrient().pureRotate();
1669
1568
// AffineTransform trans = NodeInst.pureRotate(ni.getAngle(), ni.isMirroredAboutXAxis(), ni.isMirroredAboutYAxis());
1670
Point2D in = new Point2D.Double(cX, cY);
1671
trans.transform(in, in);
1672
ni.move(in.getX(), in.getY());
1569
Point2D in = new Point2D.Double(cX, cY);
1570
trans.transform(in, in);
1571
ni.move(in.getX(), in.getY());
1675
1574
Job.getUserInterface().adjustReferencePoint(this, cX, cY);
1676
1575
// // adjust all windows showing this cell
1686
1585
// off.setLocation(off.getX()-cX, off.getY()-cY);
1687
1586
// wnd.setOffset(off);
1692
* Class for creating a description of a frame around a schematic cell.
1694
public static class FrameDescription
1696
public static final double MULTIPAGESEPARATION = 1000;
1698
private static final double FRAMESCALE = 18.0;
1699
private static final double HASCHXSIZE = ( 8.5 * FRAMESCALE);
1700
private static final double HASCHYSIZE = ( 5.5 * FRAMESCALE);
1701
private static final double ASCHXSIZE = (11.0 * FRAMESCALE);
1702
private static final double ASCHYSIZE = ( 8.5 * FRAMESCALE);
1703
private static final double BSCHXSIZE = (17.0 * FRAMESCALE);
1704
private static final double BSCHYSIZE = (11.0 * FRAMESCALE);
1705
private static final double CSCHXSIZE = (24.0 * FRAMESCALE);
1706
private static final double CSCHYSIZE = (17.0 * FRAMESCALE);
1707
private static final double DSCHXSIZE = (36.0 * FRAMESCALE);
1708
private static final double DSCHYSIZE = (24.0 * FRAMESCALE);
1709
private static final double ESCHXSIZE = (48.0 * FRAMESCALE);
1710
private static final double ESCHYSIZE = (36.0 * FRAMESCALE);
1711
private static final double FRAMEWID = ( 0.15 * FRAMESCALE);
1712
private static final double XLOGOBOX = ( 2.0 * FRAMESCALE);
1713
private static final double YLOGOBOX = ( 1.0 * FRAMESCALE);
1716
private List<Point2D> lineFromEnd;
1717
private List<Point2D> lineToEnd;
1718
private List<Point2D> textPoint;
1719
private List<Double> textSize;
1720
private List<Point2D> textBox;
1721
private List<String> textMessage;
1725
* Constructor for cell frame descriptions.
1726
* @param cell the Cell that is having a frame drawn.
1728
public FrameDescription(Cell cell, int pageNo)
1731
this.pageNo = pageNo;
1732
lineFromEnd = new ArrayList<Point2D>();
1733
lineToEnd = new ArrayList<Point2D>();
1734
textPoint = new ArrayList<Point2D>();
1735
textSize = new ArrayList<Double>();
1736
textBox = new ArrayList<Point2D>();
1737
textMessage = new ArrayList<String>();
1742
* Method to draw a line in a frame.
1743
* This method is overridden by subclasses that know how to do the function.
1744
* @param from the starting point of the line (in database units).
1745
* @param to the ending point of the line (in database units).
1747
public void showFrameLine(Point2D from, Point2D to) {}
1750
* Method to draw text in a frame.
1751
* This method is overridden by subclasses that know how to do the function.
1752
* @param ctr the anchor point of the text.
1753
* @param size the size of the text (in database units).
1754
* @param maxWid the maximum width of the text (ignored if zero).
1755
* @param maxHei the maximum height of the text (ignored if zero).
1756
* @param string the text to be displayed.
1758
public void showFrameText(Point2D ctr, double size, double maxWid, double maxHei, String string) {}
1761
* Method called to render the frame information.
1762
* It makes calls to "renderInit()", "showFrameLine()", and "showFrameText()".
1764
public void renderFrame()
1767
if (cell.isMultiPage())
1769
offY = pageNo * MULTIPAGESEPARATION;
1771
for(int i=0; i<lineFromEnd.size(); i++)
1773
Point2D from = lineFromEnd.get(i);
1774
Point2D to = lineToEnd.get(i);
1777
from = new Point2D.Double(from.getX(), from.getY() + offY);
1778
to = new Point2D.Double(to.getX(), to.getY() + offY);
1780
showFrameLine(from, to);
1782
for(int i=0; i<textPoint.size(); i++)
1784
Point2D at = textPoint.get(i);
1786
at = new Point2D.Double(at.getX(), at.getY() + offY);
1787
double size = textSize.get(i).doubleValue();
1788
Point2D box = textBox.get(i);
1789
double width = box.getX();
1790
double height = box.getY();
1791
String msg = textMessage.get(i);
1792
showFrameText(at, size, width, height, msg);
1797
* Method to determine the size of the schematic frame in the current Cell.
1798
* @param d a Dimension in which the size (database units) will be placed.
1799
* @return 0: there should be a frame whose size is absolute;
1800
* 1: there should be a frame but it combines with other stuff in the cell;
1801
* 2: there is no frame.
1803
public static int getCellFrameInfo(Cell cell, Dimension d)
1805
String frameInfo = cell.getVarValue(User.FRAME_SIZE, String.class);
1806
if (frameInfo == null) return 2;
1807
if (frameInfo.length() == 0) return 2;
1809
char chr = frameInfo.charAt(0);
1810
double wid = 0, hei = 0;
1813
wid = XLOGOBOX + FRAMEWID; hei = YLOGOBOX + FRAMEWID;
1819
case 'h': wid = HASCHXSIZE; hei = HASCHYSIZE; break;
1820
case 'a': wid = ASCHXSIZE; hei = ASCHYSIZE; break;
1821
case 'b': wid = BSCHXSIZE; hei = BSCHYSIZE; break;
1822
case 'c': wid = CSCHXSIZE; hei = CSCHYSIZE; break;
1823
case 'd': wid = DSCHXSIZE; hei = DSCHYSIZE; break;
1824
case 'e': wid = ESCHXSIZE; hei = ESCHYSIZE; break;
1827
if (frameInfo.indexOf("v") >= 0)
1829
d.setSize(hei, wid);
1832
d.setSize(wid, hei);
1837
private void loadFrame()
1839
Dimension d = new Dimension();
1840
int frameFactor = getCellFrameInfo(cell, d);
1841
if (frameFactor == 2) return;
1843
String frameInfo = cell.getVarValue(User.FRAME_SIZE, String.class);
1844
if (frameInfo == null) return;
1845
double schXSize = d.getWidth();
1846
double schYSize = d.getHeight();
1848
boolean drawTitleBox = true;
1851
if (frameFactor == 1)
1853
xSections = ySections = 0;
1856
if (frameInfo.indexOf("v") >= 0)
1861
if (frameInfo.indexOf("n") >= 0) drawTitleBox = false;
1864
double xLogoBox = XLOGOBOX;
1865
double yLogoBox = YLOGOBOX;
1866
double frameWid = FRAMEWID;
1871
double xSecSize = (schXSize - frameWid*2) / xSections;
1872
double ySecSize = (schYSize - frameWid*2) / ySections;
1874
// draw the outer frame
1875
Point2D point0 = new Point2D.Double(-schXSize/2, -schYSize/2);
1876
Point2D point1 = new Point2D.Double(-schXSize/2, schYSize/2);
1877
Point2D point2 = new Point2D.Double( schXSize/2, schYSize/2);
1878
Point2D point3 = new Point2D.Double( schXSize/2, -schYSize/2);
1879
addLine(point0, point1);
1880
addLine(point1, point2);
1881
addLine(point2, point3);
1882
addLine(point3, point0);
1884
// draw the inner frame
1885
point0 = new Point2D.Double(-schXSize/2 + frameWid, -schYSize/2 + frameWid);
1886
point1 = new Point2D.Double(-schXSize/2 + frameWid, schYSize/2 - frameWid);
1887
point2 = new Point2D.Double( schXSize/2 - frameWid, schYSize/2 - frameWid);
1888
point3 = new Point2D.Double( schXSize/2 - frameWid, -schYSize/2 + frameWid);
1889
addLine(point0, point1);
1890
addLine(point1, point2);
1891
addLine(point2, point3);
1892
addLine(point3, point0);
1894
// tick marks along the top and bottom sides
1895
for(int i=0; i<xSections; i++)
1897
double x = i * xSecSize - (schXSize/2 - frameWid);
1900
point0 = new Point2D.Double(x, schYSize/2 - frameWid);
1901
point1 = new Point2D.Double(x, schYSize/2 - frameWid/2);
1902
addLine(point0, point1);
1903
point0 = new Point2D.Double(x, -schYSize/2 + frameWid);
1904
point1 = new Point2D.Double(x, -schYSize/2 + frameWid/2);
1905
addLine(point0, point1);
1908
char chr = (char)('1' + xSections - i - 1);
1909
point0 = new Point2D.Double(x + xSecSize/2, schYSize/2 - frameWid/2);
1910
addText(point0, frameWid, 0, 0, String.valueOf(chr));
1912
point0 = new Point2D.Double(x + xSecSize/2, -schYSize/2 + frameWid/2);
1913
addText(point0, frameWid, 0, 0, String.valueOf(chr));
1916
// tick marks along the left and right sides
1917
for(int i=0; i<ySections; i++)
1919
double y = i * ySecSize - (schYSize/2 - frameWid);
1922
point0 = new Point2D.Double(schXSize/2 - frameWid, y);
1923
point1 = new Point2D.Double(schXSize/2 - frameWid/2, y);
1924
addLine(point0, point1);
1925
point0 = new Point2D.Double(-schXSize/2 + frameWid, y);
1926
point1 = new Point2D.Double(-schXSize/2 + frameWid/2, y);
1927
addLine(point0, point1);
1929
char chr = (char)('A' + i);
1930
point0 = new Point2D.Double(schXSize/2 - frameWid/2, y + ySecSize/2);
1931
addText(point0, frameWid, 0, 0, String.valueOf(chr));
1933
point0 = new Point2D.Double(-schXSize/2 + frameWid/2, y + ySecSize/2);
1934
addText(point0, frameWid, 0, 0, String.valueOf(chr));
1939
Point2D point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox, -schYSize/2 + frameWid + yLogoBox);
1940
Point2D point1 = new Point2D.Double(schXSize/2 - frameWid, -schYSize/2 + frameWid + yLogoBox);
1941
Point2D point2 = new Point2D.Double(schXSize/2 - frameWid, -schYSize/2 + frameWid);
1942
Point2D point3 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox, -schYSize/2 + frameWid);
1943
addLine(point0, point1);
1944
addLine(point1, point2);
1945
addLine(point2, point3);
1946
addLine(point3, point0);
1948
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox, -schYSize/2 + frameWid + yLogoBox*2/15);
1949
point1 = new Point2D.Double(schXSize/2 - frameWid, -schYSize/2 + frameWid + yLogoBox*2/15);
1950
addLine(point0, point1);
1952
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox, -schYSize/2 + frameWid + yLogoBox*4/15);
1953
point1 = new Point2D.Double(schXSize/2 - frameWid, -schYSize/2 + frameWid + yLogoBox*4/15);
1954
addLine(point0, point1);
1956
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox, -schYSize/2 + frameWid + yLogoBox*6/15);
1957
point1 = new Point2D.Double(schXSize/2 - frameWid, -schYSize/2 + frameWid + yLogoBox*6/15);
1958
addLine(point0, point1);
1960
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox, -schYSize/2 + frameWid + yLogoBox*8/15);
1961
point1 = new Point2D.Double(schXSize/2 - frameWid, -schYSize/2 + frameWid + yLogoBox*8/15);
1962
addLine(point0, point1);
1964
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox, -schYSize/2 + frameWid + yLogoBox*10/15);
1965
point1 = new Point2D.Double(schXSize/2 - frameWid, -schYSize/2 + frameWid + yLogoBox*10/15);
1966
addLine(point0, point1);
1968
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox, -schYSize/2 + frameWid + yLogoBox*12/15);
1969
point1 = new Point2D.Double(schXSize/2 - frameWid, -schYSize/2 + frameWid + yLogoBox*12/15);
1970
addLine(point0, point1);
1972
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox/2, -schYSize/2 + frameWid + yLogoBox*13.5/15);
1973
addText(point0, yLogoBox*2/15, xLogoBox, yLogoBox*3/15, "Cell: " + cell.describe(false) + (cell.isMultiPage() ? " Page " + (pageNo+1) : ""));
1975
String projectName = cell.getLibrary().getVarValue(User.FRAME_PROJECT_NAME, String.class, User.getFrameProjectName());
1976
if (projectName.length() > 0)
1978
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox/2, -schYSize/2 + frameWid + yLogoBox*11/15);
1979
addText(point0, yLogoBox*2/15, xLogoBox, yLogoBox*2/15, "Project: " + projectName);
1591
* Class for creating a description of a frame around a schematic cell.
1593
public static class FrameDescription {
1595
public static final double MULTIPAGESEPARATION = 1000;
1596
private static final double FRAMESCALE = 18.0;
1597
private static final double HASCHXSIZE = (8.5 * FRAMESCALE);
1598
private static final double HASCHYSIZE = (5.5 * FRAMESCALE);
1599
private static final double ASCHXSIZE = (11.0 * FRAMESCALE);
1600
private static final double ASCHYSIZE = (8.5 * FRAMESCALE);
1601
private static final double BSCHXSIZE = (17.0 * FRAMESCALE);
1602
private static final double BSCHYSIZE = (11.0 * FRAMESCALE);
1603
private static final double CSCHXSIZE = (24.0 * FRAMESCALE);
1604
private static final double CSCHYSIZE = (17.0 * FRAMESCALE);
1605
private static final double DSCHXSIZE = (36.0 * FRAMESCALE);
1606
private static final double DSCHYSIZE = (24.0 * FRAMESCALE);
1607
private static final double ESCHXSIZE = (48.0 * FRAMESCALE);
1608
private static final double ESCHYSIZE = (36.0 * FRAMESCALE);
1609
private static final double FRAMEWID = (0.15 * FRAMESCALE);
1610
private static final double XLOGOBOX = (2.0 * FRAMESCALE);
1611
private static final double YLOGOBOX = (1.0 * FRAMESCALE);
1613
private List<Point2D> lineFromEnd;
1614
private List<Point2D> lineToEnd;
1615
private List<Point2D> textPoint;
1616
private List<Double> textSize;
1617
private List<Point2D> textBox;
1618
private List<String> textMessage;
1622
* Constructor for cell frame descriptions.
1623
* @param cell the Cell that is having a frame drawn.
1625
public FrameDescription(Cell cell, int pageNo) {
1627
this.pageNo = pageNo;
1628
lineFromEnd = new ArrayList<Point2D>();
1629
lineToEnd = new ArrayList<Point2D>();
1630
textPoint = new ArrayList<Point2D>();
1631
textSize = new ArrayList<Double>();
1632
textBox = new ArrayList<Point2D>();
1633
textMessage = new ArrayList<String>();
1638
* Method to draw a line in a frame.
1639
* This method is overridden by subclasses that know how to do the function.
1640
* @param from the starting point of the line (in database units).
1641
* @param to the ending point of the line (in database units).
1643
public void showFrameLine(Point2D from, Point2D to) {
1647
* Method to draw text in a frame.
1648
* This method is overridden by subclasses that know how to do the function.
1649
* @param ctr the anchor point of the text.
1650
* @param size the size of the text (in database units).
1651
* @param maxWid the maximum width of the text (ignored if zero).
1652
* @param maxHei the maximum height of the text (ignored if zero).
1653
* @param string the text to be displayed.
1655
public void showFrameText(Point2D ctr, double size, double maxWid, double maxHei, String string) {
1659
* Method called to render the frame information.
1660
* It makes calls to "renderInit()", "showFrameLine()", and "showFrameText()".
1662
public void renderFrame() {
1664
if (cell.isMultiPage()) {
1665
offY = pageNo * MULTIPAGESEPARATION;
1667
for (int i = 0; i < lineFromEnd.size(); i++) {
1668
Point2D from = lineFromEnd.get(i);
1669
Point2D to = lineToEnd.get(i);
1671
from = new Point2D.Double(from.getX(), from.getY() + offY);
1672
to = new Point2D.Double(to.getX(), to.getY() + offY);
1674
showFrameLine(from, to);
1676
for (int i = 0; i < textPoint.size(); i++) {
1677
Point2D at = textPoint.get(i);
1679
at = new Point2D.Double(at.getX(), at.getY() + offY);
1681
double size = textSize.get(i).doubleValue();
1682
Point2D box = textBox.get(i);
1683
double width = box.getX();
1684
double height = box.getY();
1685
String msg = textMessage.get(i);
1686
showFrameText(at, size, width, height, msg);
1691
* Method to determine the size of the schematic frame in the current Cell.
1692
* @param d a Dimension in which the size (database units) will be placed.
1693
* @return 0: there should be a frame whose size is absolute;
1694
* 1: there should be a frame but it combines with other stuff in the cell;
1695
* 2: there is no frame.
1697
public static int getCellFrameInfo(Cell cell, Dimension d) {
1698
String frameInfo = cell.getVarValue(User.FRAME_SIZE, String.class);
1699
if (frameInfo == null) {
1702
if (frameInfo.length() == 0) {
1706
char chr = frameInfo.charAt(0);
1707
double wid = 0, hei = 0;
1709
wid = XLOGOBOX + FRAMEWID;
1710
hei = YLOGOBOX + FRAMEWID;
1740
if (frameInfo.indexOf("v") >= 0) {
1741
d.setSize(hei, wid);
1743
d.setSize(wid, hei);
1748
private void loadFrame() {
1749
Dimension d = new Dimension();
1750
int frameFactor = getCellFrameInfo(cell, d);
1751
if (frameFactor == 2) {
1755
String frameInfo = cell.getVarValue(User.FRAME_SIZE, String.class);
1756
if (frameInfo == null) {
1759
double schXSize = d.getWidth();
1760
double schYSize = d.getHeight();
1762
boolean drawTitleBox = true;
1765
if (frameFactor == 1) {
1766
xSections = ySections = 0;
1768
if (frameInfo.indexOf("v") >= 0) {
1772
if (frameInfo.indexOf("n") >= 0) {
1773
drawTitleBox = false;
1777
double xLogoBox = XLOGOBOX;
1778
double yLogoBox = YLOGOBOX;
1779
double frameWid = FRAMEWID;
1782
if (xSections > 0) {
1783
double xSecSize = (schXSize - frameWid * 2) / xSections;
1784
double ySecSize = (schYSize - frameWid * 2) / ySections;
1786
// draw the outer frame
1787
Point2D point0 = new Point2D.Double(-schXSize / 2, -schYSize / 2);
1788
Point2D point1 = new Point2D.Double(-schXSize / 2, schYSize / 2);
1789
Point2D point2 = new Point2D.Double(schXSize / 2, schYSize / 2);
1790
Point2D point3 = new Point2D.Double(schXSize / 2, -schYSize / 2);
1791
addLine(point0, point1);
1792
addLine(point1, point2);
1793
addLine(point2, point3);
1794
addLine(point3, point0);
1796
// draw the inner frame
1797
point0 = new Point2D.Double(-schXSize / 2 + frameWid, -schYSize / 2 + frameWid);
1798
point1 = new Point2D.Double(-schXSize / 2 + frameWid, schYSize / 2 - frameWid);
1799
point2 = new Point2D.Double(schXSize / 2 - frameWid, schYSize / 2 - frameWid);
1800
point3 = new Point2D.Double(schXSize / 2 - frameWid, -schYSize / 2 + frameWid);
1801
addLine(point0, point1);
1802
addLine(point1, point2);
1803
addLine(point2, point3);
1804
addLine(point3, point0);
1806
// tick marks along the top and bottom sides
1807
for (int i = 0; i < xSections; i++) {
1808
double x = i * xSecSize - (schXSize / 2 - frameWid);
1810
point0 = new Point2D.Double(x, schYSize / 2 - frameWid);
1811
point1 = new Point2D.Double(x, schYSize / 2 - frameWid / 2);
1812
addLine(point0, point1);
1813
point0 = new Point2D.Double(x, -schYSize / 2 + frameWid);
1814
point1 = new Point2D.Double(x, -schYSize / 2 + frameWid / 2);
1815
addLine(point0, point1);
1818
char chr = (char) ('1' + xSections - i - 1);
1819
point0 = new Point2D.Double(x + xSecSize / 2, schYSize / 2 - frameWid / 2);
1820
addText(point0, frameWid, 0, 0, String.valueOf(chr));
1822
point0 = new Point2D.Double(x + xSecSize / 2, -schYSize / 2 + frameWid / 2);
1823
addText(point0, frameWid, 0, 0, String.valueOf(chr));
1826
// tick marks along the left and right sides
1827
for (int i = 0; i < ySections; i++) {
1828
double y = i * ySecSize - (schYSize / 2 - frameWid);
1830
point0 = new Point2D.Double(schXSize / 2 - frameWid, y);
1831
point1 = new Point2D.Double(schXSize / 2 - frameWid / 2, y);
1832
addLine(point0, point1);
1833
point0 = new Point2D.Double(-schXSize / 2 + frameWid, y);
1834
point1 = new Point2D.Double(-schXSize / 2 + frameWid / 2, y);
1835
addLine(point0, point1);
1837
char chr = (char) ('A' + i);
1838
point0 = new Point2D.Double(schXSize / 2 - frameWid / 2, y + ySecSize / 2);
1839
addText(point0, frameWid, 0, 0, String.valueOf(chr));
1841
point0 = new Point2D.Double(-schXSize / 2 + frameWid / 2, y + ySecSize / 2);
1842
addText(point0, frameWid, 0, 0, String.valueOf(chr));
1846
Point2D point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox, -schYSize / 2 + frameWid + yLogoBox);
1847
Point2D point1 = new Point2D.Double(schXSize / 2 - frameWid, -schYSize / 2 + frameWid + yLogoBox);
1848
Point2D point2 = new Point2D.Double(schXSize / 2 - frameWid, -schYSize / 2 + frameWid);
1849
Point2D point3 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox, -schYSize / 2 + frameWid);
1850
addLine(point0, point1);
1851
addLine(point1, point2);
1852
addLine(point2, point3);
1853
addLine(point3, point0);
1855
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox, -schYSize / 2 + frameWid + yLogoBox * 2 / 15);
1856
point1 = new Point2D.Double(schXSize / 2 - frameWid, -schYSize / 2 + frameWid + yLogoBox * 2 / 15);
1857
addLine(point0, point1);
1859
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox, -schYSize / 2 + frameWid + yLogoBox * 4 / 15);
1860
point1 = new Point2D.Double(schXSize / 2 - frameWid, -schYSize / 2 + frameWid + yLogoBox * 4 / 15);
1861
addLine(point0, point1);
1863
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox, -schYSize / 2 + frameWid + yLogoBox * 6 / 15);
1864
point1 = new Point2D.Double(schXSize / 2 - frameWid, -schYSize / 2 + frameWid + yLogoBox * 6 / 15);
1865
addLine(point0, point1);
1867
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox, -schYSize / 2 + frameWid + yLogoBox * 8 / 15);
1868
point1 = new Point2D.Double(schXSize / 2 - frameWid, -schYSize / 2 + frameWid + yLogoBox * 8 / 15);
1869
addLine(point0, point1);
1871
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox, -schYSize / 2 + frameWid + yLogoBox * 10 / 15);
1872
point1 = new Point2D.Double(schXSize / 2 - frameWid, -schYSize / 2 + frameWid + yLogoBox * 10 / 15);
1873
addLine(point0, point1);
1875
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox, -schYSize / 2 + frameWid + yLogoBox * 12 / 15);
1876
point1 = new Point2D.Double(schXSize / 2 - frameWid, -schYSize / 2 + frameWid + yLogoBox * 12 / 15);
1877
addLine(point0, point1);
1879
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox / 2, -schYSize / 2 + frameWid + yLogoBox * 13.5 / 15);
1880
addText(point0, yLogoBox * 2 / 15, xLogoBox, yLogoBox * 3 / 15, "Cell: " + cell.describe(false) + (cell.isMultiPage() ? " Page " + (pageNo + 1) : ""));
1882
String projectName = cell.getLibrary().getVarValue(User.FRAME_PROJECT_NAME, String.class, User.getFrameProjectName());
1883
if (projectName.length() > 0) {
1884
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox / 2, -schYSize / 2 + frameWid + yLogoBox * 11 / 15);
1885
addText(point0, yLogoBox * 2 / 15, xLogoBox, yLogoBox * 2 / 15, "Project: " + projectName);
1982
1888
String designerName = cell.getVarValue(User.FRAME_DESIGNER_NAME, String.class);
1983
if (designerName == null)
1889
if (designerName == null) {
1984
1890
designerName = cell.getLibrary().getVarValue(User.FRAME_DESIGNER_NAME, String.class, User.getFrameDesignerName());
1985
if (designerName.length() > 0)
1987
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox/2, -schYSize/2 + frameWid + yLogoBox*9/15);
1988
addText(point0, yLogoBox*2/15, xLogoBox, yLogoBox*2/15, "Designer: " + designerName);
1991
String lastChangeByName = cell.getVarValue(User.FRAME_LAST_CHANGED_BY, String.class);
1992
if (lastChangeByName != null)
1994
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox/2, -schYSize/2 + frameWid + yLogoBox*7/15);
1995
addText(point0, yLogoBox*2/15, xLogoBox, yLogoBox*2/15, "Last Changed By: " + lastChangeByName);
1998
String companyName = cell.getLibrary().getVarValue(User.FRAME_COMPANY_NAME, String.class, User.getFrameCompanyName());
1999
if (companyName.length() > 0)
2001
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox/2, -schYSize/2 + frameWid + yLogoBox*5/15);
2002
addText(point0, yLogoBox*2/15, xLogoBox, yLogoBox*2/15, "Company: " + companyName);
2005
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox/2, -schYSize/2 + frameWid + yLogoBox*3/15);
2006
addText(point0, yLogoBox*2/15, xLogoBox, yLogoBox*2/15, "Created: " + TextUtils.formatDate(cell.getCreationDate()));
2008
point0 = new Point2D.Double(schXSize/2 - frameWid - xLogoBox/2, -schYSize/2 + frameWid + yLogoBox*1/15);
2009
addText(point0, yLogoBox*2/15, xLogoBox, yLogoBox*2/15, "Revised: " + TextUtils.formatDate(cell.getRevisionDate()));
2013
private void addLine(Point2D from, Point2D to)
2015
lineFromEnd.add(from);
2019
private void addText(Point2D at, double size, double width, double height, String msg)
2022
textSize.add(new Double(size));
2023
textBox.add(new Point2D.Double(width, height));
2024
textMessage.add(msg);
2028
/****************************** NODES ******************************/
2031
* Method to return an Iterator over all NodeInst objects in this Cell.
2032
* @return an Iterator over all NodeInst objects in this Cell.
2034
public synchronized Iterator<NodeInst> getNodes()
2036
List<NodeInst> nodesCopy = new ArrayList<NodeInst>(nodes);
2037
return nodesCopy.iterator();
2041
* Method to return an Iterator over all NodeInst objects in this Cell.
2042
* @return an Iterator over all NodeInst objects in this Cell.
2044
public synchronized Iterator<Nodable> getNodables()
2046
List<Nodable> nodesCopy = new ArrayList<Nodable>(nodes);
2047
return nodesCopy.iterator();
2051
* Method to return the number of NodeInst objects in this Cell.
2052
* @return the number of NodeInst objects in this Cell.
2054
public int getNumNodes()
2056
return nodes.size();
2060
* Method to return the NodeInst at specified position.
2061
* @param nodeIndex specified position of NodeInst.
2062
* @return the NodeInst at specified position.
2064
public final NodeInst getNode(int nodeIndex)
2066
return nodes.get(nodeIndex);
2070
* Method to return the NodeInst by its chronological index.
2071
* @param nodeId chronological index of NodeInst.
2072
* @return the NodeInst with specified chronological index.
2074
public NodeInst getNodeById(int nodeId)
2076
return nodeId < chronNodes.size() ? chronNodes.get(nodeId) : null;
1892
if (designerName.length() > 0) {
1893
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox / 2, -schYSize / 2 + frameWid + yLogoBox * 9 / 15);
1894
addText(point0, yLogoBox * 2 / 15, xLogoBox, yLogoBox * 2 / 15, "Designer: " + designerName);
1897
String lastChangeByName = cell.getVarValue(User.FRAME_LAST_CHANGED_BY, String.class);
1898
if (lastChangeByName != null) {
1899
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox / 2, -schYSize / 2 + frameWid + yLogoBox * 7 / 15);
1900
addText(point0, yLogoBox * 2 / 15, xLogoBox, yLogoBox * 2 / 15, "Last Changed By: " + lastChangeByName);
1903
String companyName = cell.getLibrary().getVarValue(User.FRAME_COMPANY_NAME, String.class, User.getFrameCompanyName());
1904
if (companyName.length() > 0) {
1905
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox / 2, -schYSize / 2 + frameWid + yLogoBox * 5 / 15);
1906
addText(point0, yLogoBox * 2 / 15, xLogoBox, yLogoBox * 2 / 15, "Company: " + companyName);
1909
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox / 2, -schYSize / 2 + frameWid + yLogoBox * 3 / 15);
1910
addText(point0, yLogoBox * 2 / 15, xLogoBox, yLogoBox * 2 / 15, "Created: " + TextUtils.formatDate(cell.getCreationDate()));
1912
point0 = new Point2D.Double(schXSize / 2 - frameWid - xLogoBox / 2, -schYSize / 2 + frameWid + yLogoBox * 1 / 15);
1913
addText(point0, yLogoBox * 2 / 15, xLogoBox, yLogoBox * 2 / 15, "Revised: " + TextUtils.formatDate(cell.getRevisionDate()));
1917
private void addLine(Point2D from, Point2D to) {
1918
lineFromEnd.add(from);
1922
private void addText(Point2D at, double size, double width, double height, String msg) {
1924
textSize.add(new Double(size));
1925
textBox.add(new Point2D.Double(width, height));
1926
textMessage.add(msg);
1930
/****************************** NODES ******************************/
1932
* Method to return an Iterator over all NodeInst objects in this Cell.
1933
* @return an Iterator over all NodeInst objects in this Cell.
1935
public synchronized Iterator<NodeInst> getNodes() {
1936
return getTopology().getNodes();
1940
* Method to return an Iterator over all NodeInst objects in this Cell.
1941
* @return an Iterator over all NodeInst objects in this Cell.
1943
public synchronized Iterator<Nodable> getNodables() {
1944
return getTopology().getNodables();
1948
* Method to return the number of NodeInst objects in this Cell.
1949
* @return the number of NodeInst objects in this Cell.
1951
public int getNumNodes() {
1952
Topology topology = getTopologyOptional();
1953
return topology != null ? topology.getNumNodes() : backup().cellRevision.nodes.size();
1957
* Method to return the NodeInst at specified position.
1958
* @param nodeIndex specified position of NodeInst.
1959
* @return the NodeInst at specified position.
1961
public final NodeInst getNode(int nodeIndex) {
1962
return getTopology().getNode(nodeIndex);
1966
* Method to return the NodeInst by its chronological index.
1967
* @param nodeId chronological index of NodeInst.
1968
* @return the NodeInst with specified chronological index.
1970
public NodeInst getNodeById(int nodeId) {
1971
return getTopology().getNodeById(nodeId);
2080
1975
* Tells expanded status of NodeInst with specified nodeId.
2335
* Method to return unique autoname for NodeInst in this cell.
2336
* @param basename base name of autoname
2339
public Name getNodeAutoname(Name basename)
2341
String basenameString = basename.toString();
2342
// String basenameString = basename.canonicString();
2343
MaxSuffix ms = maxSuffix.get(basenameString);
2347
ms = new MaxSuffix();
2348
maxSuffix.put(basenameString, ms);
2349
name = basename.findSuffixed(0);
2353
name = basename.findSuffixed(ms.v);
2355
assert searchNode(name.toString()) < 0;
2360
* Method to remove an NodeInst from the cell.
2361
* @param ni the NodeInst to be removed from the cell.
2363
private void removeNode(NodeInst ni)
2366
assert ni.isLinked();
2368
essenBounds.remove(ni);
2239
* Method to remove an NodeInst from the cell.
2240
* @param ni the NodeInst to be removed from the cell.
2242
private void removeNode(NodeInst ni) {
2244
assert ni.isLinked();
2245
getTopology().removeNode(ni);
2247
// essenBounds.remove(ni);
2370
2249
// remove usage count
2371
2250
if (ni.isCellInstance()) {
2372
Cell subCell = (Cell)ni.getProto();
2251
Cell subCell = (Cell) ni.getProto();
2373
2252
CellUsage u = getId().getUsageIn(subCell.getId());
2374
2253
cellUsages[u.indexInParent]--;
2375
2254
if (cellUsages[u.indexInParent] <= 0) {
2376
2255
assert cellUsages[u.indexInParent] == 0;
2377
2256
// remove library dependency, if possible
2378
getLibrary().removeReferencedLib(((Cell)ni.getProto()).getLibrary());
2257
getLibrary().removeReferencedLib(((Cell) ni.getProto()).getLibrary());
2382
setContentsModified();
2384
int nodeId = ni.getD().nodeId;
2385
assert chronNodes.get(nodeId) == ni;
2386
chronNodes.set(nodeId, null);
2391
* Method to remove an NodeInst from the name index of this cell.
2392
* @param ni the NodeInst to be removed from the cell.
2394
public void removeNodeName(NodeInst ni)
2396
int nodeIndex = ni.getNodeIndex();
2397
NodeInst removedNi = nodes.remove(nodeIndex);
2398
assert removedNi == ni;
2399
for (int i = nodeIndex; i < nodes.size(); i++)
2401
NodeInst n = nodes.get(i);
2404
ni.setNodeIndex(-1);
2408
* Searches the nodes for the specified name using the binary
2410
* @param name the name to be searched.
2411
* @return index of the search name, if it is contained in the nodes;
2412
* otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
2413
* <i>insertion point</i> is defined as the point at which the
2414
* NodeInst would be inserted into the list: the index of the first
2415
* element greater than the name, or <tt>nodes.size()</tt>, if all
2416
* elements in the list are less than the specified name. Note
2417
* that this guarantees that the return value will be >= 0 if
2418
* and only if the NodeInst is found.
2420
private int searchNode(String name)
2423
int high = nodes.size()-1;
2424
int pick = high; // initially try the last postition
2425
while (low <= high) {
2426
NodeInst ni = nodes.get(pick);
2427
int cmp = TextUtils.STRING_NUMBER_ORDER.compare(ni.getName(), name);
2434
return pick; // NodeInst found
2435
pick = (low + high) >> 1; // try in a middle
2437
return -(low + 1); // NodeInst not found.
2440
/****************************** ARCS ******************************/
2443
* Method to return an Iterator over all ArcInst objects in this Cell.
2444
* @return an Iterator over all ArcInst objects in this Cell.
2446
public synchronized Iterator<ArcInst> getArcs() { return getTopology().getArcs(); }
2449
* Method to return the number of ArcInst objects in this Cell.
2450
* @return the number of ArcInst objects in this Cell.
2452
public int getNumArcs() { return topology.getNumArcs(); }
2455
* Method to return the ArcInst at specified position.
2456
* @param arcIndex specified position of ArcInst.
2457
* @return the ArcInst at specified position..
2459
public final ArcInst getArc(int arcIndex) { return getTopology().getArc(arcIndex); }
2462
* Method to return the ArcInst by its chronological index.
2463
* @param arcId chronological index of ArcInst.
2464
* @return the ArcInst with specified chronological index.
2466
public ArcInst getArcById(int arcId) { return getTopology().getArcById(arcId); }
2469
* Method to find a named ArcInst on this Cell.
2470
* @param name the name of the ArcInst.
2471
* @return the ArcInst. Returns null if none with that name are found.
2473
public ArcInst findArc(String name) { return getTopology().findArc(name); }
2476
* Method to unlink a set of these ArcInsts from this Cell.
2261
setTopologyModified();
2262
// removeNodeName(ni);
2263
// int nodeId = ni.getD().nodeId;
2264
// assert chronNodes.get(nodeId) == ni;
2265
// chronNodes.set(nodeId, null);
2270
// * Method to remove an NodeInst from the name index of this cell.
2271
// * @param ni the NodeInst to be removed from the cell.
2273
// public void removeNodeName(NodeInst ni) {
2274
// int nodeIndex = ni.getNodeIndex();
2275
// NodeInst removedNi = nodes.remove(nodeIndex);
2276
// assert removedNi == ni;
2277
// for (int i = nodeIndex; i < nodes.size(); i++) {
2278
// NodeInst n = nodes.get(i);
2279
// n.setNodeIndex(i);
2281
// ni.setNodeIndex(-1);
2283
/****************************** ARCS ******************************/
2285
* Method to return an Iterator over all ArcInst objects in this Cell.
2286
* @return an Iterator over all ArcInst objects in this Cell.
2288
public synchronized Iterator<ArcInst> getArcs() {
2289
return getTopology().getArcs();
2293
* Method to return the number of ArcInst objects in this Cell.
2294
* @return the number of ArcInst objects in this Cell.
2296
public int getNumArcs() {
2297
Topology topology = getTopologyOptional();
2298
return topology != null ? topology.getNumArcs() : backup().cellRevision.arcs.size();
2302
* Method to return the ArcInst at specified position.
2303
* @param arcIndex specified position of ArcInst.
2304
* @return the ArcInst at specified position..
2306
public final ArcInst getArc(int arcIndex) {
2307
return getTopology().getArc(arcIndex);
2311
* Method to return the ArcInst by its chronological index.
2312
* @param arcId chronological index of ArcInst.
2313
* @return the ArcInst with specified chronological index.
2315
public ArcInst getArcById(int arcId) {
2316
return getTopology().getArcById(arcId);
2320
* Method to return a map from arcId of arcs in the Cell to their arcIndex in alphanumerical order.
2321
* @return a map from arcId to arcIndex.
2323
public int[] getArcIndexByArcIdMap() {
2324
return backup().getArcIndexByArcIdMap();
2328
* Method to find a named ArcInst on this Cell.
2329
* @param name the name of the ArcInst.
2330
* @return the ArcInst. Returns null if none with that name are found.
2332
public ArcInst findArc(String name) {
2333
return getTopology().findArc(name);
2337
* Method to unlink a set of these ArcInsts from this Cell.
2477
2338
* @param killedArcs a set of ArcInsts to kill.
2479
public void killArcs(Set<ArcInst> killedArcs) {
2480
if (killedArcs.isEmpty()) return;
2481
for(ArcInst ai : killedArcs) {
2482
if (ai.getParent() != this)
2340
public void killArcs(Set<ArcInst> killedArcs) {
2341
if (killedArcs.isEmpty()) {
2344
for (ArcInst ai : killedArcs) {
2345
if (ai.getParent() != this) {
2483
2346
throw new IllegalArgumentException("parent");
2485
2349
for (int arcIndex = getNumArcs() - 1; arcIndex >= 0; arcIndex--) {
2486
2350
ArcInst ai = getArc(arcIndex);
2487
if (killedArcs.contains(ai))
2351
if (killedArcs.contains(ai)) {
2492
/****************************** EXPORTS ******************************/
2495
* Add a PortProto to this NodeProto.
2496
* Adds Exports for Cells, PrimitivePorts for PrimitiveNodes.
2497
* @param export the PortProto to add to this NodeProto.
2499
void addExport(Export export)
2357
/****************************** EXPORTS ******************************/
2359
* Add a PortProto to this NodeProto.
2360
* Adds Exports for Cells, PrimitivePorts for PrimitiveNodes.
2361
* @param export the PortProto to add to this NodeProto.
2363
void addExport(Export export) {
2502
2365
setContentsModified();
2504
int portIndex = - searchExport(export.getName()) - 1;
2505
assert portIndex >= 0;
2506
export.setPortIndex(portIndex);
2367
int portIndex = -searchExport(export.getName()) - 1;
2368
assert portIndex >= 0;
2369
export.setPortIndex(portIndex);
2508
2371
// Add to chronExprots
2509
2372
int chronIndex = export.getId().getChronIndex();
2510
2373
if (chronExports.length <= chronIndex) {
2511
Export[] newChronExports = new Export[Math.max(chronIndex + 1, chronExports.length*2)];
2374
Export[] newChronExports = new Export[Math.max(chronIndex + 1, chronExports.length * 2)];
2512
2375
System.arraycopy(chronExports, 0, newChronExports, 0, chronExports.length);
2513
2376
chronExports = newChronExports;
2515
2378
chronExports[chronIndex] = export;
2517
Export[] newExports = new Export[exports.length + 1];
2518
System.arraycopy(exports, 0, newExports, 0, portIndex);
2519
newExports[portIndex] = export;
2520
for (int i = portIndex; i < exports.length; i++)
2522
Export e = exports[i];
2523
e.setPortIndex(i + 1);
2524
newExports[i + 1] = e;
2526
exports = newExports;
2380
Export[] newExports = new Export[exports.length + 1];
2381
System.arraycopy(exports, 0, newExports, 0, portIndex);
2382
newExports[portIndex] = export;
2383
for (int i = portIndex; i < exports.length; i++) {
2384
Export e = exports[i];
2385
e.setPortIndex(i + 1);
2386
newExports[i + 1] = e;
2388
exports = newExports;
2528
// create a PortInst for every instance of this Cell
2529
if (getId().numUsagesOf() == 0) return;
2390
// create a PortInst for every instance of this Cell
2391
if (getId().numUsagesOf() == 0) {
2530
2394
int[] pattern = new int[exports.length];
2531
for (int i = 0; i < portIndex; i++) pattern[i] = i;
2395
for (int i = 0; i < portIndex; i++) {
2532
2398
pattern[portIndex] = -1;
2533
for (int i = portIndex + 1; i < exports.length; i++) pattern[i] = i - 1;
2399
for (int i = portIndex + 1; i < exports.length; i++) {
2534
2402
updatePortInsts(pattern);
2535
2403
// for(Iterator<NodeInst> it = getInstancesOf(); it.hasNext(); ) {
2536
2404
// NodeInst ni = it.next();
2537
2405
// ni.addPortInst(export);
2538
2406
// assert ni.getNumPortInsts() == exports.length;
2543
* Removes an Export from this Cell.
2544
* @param export the Export to remove from this Cell.
2546
void removeExport(Export export)
2411
* Removes an Export from this Cell.
2412
* @param export the Export to remove from this Cell.
2414
void removeExport(Export export) {
2549
2416
setContentsModified();
2550
int portIndex = export.getPortIndex();
2417
int portIndex = export.getPortIndex();
2552
Export[] newExports = exports.length > 1 ? new Export[exports.length - 1] : NULL_EXPORT_ARRAY;
2553
System.arraycopy(exports, 0, newExports, 0, portIndex);
2554
for (int i = portIndex; i < newExports.length; i++)
2556
Export e = exports[i + 1];
2560
exports = newExports;
2419
Export[] newExports = exports.length > 1 ? new Export[exports.length - 1] : NULL_EXPORT_ARRAY;
2420
System.arraycopy(exports, 0, newExports, 0, portIndex);
2421
for (int i = portIndex; i < newExports.length; i++) {
2422
Export e = exports[i + 1];
2426
exports = newExports;
2561
2427
chronExports[export.getId().getChronIndex()] = null;
2562
export.setPortIndex(-1);
2428
export.setPortIndex(-1);
2564
// remove the PortInst from every instance of this Cell
2565
if (getId().numUsagesOf() == 0) return;
2430
// remove the PortInst from every instance of this Cell
2431
if (getId().numUsagesOf() == 0) {
2566
2434
int[] pattern = new int[exports.length];
2567
for (int i = 0; i < portIndex; i++) pattern[i] = i;
2568
for (int i = portIndex; i < exports.length; i++) pattern[i] = i + 1;
2435
for (int i = 0; i < portIndex; i++) {
2438
for (int i = portIndex; i < exports.length; i++) {
2569
2441
updatePortInsts(pattern);
2570
2442
// for(Iterator<NodeInst> it = getInstancesOf(); it.hasNext(); )
2572
2444
// NodeInst ni = it.next();
2573
2445
// ni.removePortInst(export);
2578
* Move renamed Export in sorted exports array.
2579
* @param oldPortIndex old position of the Export in exports array.
2581
void moveExport(int oldPortIndex, String newName)
2583
Export export = exports[oldPortIndex];
2584
int newPortIndex = - searchExport(newName) - 1;
2585
if (newPortIndex < 0) return;
2586
if (newPortIndex > oldPortIndex)
2588
if (newPortIndex == oldPortIndex) return;
2590
if (newPortIndex > oldPortIndex)
2592
for (int i = oldPortIndex; i < newPortIndex; i++)
2594
Export e = exports[i + 1];
2600
for (int i = oldPortIndex; i > newPortIndex; i--)
2602
Export e = exports[i - 1];
2607
export.setPortIndex(newPortIndex);
2608
exports[newPortIndex] = export;
2450
* Move renamed Export in sorted exports array.
2451
* @param oldPortIndex old position of the Export in exports array.
2453
void moveExport(int oldPortIndex, String newName) {
2454
Export export = exports[oldPortIndex];
2455
int newPortIndex = -searchExport(newName) - 1;
2456
if (newPortIndex < 0) {
2459
if (newPortIndex > oldPortIndex) {
2462
if (newPortIndex == oldPortIndex) {
2466
if (newPortIndex > oldPortIndex) {
2467
for (int i = oldPortIndex; i < newPortIndex; i++) {
2468
Export e = exports[i + 1];
2473
for (int i = oldPortIndex; i > newPortIndex; i--) {
2474
Export e = exports[i - 1];
2479
export.setPortIndex(newPortIndex);
2480
exports[newPortIndex] = export;
2610
2482
// move PortInst for every instance of this Cell.
2611
if (getId().numUsagesOf() == 0) return;
2483
if (getId().numUsagesOf() == 0) {
2612
2486
int[] pattern = new int[exports.length];
2613
for (int i = 0; i < pattern.length; i++) pattern[i] = i;
2487
for (int i = 0; i < pattern.length; i++) {
2614
2490
pattern[newPortIndex] = oldPortIndex;
2615
if (newPortIndex > oldPortIndex)
2616
for (int i = oldPortIndex; i < newPortIndex; i++) pattern[i] = i + 1;
2618
for (int i = oldPortIndex; i > newPortIndex; i--) pattern[i] = i - 1;
2491
if (newPortIndex > oldPortIndex) {
2492
for (int i = oldPortIndex; i < newPortIndex; i++) {
2496
for (int i = oldPortIndex; i > newPortIndex; i--) {
2619
2500
updatePortInsts(pattern);
2623
* Update PortInsts of all instances of this Cell accoding to pattern.
2504
* Update PortInsts of all instances of this Cell accoding to pattern.
2624
2505
* Pattern contains an element for each Export.
2625
2506
* If Export was just created, the element contains -1.
2626
2507
* For old Exports the element contains old index of the Export.
2627
* @param pattern array with elements describing new PortInsts.
2508
* @param pattern array with elements describing new PortInsts.
2629
2510
public void updatePortInsts(int[] pattern) {
2630
for(Iterator<NodeInst> it = getInstancesOf(); it.hasNext(); ) {
2631
NodeInst ni = it.next();
2632
ni.updatePortInsts(pattern);
2511
for (Iterator<CellUsage> it = getUsagesOf(); it.hasNext(); ) {
2512
CellUsage cu = it.next();
2513
Cell parentCell = cu.getParent(database);
2514
Topology topology = parentCell.getTopologyOptional();
2515
if (topology != null) {
2516
topology.updatePortInsts(this, pattern);
2637
* Method to unlink a set of these Export from this Cell.
2522
* Method to unlink a set of these Export from this Cell.
2638
2523
* @param killedExports a set of Exports to kill.
2640
public void killExports(Set<Export> killedExports) {
2642
if (killedExports.isEmpty()) return;
2643
for (Export export: killedExports) {
2644
if (export.getParent() != this)
2525
public void killExports(Set<Export> killedExports) {
2527
if (killedExports.isEmpty()) {
2530
for (Export export : killedExports) {
2531
if (export.getParent() != this) {
2645
2532
throw new IllegalArgumentException("parent");
2648
2536
Export[] killedExportsArray = killedExports.toArray(new Export[killedExports.size()]);
2649
for (Iterator<CellUsage> uit = getUsagesOf(); uit.hasNext(); ) {
2537
for (Iterator<CellUsage> uit = getUsagesOf(); uit.hasNext();) {
2650
2538
CellUsage u = uit.next();
2651
2539
Cell higherCell = database.getCell(u.parentId);
2653
2541
// collect the arcs attached to the connections to these port instance.
2654
2542
List<ArcInst> arcsToKill = new ArrayList<ArcInst>();
2655
for (Iterator<ArcInst> ait = higherCell.getArcs(); ait.hasNext(); ) {
2543
for (Iterator<ArcInst> ait = higherCell.getArcs(); ait.hasNext();) {
2656
2544
ArcInst ai = ait.next();
2657
2545
PortInst tail = ai.getTailPortInst();
2658
2546
PortInst head = ai.getHeadPortInst();
2659
if (tail.getNodeInst().getProto() == this && killedExports.contains(tail.getPortProto()) ||
2660
head.getNodeInst().getProto() == this && killedExports.contains(head.getPortProto()))
2547
if (tail.getNodeInst().getProto() == this && killedExports.contains(tail.getPortProto())
2548
|| head.getNodeInst().getProto() == this && killedExports.contains(head.getPortProto())) {
2661
2549
arcsToKill.add(ai);
2663
2552
// collect reexports
2664
2553
Set<Export> higherExportsToKill = null;
2665
for (Export higherExport: higherCell.exports) {
2554
for (Export higherExport : higherCell.exports) {
2666
2555
PortInst pi = higherExport.getOriginalPort();
2667
if (pi.getNodeInst().getProto() != this) continue;
2668
Export lowerExport = (Export)pi.getPortProto();
2556
if (pi.getNodeInst().getProto() != this) {
2559
Export lowerExport = (Export) pi.getPortProto();
2669
2560
assert lowerExport.getParent() == this;
2670
if (!killedExports.contains(lowerExport)) continue;
2671
if (higherExportsToKill == null) higherExportsToKill = new HashSet<Export>();
2561
if (!killedExports.contains(lowerExport)) {
2564
if (higherExportsToKill == null) {
2565
higherExportsToKill = new HashSet<Export>();
2672
2567
higherExportsToKill.add(higherExport);
2675
2570
// delete variables on port instances
2676
for (NodeInst ni: higherCell.nodes) {
2677
if (ni.getProto() != this) continue;
2678
for (Export e: killedExportsArray)
2571
for (Iterator<NodeInst> it = higherCell.getNodes(); it.hasNext();) {
2572
NodeInst ni = it.next();
2573
if (ni.getProto() != this) {
2576
for (Export e : killedExportsArray) {
2679
2577
ni.findPortInstFromProto(e).delVars();
2681
2580
// delete connected arcs
2682
for (ArcInst ai: arcsToKill)
2581
for (ArcInst ai : arcsToKill) {
2684
// recurse up the hierarchy deleting rexports
2685
if (higherExportsToKill != null)
2584
// recurse up the hierarchy deleting rexports
2585
if (higherExportsToKill != null) {
2686
2586
higherCell.killExports(higherExportsToKill);
2689
2590
// kill exports themselves
2690
for (Export e: killedExports) {
2591
for (Export e : killedExports) {
2691
2592
assert e.isLinked();
2692
2593
NodeInst originalNode = e.getOriginalPort().getNodeInst();
2693
2594
originalNode.redoGeometric();
2694
2595
removeExport(e);
2695
// handle change control, constraint, and broadcast
2696
Constraints.getCurrent().killObject(e);
2596
// handle change control, constraint, and broadcast
2597
Constraints.getCurrent().killObject(e);
2701
* Method to recursively alter the state bit fields of these Exports.
2602
* Method to recursively alter the state bit fields of these Exports.
2702
2603
* @param changedExports changed exports of this Cell.
2704
void recursivelyChangeAllPorts(Set<Export> changedExports) {
2705
// look at all usages of this cell
2706
for (Iterator<CellUsage> cit = getUsagesOf(); cit.hasNext(); ) {
2605
void recursivelyChangeAllPorts(Set<Export> changedExports) {
2606
// look at all usages of this cell
2607
for (Iterator<CellUsage> cit = getUsagesOf(); cit.hasNext();) {
2707
2608
CellUsage u = cit.next();
2708
2609
Cell higherCell = database.getCell(u.parentId);
2709
2610
Set<Export> changedHigherExports = null;
2710
2611
// see reexports of these ports
2711
for (Export higherExport: higherCell.exports) {
2612
for (Export higherExport : higherCell.exports) {
2712
2613
PortInst pi = higherExport.getOriginalPort();
2713
if (pi.getNodeInst().getProto() != this) continue;
2714
Export lowerExport = (Export)pi.getPortProto();
2614
if (pi.getNodeInst().getProto() != this) {
2617
Export lowerExport = (Export) pi.getPortProto();
2715
2618
assert lowerExport.getParent() == this;
2716
if (!changedExports.contains(lowerExport)) continue;
2717
if (changedHigherExports == null) changedHigherExports = new HashSet<Export>();
2619
if (!changedExports.contains(lowerExport)) {
2622
if (changedHigherExports == null) {
2623
changedHigherExports = new HashSet<Export>();
2718
2625
changedHigherExports.add(higherExport);
2720
2627
higherExport.copyStateBits(lowerExport);
2722
// recurse up the hierarchy
2723
if (changedHigherExports != null)
2629
// recurse up the hierarchy
2630
if (changedHigherExports != null) {
2724
2631
higherCell.recursivelyChangeAllPorts(changedHigherExports);
2729
* Method to find the PortProto that has a particular name.
2730
* @return the PortProto, or null if there is no PortProto with that name.
2732
public PortProto findPortProto(String name)
2734
if (name == null) return null;
2735
return findPortProto(Name.findName(name));
2739
* Method to find the PortProto that has a particular Name.
2740
* @return the PortProto, or null if there is no PortProto with that name.
2637
* Method to find the PortProto that has a particular name.
2638
* @return the PortProto, or null if there is no PortProto with that name.
2640
public PortProto findPortProto(String name) {
2644
return findPortProto(Name.findName(name));
2648
* Method to find the PortProto that has a particular Name.
2649
* @return the PortProto, or null if there is no PortProto with that name.
2742
2651
public PortProto findPortProto(Name name) {
2743
if (name == null) return null;
2744
2655
int portIndex = searchExport(name.toString());
2745
if (portIndex >= 0) return exports[portIndex];
2656
if (portIndex >= 0) {
2657
return exports[portIndex];
2746
2659
// String nameString = name.canonicString();
2747
2660
// for (int i = 0; i < exports.length; i++) {
2748
2661
// Export e = exports[i];
2845
2764
* that this guarantees that the return value will be >= 0 if
2846
2765
* and only if the Export is found.
2848
private int searchExport(String name)
2851
int high = exports.length-1;
2853
while (low <= high) {
2854
int mid = (low + high) >> 1;
2855
Export e = exports[mid];
2856
int cmp = TextUtils.STRING_NUMBER_ORDER.compare(e.getName(), name);
2863
return mid; // Export found
2865
return -(low + 1); // Export not found.
2868
/****************************** TEXT ******************************/
2871
* Method to return the CellName object describing this Cell.
2872
* @return the CellName object describing this Cell.
2874
public CellName getCellName() { return getD().cellId.cellName; }
2877
* Method to return the pure name of this Cell, without
2878
* any view or version information.
2879
* @return the pure name of this Cell.
2881
public String getName() { return getCellName().getName(); }
2884
* Method to describe this cell.
2885
* The description has the form: cell;version{view}
2886
* If the cell is not from the current library, prepend the library name.
2767
private int searchExport(String name) {
2769
int high = exports.length - 1;
2771
while (low <= high) {
2772
int mid = (low + high) >> 1;
2773
Export e = exports[mid];
2774
int cmp = TextUtils.STRING_NUMBER_ORDER.compare(e.getName(), name);
2778
} else if (cmp > 0) {
2781
return mid; // Export found
2784
return -(low + 1); // Export not found.
2787
/****************************** TEXT ******************************/
2789
* Method to return the CellName object describing this Cell.
2790
* @return the CellName object describing this Cell.
2792
public CellName getCellName() {
2793
return getD().cellId.cellName;
2797
* Method to return the pure name of this Cell, without
2798
* any view or version information.
2799
* @return the pure name of this Cell.
2801
public String getName() {
2802
return getCellName().getName();
2806
* Method to describe this cell.
2807
* The description has the form: cell;version{view}
2808
* If the cell is not from the current library, prepend the library name.
2887
2809
* @param withQuotes to wrap description between quotes
2888
* @return a String that describes this cell.
2890
public String describe(boolean withQuotes)
2893
if (lib != Library.getCurrent())
2894
name += lib.getName() + ":";
2895
name += noLibDescribe();
2896
return (withQuotes) ? "'"+name+"'" : name;
2810
* @return a String that describes this cell.
2812
public String describe(boolean withQuotes) {
2814
if (lib != Library.getCurrent()) {
2815
name += lib.getName() + ":";
2817
name += noLibDescribe();
2818
return (withQuotes) ? "'" + name + "'" : name;
2900
2822
* Method to describe this cell.
2901
2823
* The description has the form: Library:cell;version{view}
2902
2824
* @return a String that describes this cell.
2904
public String libDescribe()
2826
public String libDescribe() {
2906
2827
return (lib.getName() + ":" + noLibDescribe());
2910
* Method to describe this cell.
2911
* The description has the form: cell;version{view}
2912
* Unlike "describe()", this method never prepends the library name.
2913
* @return a String that describes this cell.
2915
public String noLibDescribe()
2917
String name = getName();
2918
if (getNewestVersion() != this)
2919
name += ";" + getVersion();
2920
name += getView().getAbbreviationExtension();
2925
* Method to find the NodeProto with the given name.
2926
* This can be a PrimitiveNode (and can be prefixed by a Technology name),
2927
* or it can be a Cell (and be prefixed by a Library name).
2928
* @param line the name of the NodeProto.
2929
* @return the specified NodeProto, or null if none can be found.
2931
public static NodeProto findNodeProto(String line)
2933
Technology tech = Technology.getCurrent();
2934
Library lib = Library.getCurrent();
2935
boolean saidtech = false;
2936
boolean saidlib = false;
2937
int colon = line.indexOf(':');
2938
String withoutPrefix;
2939
if (colon == -1) withoutPrefix = line; else
2941
String prefix = line.substring(0, colon);
2942
Technology t = Technology.findTechnology(prefix);
2948
Library l = Library.findLibrary(prefix);
2954
withoutPrefix = line.substring(colon+1);
2957
/* try primitives in the technology */
2960
PrimitiveNode np = tech.findNodeProto(withoutPrefix);
2961
if (np != null) return np;
2964
if (!saidtech && lib != null)
2966
Cell np = lib.findNodeProto(withoutPrefix);
2967
if (np != null) return np;
2973
* Method to get the strings in this Cell.
2974
* It is only valid for cells with "text" views (documentation, vhdl, netlist, etc.)
2975
* @return the strings in this Cell.
2976
* Returns null if there are no strings.
2978
public String [] getTextViewContents()
2980
// look on the cell for its text
2981
Variable var = getVar(Cell.CELL_TEXT_KEY);
2982
if (var == null) return null;
2983
Object obj = var.getObject();
2984
if (!(obj instanceof String[])) return null;
2985
return (String [])obj;
2989
* Method to set the strings in this Cell.
2990
* It is only valid for cells with "text" views (documentation, vhdl, netlist, etc.)
2991
* The call needs to be wrapped inside of a Job.
2992
* @param strings an array of Strings that define this Cell.
2994
public void setTextViewContents(String [] strings)
2997
newVar(Cell.CELL_TEXT_KEY, strings);
2831
* Method to describe this cell.
2832
* The description has the form: cell;version{view}
2833
* Unlike "describe()", this method never prepends the library name.
2834
* @return a String that describes this cell.
2836
public String noLibDescribe() {
2837
String name = getName();
2838
if (getNewestVersion() != this) {
2839
name += ";" + getVersion();
2841
name += getView().getAbbreviationExtension();
2846
* Method to find the NodeProto with the given name.
2847
* This can be a PrimitiveNode (and can be prefixed by a Technology name),
2848
* or it can be a Cell (and be prefixed by a Library name).
2849
* @param line the name of the NodeProto.
2850
* @return the specified NodeProto, or null if none can be found.
2852
public static NodeProto findNodeProto(String line) {
2853
Technology tech = Technology.getCurrent();
2854
Library lib = Library.getCurrent();
2855
boolean saidtech = false;
2856
boolean saidlib = false;
2857
int colon = line.indexOf(':');
2858
String withoutPrefix;
2860
withoutPrefix = line;
2862
String prefix = line.substring(0, colon);
2863
Technology t = Technology.findTechnology(prefix);
2868
Library l = Library.findLibrary(prefix);
2873
withoutPrefix = line.substring(colon + 1);
2876
/* try primitives in the technology */
2878
PrimitiveNode np = tech.findNodeProto(withoutPrefix);
2884
if (!saidtech && lib != null) {
2885
Cell np = lib.findNodeProto(withoutPrefix);
2894
* Method to get the strings in this Cell.
2895
* It is only valid for cells with "text" views (documentation, vhdl, netlist, etc.)
2896
* @return the strings in this Cell.
2897
* Returns null if there are no strings.
2899
public String[] getTextViewContents() {
2900
// look on the cell for its text
2901
Variable var = getVar(Cell.CELL_TEXT_KEY);
2905
Object obj = var.getObject();
2906
if (!(obj instanceof String[])) {
2909
return (String[]) obj;
2913
* Method to set the strings in this Cell.
2914
* It is only valid for cells with "text" views (documentation, vhdl, netlist, etc.)
2915
* The call needs to be wrapped inside of a Job.
2916
* @param strings an array of Strings that define this Cell.
2918
public void setTextViewContents(String[] strings) {
2920
newVar(Cell.CELL_TEXT_KEY, strings);
3001
2924
* Method to return the Variable on this Cell with the given key
3095
3025
private void setParams(Cell paramOwner) {
3096
for (Iterator<Variable> it = getParameters(); it.hasNext(); ) {
3097
delParam((Variable.AttrKey)it.next().getKey());
3026
for (Iterator<Variable> it = getParameters(); it.hasNext();) {
3027
delParam((Variable.AttrKey) it.next().getKey());
3099
for (Iterator<Variable> it = paramOwner.getParameters(); it.hasNext(); ) {
3029
for (Iterator<Variable> it = paramOwner.getParameters(); it.hasNext();) {
3100
3030
Variable param = it.next();
3101
3031
addParam(param);
3106
* Method to return a list of Polys that describes all text on this Cell.
3107
* @param hardToSelect is true if considering hard-to-select text.
3108
* @param wnd the window in which the text will be drawn.
3109
* @return an array of Polys that describes the text.
3111
public Poly [] getAllText(boolean hardToSelect, EditWindow0 wnd) {
3112
return getDisplayableVariables(CENTERRECT, wnd, false);
3116
* Method to return the bounds of all relative text in this Cell.
3117
* This is used when displaying "full screen" because the text may grow to
3118
* be larger than the actual cell contents.
3119
* Only relative (scalable) text is considered, since it is not possible
3120
* to change the size of absolute text.
3121
* @param wnd the EditWindow0 in which this Cell is being displayed.
3122
* @return the bounds of the relative (scalable) text.
3124
public Rectangle2D getRelativeTextBounds(EditWindow0 wnd)
3126
Rectangle2D bounds = null;
3127
for(Iterator<NodeInst> it = this.getNodes(); it.hasNext(); )
3129
NodeInst ni = it.next();
3130
bounds = accumulateTextBoundsOnObject(ni, bounds, wnd);
3131
for(Iterator<PortInst> pIt = ni.getPortInsts(); pIt.hasNext(); )
3133
PortInst pi = pIt.next();
3134
bounds = accumulateTextBoundsOnObject(pi, bounds, wnd);
3137
for(Iterator<ArcInst> it = this.getArcs(); it.hasNext(); )
3139
ArcInst ai = it.next();
3140
bounds = accumulateTextBoundsOnObject(ai, bounds, wnd);
3142
for(Iterator<Export> it = this.getExports(); it.hasNext(); )
3144
Export pp = it.next();
3145
bounds = accumulateTextBoundsOnObject(pp, bounds, wnd);
3147
bounds = accumulateTextBoundsOnObject(this, bounds, wnd);
3151
private Rectangle2D accumulateTextBoundsOnObject(ElectricObject eObj, Rectangle2D bounds, EditWindow0 wnd)
3153
Rectangle2D objBounds = eObj.getTextBounds(wnd);
3154
if (objBounds == null) return bounds;
3155
if (bounds == null) return objBounds;
3156
Rectangle2D.union(bounds, objBounds, bounds);
3161
* Method to return the basename for autonaming instances of this Cell.
3162
* @return the basename for autonaming instances of this Cell.
3164
public Name getBasename() {
3165
String protoName = getName();
3166
Name basename = Name.findName(protoName.substring(0,Math.min(ABBREVLEN,protoName.length()))+"@0").getBasename();
3167
if (basename == null)
3168
basename = PrimitiveNode.Function.UNKNOWN.getBasename();
3036
* Method to return a list of Polys that describes all text on this Cell.
3037
* @param hardToSelect is true if considering hard-to-select text.
3038
* @param wnd the window in which the text will be drawn.
3039
* @return an array of Polys that describes the text.
3041
public Poly[] getAllText(boolean hardToSelect, EditWindow0 wnd) {
3042
return getDisplayableVariables(CENTERRECT, wnd, false);
3046
* Method to return the bounds of all relative text in this Cell.
3047
* This is used when displaying "full screen" because the text may grow to
3048
* be larger than the actual cell contents.
3049
* Only relative (scalable) text is considered, since it is not possible
3050
* to change the size of absolute text.
3051
* @param wnd the EditWindow0 in which this Cell is being displayed.
3052
* @return the bounds of the relative (scalable) text.
3054
public Rectangle2D getRelativeTextBounds(EditWindow0 wnd) {
3055
Rectangle2D bounds = null;
3056
for (Iterator<NodeInst> it = this.getNodes(); it.hasNext();) {
3057
NodeInst ni = it.next();
3058
bounds = accumulateTextBoundsOnObject(ni, bounds, wnd);
3059
for (Iterator<PortInst> pIt = ni.getPortInsts(); pIt.hasNext();) {
3060
PortInst pi = pIt.next();
3061
bounds = accumulateTextBoundsOnObject(pi, bounds, wnd);
3064
for (Iterator<ArcInst> it = this.getArcs(); it.hasNext();) {
3065
ArcInst ai = it.next();
3066
bounds = accumulateTextBoundsOnObject(ai, bounds, wnd);
3068
for (Iterator<Export> it = this.getExports(); it.hasNext();) {
3069
Export pp = it.next();
3070
bounds = accumulateTextBoundsOnObject(pp, bounds, wnd);
3072
bounds = accumulateTextBoundsOnObject(this, bounds, wnd);
3076
private Rectangle2D accumulateTextBoundsOnObject(ElectricObject eObj, Rectangle2D bounds, EditWindow0 wnd) {
3077
Rectangle2D objBounds = eObj.getTextBounds(wnd);
3078
if (objBounds == null) {
3081
if (bounds == null) {
3084
Rectangle2D.union(bounds, objBounds, bounds);
3089
* Method to return the basename for autonaming instances of this Cell.
3090
* @return the basename for autonaming instances of this Cell.
3092
public Name getBasename() {
3093
String protoName = getName();
3094
Name basename = Name.findName(protoName.substring(0, Math.min(ABBREVLEN, protoName.length())) + "@0").getBasename();
3095
if (basename == null) {
3096
basename = PrimitiveNode.Function.UNKNOWN.getBasename();
3169
3098
return basename;
3173
* Method to determine the index value which, when appended to a given string,
3174
* will generate a unique name in this Cell.
3175
* @param prefix the start of the string.
3176
* @param cls the type of object being examined.
3177
* @param startingIndex the starting value to append to the string.
3178
* @return a value that, when appended to the prefix, forms a unique name in the cell.
3180
public int getUniqueNameIndex(String prefix, Class cls, int startingIndex)
3182
int len = prefix.length();
3183
int uniqueIndex = startingIndex;
3184
if (cls == PortProto.class)
3186
for(Iterator<PortProto> it = getPorts(); it.hasNext(); )
3188
PortProto pp = it.next();
3189
if (pp.getName().startsWith(prefix))
3190
// if (TextUtils.startsWithIgnoreCase(pp.getName(), prefix))
3192
String restOfName = pp.getName().substring(len);
3193
if (TextUtils.isANumber(restOfName))
3195
int indexVal = TextUtils.atoi(restOfName);
3196
if (indexVal >= uniqueIndex) uniqueIndex = indexVal + 1;
3200
} else if (cls == NodeInst.class)
3202
for(Iterator<NodeInst> it = getNodes(); it.hasNext(); )
3204
NodeInst ni = it.next();
3205
if (ni.getName().startsWith(prefix))
3206
// if (TextUtils.startsWithIgnoreCase(ni.getName(), prefix))
3208
String restOfName = ni.getName().substring(len);
3209
if (TextUtils.isANumber(restOfName))
3211
int indexVal = TextUtils.atoi(restOfName);
3212
if (indexVal >= uniqueIndex) uniqueIndex = indexVal + 1;
3216
} else if (cls == ArcInst.class)
3218
for(Iterator<ArcInst> it = getArcs(); it.hasNext(); )
3220
ArcInst ai = it.next();
3221
if (ai.getName().startsWith(prefix))
3222
// if (TextUtils.startsWithIgnoreCase(ai.getName(), prefix))
3224
String restOfName = ai.getName().substring(len);
3225
if (TextUtils.isANumber(restOfName))
3227
int indexVal = TextUtils.atoi(restOfName);
3228
if (indexVal >= uniqueIndex) uniqueIndex = indexVal + 1;
3237
* Method to determine whether a name is unique in this Cell.
3238
* @param name the Name being tested to see if it is unique.
3239
* @param cls the type of object being examined.
3240
* The only classes that can be examined are PortProto, NodeInst, and ArcInst.
3241
* @param exclude an object that should not be considered in this test (null to ignore the exclusion).
3242
* @return true if the name is unique in the Cell. False if it already exists.
3244
public boolean isUniqueName(String name, Class cls, ElectricObject exclude)
3246
return isUniqueName(Name.findName(name), cls, exclude);
3250
* Method to determine whether a name is unique in this Cell.
3251
* @param name the Name being tested to see if it is unique.
3252
* @param cls the type of object being examined.
3253
* The only classes that can be examined are PortProto, NodeInst, and ArcInst.
3254
* @param exclude an object that should not be considered in this test (null to ignore the exclusion).
3255
* @return true if the name is unique in the Cell. False if it already exists.
3257
public boolean isUniqueName(Name name, Class cls, ElectricObject exclude)
3102
* Method to determine the index value which, when appended to a given string,
3103
* will generate a unique name in this Cell.
3104
* @param prefix the start of the string.
3105
* @param cls the type of object being examined.
3106
* @param startingIndex the starting value to append to the string.
3107
* @return a value that, when appended to the prefix, forms a unique name in the cell.
3109
public int getUniqueNameIndex(String prefix, Class cls, int startingIndex) {
3110
int len = prefix.length();
3111
int uniqueIndex = startingIndex;
3112
if (cls == PortProto.class) {
3113
for (Iterator<PortProto> it = getPorts(); it.hasNext();) {
3114
PortProto pp = it.next();
3115
if (pp.getName().startsWith(prefix)) // if (TextUtils.startsWithIgnoreCase(pp.getName(), prefix))
3117
String restOfName = pp.getName().substring(len);
3118
if (TextUtils.isANumber(restOfName)) {
3119
int indexVal = TextUtils.atoi(restOfName);
3120
if (indexVal >= uniqueIndex) {
3121
uniqueIndex = indexVal + 1;
3126
} else if (cls == NodeInst.class) {
3127
for (Iterator<NodeInst> it = getNodes(); it.hasNext();) {
3128
NodeInst ni = it.next();
3129
if (ni.getName().startsWith(prefix)) // if (TextUtils.startsWithIgnoreCase(ni.getName(), prefix))
3131
String restOfName = ni.getName().substring(len);
3132
if (TextUtils.isANumber(restOfName)) {
3133
int indexVal = TextUtils.atoi(restOfName);
3134
if (indexVal >= uniqueIndex) {
3135
uniqueIndex = indexVal + 1;
3140
} else if (cls == ArcInst.class) {
3141
for (Iterator<ArcInst> it = getArcs(); it.hasNext();) {
3142
ArcInst ai = it.next();
3143
if (ai.getName().startsWith(prefix)) // if (TextUtils.startsWithIgnoreCase(ai.getName(), prefix))
3145
String restOfName = ai.getName().substring(len);
3146
if (TextUtils.isANumber(restOfName)) {
3147
int indexVal = TextUtils.atoi(restOfName);
3148
if (indexVal >= uniqueIndex) {
3149
uniqueIndex = indexVal + 1;
3159
* Method to determine whether a name is unique in this Cell.
3160
* @param name the Name being tested to see if it is unique.
3161
* @param cls the type of object being examined.
3162
* The only classes that can be examined are PortProto, NodeInst, and ArcInst.
3163
* @param exclude an object that should not be considered in this test (null to ignore the exclusion).
3164
* @return true if the name is unique in the Cell. False if it already exists.
3166
public boolean isUniqueName(String name, Class cls, ElectricObject exclude) {
3167
return isUniqueName(Name.findName(name), cls, exclude);
3171
* Method to determine whether a name is unique in this Cell.
3172
* @param name the Name being tested to see if it is unique.
3173
* @param cls the type of object being examined.
3174
* The only classes that can be examined are PortProto, NodeInst, and ArcInst.
3175
* @param exclude an object that should not be considered in this test (null to ignore the exclusion).
3176
* @return true if the name is unique in the Cell. False if it already exists.
3178
public boolean isUniqueName(Name name, Class cls, ElectricObject exclude) {
3259
3179
// name = name.canonic();
3260
if (cls == PortProto.class)
3262
PortProto pp = findExport(name);
3263
if (pp == null || exclude == pp) return true;
3266
if (cls == NodeInst.class)
3180
if (cls == PortProto.class) {
3181
PortProto pp = findExport(name);
3182
if (pp == null || exclude == pp) {
3187
if (cls == NodeInst.class) {
3268
3188
NodeInst ni = findNode(name.toString());
3269
3189
return (ni == null || exclude == ni);
3271
if (cls == ArcInst.class)
3191
if (cls == ArcInst.class) {
3273
3192
ArcInst ai = findArc(name.toString());
3274
3193
return ai == null || exclude == ai;
3275
3194
// String nameString = name.canonicString();
3837
3815
// setCellGroup(null);
3841
* Method to put this Cell together with all its versions and views into the given CellGroup.
3842
* @param cellGroup the CellGroup that this cell belongs to or null to put int own cell group
3844
public void setCellGroup(CellGroup cellGroup)
3846
if (!isLinked()) return;
3818
* Method to put this Cell together with all its versions and views into the given CellGroup.
3819
* @param cellGroup the CellGroup that this cell belongs to or null to put int own cell group
3821
public void setCellGroup(CellGroup cellGroup) {
3847
3825
// CellGroup oldCellGroup = this.cellGroup;
3848
if (cellGroup == null) cellGroup = new CellGroup(lib);
3826
if (cellGroup == null) {
3827
cellGroup = new CellGroup(lib);
3849
3829
checkChanging();
3850
if (cellGroup == this.cellGroup) return;
3830
if (cellGroup == this.cellGroup) {
3851
3833
database.unfreshSnapshot();
3852
3834
lib.setChanged();
3853
String protoName = getName();
3854
for (Iterator<Cell> it = getViewsTail(); it.hasNext(); )
3856
Cell cell = it.next();
3857
if (!cell.getName().equals(protoName)) break;
3858
cell.cellGroup.remove(cell);
3859
cellGroup.add(cell);
3835
String protoName = getName();
3836
for (Iterator<Cell> it = getViewsTail(); it.hasNext();) {
3837
Cell cell = it.next();
3838
if (!cell.getName().equals(protoName)) {
3841
cell.cellGroup.remove(cell);
3842
cellGroup.add(cell);
3861
3844
// Undo.modifyCellGroup(this, oldCellGroup);
3864
/****************************** VIEWS ******************************/
3867
* Method to get this Cell's View.
3868
* Views include "layout", "schematics", "icon", "netlist", etc.
3869
* @return to get this Cell's View.
3871
public View getView() { return getCellName().getView(); }
3874
* Method to change the view of this Cell.
3875
* @param newView the new View.
3877
public IdMapper setView(View newView)
3879
return rename(CellName.newName(getName(), newView, getVersion()), null);
3883
* Method to determine whether this Cell is an icon Cell.
3884
* @return true if this Cell is an icon Cell.
3886
public boolean isIcon() { return getId().isIcon(); }
3889
* Method to determine whether this Cell is an icon of another Cell.
3890
* @param cell the other cell which this may be an icon of.
3891
* @return true if this Cell is an icon of that other Cell.
3893
public boolean isIconOf(Cell cell)
3895
return isIcon() && cellGroup == cell.cellGroup && cell.isSchematic();
3899
* Method to return true if this Cell is a schematic Cell.
3900
* @return true if this Cell is a schematic Cell.
3902
public boolean isSchematic() { return getId().isSchematic(); }
3847
/****************************** VIEWS ******************************/
3849
* Method to get this Cell's View.
3850
* Views include "layout", "schematics", "icon", "netlist", etc.
3851
* @return to get this Cell's View.
3853
public View getView() {
3854
return getCellName().getView();
3858
* Method to change the view of this Cell.
3859
* @param newView the new View.
3861
public IdMapper setView(View newView) {
3862
return rename(CellName.newName(getName(), newView, getVersion()), null);
3866
* Method to determine whether this Cell is an icon Cell.
3867
* @return true if this Cell is an icon Cell.
3869
public boolean isIcon() {
3870
return getId().isIcon();
3874
* Method to determine whether this Cell is an icon of another Cell.
3875
* @param cell the other cell which this may be an icon of.
3876
* @return true if this Cell is an icon of that other Cell.
3878
public boolean isIconOf(Cell cell) {
3879
return isIcon() && cellGroup == cell.cellGroup && cell.isSchematic();
3883
* Method to return true if this Cell is a schematic Cell.
3884
* @return true if this Cell is a schematic Cell.
3886
public boolean isSchematic() {
3887
return getId().isSchematic();
3905
3891
* Method to return true if bus names are allowed in this Cell
3906
3892
* @return true if bus names are allowed in this Cell
3908
public boolean busNamesAllowed() { return getD().busNamesAllowed(); }
3894
public boolean busNamesAllowed() {
3895
return getD().busNamesAllowed();
3911
3899
* Method to return true if this Cell is a layout Cell.
3912
3900
* @return true if this Cell is a layout Cell
3914
public boolean isLayout()
3902
public boolean isLayout() {
3916
3903
View w = getView();
3917
3904
return w == View.LAYOUT || w == View.LAYOUTCOMP || w == View.LAYOUTSKEL;
3921
* Method to return the number of pages in this multi-page Cell.
3922
* @return the number of different pages.
3924
public int getNumMultiPages()
3926
if (!isMultiPage()) return 1;
3927
Rectangle2D bounds = getBounds();
3928
int numPages = (int)(bounds.getHeight() / FrameDescription.MULTIPAGESEPARATION) + 1;
3929
Integer storedCount = getVarValue(MULTIPAGE_COUNT_KEY, Integer.class);
3930
if (storedCount != null)
3932
if (storedCount.intValue() > numPages) numPages = storedCount.intValue();
3938
* Method to find the contents Cell associated with this Cell.
3939
* This only makes sense if the current Cell is an icon or skeleton Cell.
3940
* @return the contents Cell associated with this Cell.
3941
* Returns null if no such Cell can be found.
3943
public Cell contentsView()
3945
// can only consider contents if this cell is an icon
3946
if (!isIcon() && getView() != View.LAYOUTSKEL)
3949
// first check to see if there is a schematics link
3950
for(Iterator<Cell> it = getCellGroup().getCells(); it.hasNext(); )
3952
Cell cellInGroup = it.next();
3953
if (cellInGroup.isSchematic()) return cellInGroup;
3956
// now check to see if there is any layout link
3957
for(Iterator<Cell> it = getCellGroup().getCells(); it.hasNext(); )
3959
Cell cellInGroup = it.next();
3960
if (cellInGroup.getView() == View.LAYOUT) return cellInGroup;
3963
// finally check to see if there is any "unknown" link
3964
for(Iterator<Cell> it = getCellGroup().getCells(); it.hasNext(); )
3966
Cell cellInGroup = it.next();
3967
if (cellInGroup.getView() == View.UNKNOWN) return cellInGroup;
3970
// no contents found
3975
* Method to find the icon Cell associated with this Cell.
3976
* @return the icon Cell associated with this Cell.
3977
* Returns null if no such Cell can be found.
3979
public Cell iconView()
3981
// can only get icon view if this is a schematic
3982
if (!isSchematic()) return null;
3984
// now look for views
3985
for(Iterator<Cell> it = getCellGroup().getCells(); it.hasNext(); )
3987
Cell cellInGroup = it.next();
3988
if (cellInGroup.isIcon()) return cellInGroup;
3995
* Method to find the Cell of a given View that is in the same group as this Cell.
3908
* Method to return the number of pages in this multi-page Cell.
3909
* @return the number of different pages.
3911
public int getNumMultiPages() {
3912
if (!isMultiPage()) {
3915
Rectangle2D bounds = getBounds();
3916
int numPages = (int) (bounds.getHeight() / FrameDescription.MULTIPAGESEPARATION) + 1;
3917
Integer storedCount = getVarValue(MULTIPAGE_COUNT_KEY, Integer.class);
3918
if (storedCount != null) {
3919
if (storedCount.intValue() > numPages) {
3920
numPages = storedCount.intValue();
3927
* Method to find the contents Cell associated with this Cell.
3928
* This only makes sense if the current Cell is an icon or skeleton Cell.
3929
* @return the contents Cell associated with this Cell.
3930
* Returns null if no such Cell can be found.
3932
public Cell contentsView() {
3933
// can only consider contents if this cell is an icon
3934
if (!isIcon() && getView() != View.LAYOUTSKEL) {
3938
// first check to see if there is a schematics link
3939
for (Iterator<Cell> it = getCellGroup().getCells(); it.hasNext();) {
3940
Cell cellInGroup = it.next();
3941
if (cellInGroup.isSchematic()) {
3946
// now check to see if there is any layout link
3947
for (Iterator<Cell> it = getCellGroup().getCells(); it.hasNext();) {
3948
Cell cellInGroup = it.next();
3949
if (cellInGroup.getView() == View.LAYOUT) {
3954
// finally check to see if there is any "unknown" link
3955
for (Iterator<Cell> it = getCellGroup().getCells(); it.hasNext();) {
3956
Cell cellInGroup = it.next();
3957
if (cellInGroup.getView() == View.UNKNOWN) {
3962
// no contents found
3967
* Method to find the icon Cell associated with this Cell.
3968
* @return the icon Cell associated with this Cell.
3969
* Returns null if no such Cell can be found.
3971
public Cell iconView() {
3972
// can only get icon view if this is a schematic
3973
if (!isSchematic()) {
3977
// now look for views
3978
for (Iterator<Cell> it = getCellGroup().getCells(); it.hasNext();) {
3979
Cell cellInGroup = it.next();
3980
if (cellInGroup.isIcon()) {
3989
* Method to find the Cell of a given View that is in the same group as this Cell.
3996
3990
* If there is more than one cell matching the View, it will do a name match.
3997
* @param view the View of the other Cell.
3998
* @return the Cell from this group with the specified View.
3999
* Returns null if no such Cell can be found.
4001
public Cell otherView(View view)
3991
* @param view the View of the other Cell.
3992
* @return the Cell from this group with the specified View.
3993
* Returns null if no such Cell can be found.
3995
public Cell otherView(View view) {
4003
3996
Cell otherViewCell = null;
4006
for(Iterator<Cell> it = getCellGroup().getCells(); it.hasNext(); )
4008
Cell cellInGroup = it.next();
4009
if (cellInGroup.getView() == view)
3999
for (Iterator<Cell> it = getCellGroup().getCells(); it.hasNext();) {
4000
Cell cellInGroup = it.next();
4001
if (cellInGroup.getView() == view) {
4011
4002
otherViewCell = cellInGroup.getNewestVersion();
4012
4003
// Perfect match including name
4013
if (cellInGroup.getName().equals(getName()))
4014
// get latest version
4004
if (cellInGroup.getName().equals(getName())) // get latest version
4015
4006
return otherViewCell;
4019
return otherViewCell;
4022
/****************************** NETWORKS ******************************/
4024
/** Recompute the Netlist structure for this Cell whithout shortening resistors.
4025
* @return the Netlist structure for this cell.
4026
* @throws NetworkTool.NetlistNotReady if called from GUI thread and change Job hasn't prepared Netlist yet
4011
return otherViewCell;
4014
/****************************** NETWORKS ******************************/
4015
/** Recompute the Netlist structure for this Cell whithout shortening resistors.
4016
* @return the Netlist structure for this cell.
4017
* @throws NetworkTool.NetlistNotReady if called from GUI thread and change Job hasn't prepared Netlist yet
4028
public Netlist getNetlist() { return getNetlist(Netlist.ShortResistors.NO); }
4019
public Netlist getNetlist() {
4020
return getNetlist(Netlist.ShortResistors.NO);
4030
/** Recompute the Netlist structure for this Cell.
4023
/** Recompute the Netlist structure for this Cell.
4031
4024
* @param shortResistors short resistors mode of Netlist.
4032
* @return the Netlist structure for this cell.
4033
* @throws NetworkTool.NetlistNotReady if called from GUI thread and change Job hasn't prepared Netlist yet
4035
public Netlist getNetlist(Netlist.ShortResistors shortResistors) { return NetworkTool.getNetlist(this, shortResistors); }
4037
/** Returns the Netlist structure for this Cell, using current network options.
4038
* Waits for completion of change Job when called from GUI thread
4039
* @return the Netlist structure for this cell.
4041
public Netlist getUserNetlist() { return NetworkTool.getUserNetlist(this); }
4043
/** Returns the Netlist structure for this Cell, using current network options.
4044
* Returns null if change Job hasn't prepared GUI Netlist
4045
* @return the Netlist structure for this cell.
4047
public Netlist acquireUserNetlist() { return NetworkTool.acquireUserNetlist(this); }
4049
/****************************** DATES ******************************/
4052
* Method to get the creation date of this Cell.
4053
* @return the creation date of this Cell.
4055
public Date getCreationDate() { return new Date(getD().creationDate); }
4058
* Method to set this Cell's creation date.
4059
* This is a low-level method and should not be called unless you know what you are doing.
4060
* @param creationDate the date of this Cell's creation.
4062
public void lowLevelSetCreationDate(Date creationDate) { setD(getD().withCreationDate(creationDate.getTime())); }
4065
* Method to return the revision date of this Cell.
4066
* @return the revision date of this Cell.
4068
public Date getRevisionDate() { return new Date(getD().revisionDate); }
4071
* Method to set this Cell's last revision date.
4072
* This is a low-level method and should not be called unless you know what you are doing.
4073
* @param revisionDate the date of this Cell's last revision.
4075
public void lowLevelSetRevisionDate(Date revisionDate) {
4025
* @return the Netlist structure for this cell.
4026
* @throws NetworkTool.NetlistNotReady if called from GUI thread and change Job hasn't prepared Netlist yet
4028
public Netlist getNetlist(Netlist.ShortResistors shortResistors) {
4029
if (NetworkTool.isLazy()) {
4030
NetCell netCell = netCellRef.get();
4031
if (netCell == null) {
4032
netCell = NetCell.newInstance(this);
4033
setNetCellRef(netCell);
4035
return netCell.getNetlist(shortResistors);
4037
return NetworkTool.getNetlist(this, shortResistors);
4041
private void setNetCellRef(NetCell netCell) {
4042
netCellRef = USE_WEAK_REFERENCES ? new WeakReference<NetCell>(netCell) : new SoftReference<NetCell>(netCell);
4045
/** Returns the Netlist structure for this Cell, using current network options.
4046
* Waits for completion of change Job when called from GUI thread
4047
* @return the Netlist structure for this cell.
4049
public Netlist getUserNetlist() {
4050
return Job.isThreadSafe() ? getNetlist() : NetworkTool.getUserNetlist(this);
4053
/** Returns the Netlist structure for this Cell, using current network options.
4054
* Returns null if change Job hasn't prepared GUI Netlist
4055
* @return the Netlist structure for this cell.
4057
public Netlist acquireUserNetlist() {
4058
return Job.isThreadSafe() ? getNetlist() : NetworkTool.acquireUserNetlist(this);
4061
/****************************** DATES ******************************/
4063
* Method to get the creation date of this Cell.
4064
* @return the creation date of this Cell.
4066
public Date getCreationDate() {
4067
return new Date(getD().creationDate);
4071
* Method to set this Cell's creation date.
4072
* This is a low-level method and should not be called unless you know what you are doing.
4073
* @param creationDate the date of this Cell's creation.
4075
public void lowLevelSetCreationDate(Date creationDate) {
4076
setD(getD().withCreationDate(creationDate.getTime()));
4080
* Method to return the revision date of this Cell.
4081
* @return the revision date of this Cell.
4083
public Date getRevisionDate() {
4084
return new Date(getD().revisionDate);
4088
* Method to set this Cell's last revision date.
4089
* This is a low-level method and should not be called unless you know what you are doing.
4090
* @param revisionDate the date of this Cell's last revision.
4092
public void lowLevelSetRevisionDate(Date revisionDate) {
4076
4093
lowLevelSetRevisionDate(revisionDate.getTime());
4080
* Method to set this Cell's revision date and user name.
4097
* Method to set this Cell's revision date and user name.
4081
4098
* Change system is not informed about this.
4082
* This is a low-level method and should not be called unless you know what you are doing.
4084
public void lowLevelMadeRevision(long revisionDate, String userName, CellRevision oldRevision) {
4099
* This is a low-level method and should not be called unless you know what you are doing.
4101
public void lowLevelMadeRevision(long revisionDate, String userName, CellRevision oldRevision) {
4086
if (!isModified() || backup.cellRevision == oldRevision || revisionDateFresh)
4103
if (!isModified() || backup.cellRevision == oldRevision || revisionDateFresh) {
4088
4106
lowLevelSetRevisionDate(revisionDate);
4091
private void lowLevelSetRevisionDate(long revisionDate) {
4109
private void lowLevelSetRevisionDate(long revisionDate) {
4092
4110
backup = backup().withRevisionDate(revisionDate);
4093
4111
d = backup.cellRevision.d;
4094
4112
revisionDateFresh = true;
4095
4114
database.unfreshSnapshot();
4099
* Method to check the current cell to be sure that no subcells have a more recent date.
4100
* This is invoked when the "Check cell dates" feature is enabled in the New Nodes tab of
4101
* the Edit Options dialog.
4103
public void checkCellDates()
4105
Set<Cell> cellsChecked = new HashSet<Cell>();
4106
checkCellDate(getRevisionDate(), cellsChecked);
4110
* Recursive method to check sub-cell revision times.
4111
* @param rev_time the revision date of the top-level cell.
4112
* Nothing below it can be newer.
4114
private void checkCellDate(Date rev_time, Set<Cell> cellsChecked)
4116
for(Iterator<NodeInst> it = getNodes(); it.hasNext(); )
4118
NodeInst ni = it.next();
4119
if (!ni.isCellInstance()) continue;
4120
Cell subCell = (Cell)ni.getProto();
4122
// ignore recursive references (showing icon in contents)
4123
if (subCell.isIconOf(this)) continue;
4124
if (!cellsChecked.contains(subCell))
4126
subCell.checkCellDate(rev_time, cellsChecked); // recurse
4129
Cell contentsCell = subCell.contentsView();
4130
if (contentsCell != null)
4132
if (!cellsChecked.contains(contentsCell))
4134
contentsCell.checkCellDate(rev_time, cellsChecked); // recurse
4140
cellsChecked.add(this); // flag that we have seen this one
4141
if (!getRevisionDate().after(rev_time)) return;
4143
// possible error in hierarchy
4144
System.out.println("WARNING: sub-cell " + this +
4145
" has been edited since the last revision to the current cell");
4148
/****************************** MISCELLANEOUS ******************************/
4150
private int getFlags() { return d.flags; }
4152
private boolean isFlag(int mask) { return (getFlags() & mask) != 0; }
4154
private void setFlag(int mask, boolean value) { lowLevelSetUserbits(value ? getFlags() | mask : getFlags() & ~mask); }
4157
* Method to set this Cell so that instances of it are "expanded" by when created.
4158
* Expanded NodeInsts are instances of Cells that show their contents.
4160
public void setWantExpanded() { setFlag(WANTNEXPAND, true); }
4163
* Method to set this Cell so that instances of it are "not expanded" by when created.
4164
* Expanded NodeInsts are instances of Cells that show their contents.
4166
public void clearWantExpanded() { setFlag(WANTNEXPAND, false); }
4169
* Method to tell if instances of it are "expanded" by when created.
4170
* Expanded NodeInsts are instances of Cells that show their contents.
4171
* @return true if instances of it are "expanded" by when created.
4173
public boolean isWantExpanded() { return isFlag(WANTNEXPAND) || isIcon(); }
4176
* Method to return the function of this Cell.
4177
* The Function of CELL is alway UNKNOWN.
4178
* @return the function of this Cell.
4180
public PrimitiveNode.Function getFunction() { return PrimitiveNode.Function.UNKNOWN; }
4183
* Method to set this Cell so that everything inside of it is locked.
4184
* Locked instances cannot be moved or deleted.
4186
public void setAllLocked() { setFlag(NPLOCKED, true); }
4189
* Method to set this Cell so that everything inside of it is not locked.
4190
* Locked instances cannot be moved or deleted.
4192
public void clearAllLocked() { setFlag(NPLOCKED, false); }
4195
* Method to tell if the contents of this Cell are locked.
4196
* Locked instances cannot be moved or deleted.
4197
* @return true if the contents of this Cell are locked.
4199
public boolean isAllLocked() { return isFlag(NPLOCKED); }
4202
* Method to set this Cell so that all instances inside of it are locked.
4203
* Locked instances cannot be moved or deleted.
4205
public void setInstancesLocked() { setFlag(NPILOCKED, true); }
4208
* Method to set this Cell so that all instances inside of it are not locked.
4209
* Locked instances cannot be moved or deleted.
4211
public void clearInstancesLocked() { setFlag(NPILOCKED, false); }
4214
* Method to tell if the sub-instances in this Cell are locked.
4215
* Locked instances cannot be moved or deleted.
4216
* @return true if the sub-instances in this Cell are locked.
4218
public boolean isInstancesLocked() { return isFlag(NPILOCKED); }
4221
* Method to set this Cell so that it is part of a cell library.
4222
* Cell libraries are simply libraries that contain standard cells but no hierarchy
4223
* (as opposed to libraries that define a complete circuit).
4224
* Certain commands exclude facets from cell libraries, so that the actual circuit hierarchy can be more clearly seen.
4226
public void setInCellLibrary() { setFlag(INCELLLIBRARY, true); }
4118
* Method to check the current cell to be sure that no subcells have a more recent date.
4119
* This is invoked when the "Check cell dates" feature is enabled in the New Nodes tab of
4120
* the Edit Options dialog.
4122
public void checkCellDates() {
4123
Set<Cell> cellsChecked = new HashSet<Cell>();
4124
checkCellDate(getRevisionDate(), cellsChecked);
4128
* Recursive method to check sub-cell revision times.
4129
* @param rev_time the revision date of the top-level cell.
4130
* Nothing below it can be newer.
4132
private void checkCellDate(Date rev_time, Set<Cell> cellsChecked) {
4133
for (Iterator<NodeInst> it = getNodes(); it.hasNext();) {
4134
NodeInst ni = it.next();
4135
if (!ni.isCellInstance()) {
4138
Cell subCell = (Cell) ni.getProto();
4140
// ignore recursive references (showing icon in contents)
4141
if (subCell.isIconOf(this)) {
4144
if (!cellsChecked.contains(subCell)) {
4145
subCell.checkCellDate(rev_time, cellsChecked); // recurse
4148
Cell contentsCell = subCell.contentsView();
4149
if (contentsCell != null) {
4150
if (!cellsChecked.contains(contentsCell)) {
4151
contentsCell.checkCellDate(rev_time, cellsChecked); // recurse
4157
cellsChecked.add(this); // flag that we have seen this one
4158
if (!getRevisionDate().after(rev_time)) {
4162
// possible error in hierarchy
4163
System.out.println("WARNING: sub-cell " + this
4164
+ " has been edited since the last revision to the current cell");
4167
/****************************** MISCELLANEOUS ******************************/
4168
private int getFlags() {
4172
private boolean isFlag(int mask) {
4173
return (getFlags() & mask) != 0;
4176
private void setFlag(int mask, boolean value) {
4177
lowLevelSetUserbits(value ? getFlags() | mask : getFlags() & ~mask);
4181
* Method to set this Cell so that instances of it are "expanded" by when created.
4182
* Expanded NodeInsts are instances of Cells that show their contents.
4184
public void setWantExpanded() {
4185
setFlag(WANTNEXPAND, true);
4189
* Method to set this Cell so that instances of it are "not expanded" by when created.
4190
* Expanded NodeInsts are instances of Cells that show their contents.
4192
public void clearWantExpanded() {
4193
setFlag(WANTNEXPAND, false);
4197
* Method to tell if instances of it are "expanded" by when created.
4198
* Expanded NodeInsts are instances of Cells that show their contents.
4199
* @return true if instances of it are "expanded" by when created.
4201
public boolean isWantExpanded() {
4202
return isFlag(WANTNEXPAND) || isIcon();
4206
* Method to return the function of this Cell.
4207
* The Function of CELL is alway UNKNOWN.
4208
* @return the function of this Cell.
4210
public PrimitiveNode.Function getFunction() {
4211
return PrimitiveNode.Function.UNKNOWN;
4215
* Method to set this Cell so that everything inside of it is locked.
4216
* Locked instances cannot be moved or deleted.
4218
public void setAllLocked() {
4219
setFlag(NPLOCKED, true);
4223
* Method to set this Cell so that everything inside of it is not locked.
4224
* Locked instances cannot be moved or deleted.
4226
public void clearAllLocked() {
4227
setFlag(NPLOCKED, false);
4231
* Method to tell if the contents of this Cell are locked.
4232
* Locked instances cannot be moved or deleted.
4233
* @return true if the contents of this Cell are locked.
4235
public boolean isAllLocked() {
4236
return isFlag(NPLOCKED);
4240
* Method to set this Cell so that all instances inside of it are locked.
4241
* Locked instances cannot be moved or deleted.
4243
public void setInstancesLocked() {
4244
setFlag(NPILOCKED, true);
4248
* Method to set this Cell so that all instances inside of it are not locked.
4249
* Locked instances cannot be moved or deleted.
4251
public void clearInstancesLocked() {
4252
setFlag(NPILOCKED, false);
4256
* Method to tell if the sub-instances in this Cell are locked.
4257
* Locked instances cannot be moved or deleted.
4258
* @return true if the sub-instances in this Cell are locked.
4260
public boolean isInstancesLocked() {
4261
return isFlag(NPILOCKED);
4265
* Method to set this Cell so that it is part of a cell library.
4266
* Cell libraries are simply libraries that contain standard cells but no hierarchy
4267
* (as opposed to libraries that define a complete circuit).
4268
* Certain commands exclude facets from cell libraries, so that the actual circuit hierarchy can be more clearly seen.
4270
public void setInCellLibrary() {
4271
setFlag(INCELLLIBRARY, true);
4229
4275
// * Method to set this Cell so that it is not part of a cell library.
4505
4621
assert e.getParent() == this;
4506
4622
assert e.getPortIndex() == portIndex;
4507
4623
assert chronExports[e.getId().getChronIndex()] == e;
4508
if (cellContentsFresh) assert cellRevision.exports.get(portIndex) == e.getD();
4510
assert(TextUtils.STRING_NUMBER_ORDER.compare(exports[portIndex - 1].getName(), e.getName()) < 0);
4624
if (cellContentsFresh) {
4625
assert cellRevision.exports.get(portIndex) == e.getD();
4627
if (portIndex > 0) {
4628
assert (TextUtils.STRING_NUMBER_ORDER.compare(exports[portIndex - 1].getName(), e.getName()) < 0);
4511
4630
assert e.getOriginalPort() == getPortInst(e.getD().originalNodeId, e.getD().originalPortId);
4513
4632
for (int chronIndex = 0; chronIndex < chronExports.length; chronIndex++) {
4514
4633
Export e = chronExports[chronIndex];
4515
if (e == null) continue;
4516
4637
assert e.getId() == cellId.getPortId(chronIndex);
4517
4638
assert e == exports[e.getPortIndex()];
4642
Topology topology = getTopologyOptional();
4521
4643
if (topology != null) {
4644
topology.check(cellUsages);
4523
4645
if (cellContentsFresh) {
4524
for(int arcIndex = 0; arcIndex < topology.getNumArcs(); arcIndex++) {
4646
assert cellRevision.arcs.size() == topology.getNumArcs();
4647
for (int arcIndex = 0; arcIndex < topology.getNumArcs(); arcIndex++) {
4525
4648
ArcInst ai = topology.getArc(arcIndex);
4526
4649
ImmutableArcInst a = ai.getD();
4527
4650
assert cellRevision.arcs.get(arcIndex) == a;
4533
NodeInst prevNi = null;
4534
int[] usages = new int[cellId.numUsagesIn()];
4535
for(int nodeIndex = 0; nodeIndex < nodes.size(); nodeIndex++) {
4536
NodeInst ni = nodes.get(nodeIndex);
4537
ImmutableNodeInst n = ni.getD();
4538
assert ni.getParent() == this;
4539
assert ni.getNodeIndex() == nodeIndex;
4540
assert chronNodes.get(n.nodeId) == ni;
4541
if (cellContentsFresh) assert cellRevision.nodes.get(nodeIndex) == n;
4542
if (prevNi != null) {
4543
assert TextUtils.STRING_NUMBER_ORDER.compare(prevNi.getName(), ni.getName()) < 0;
4545
if (ni.isCellInstance()) {
4546
Cell subCell = (Cell)ni.getProto();
4547
assert subCell.isLinked();
4548
assert subCell.database == database;
4549
CellUsage u = cellId.getUsageIn(subCell.getId());
4550
usages[u.indexInParent]++;
4555
for (int nodeId = 0; nodeId < chronNodes.size(); nodeId++) {
4556
NodeInst ni = chronNodes.get(nodeId);
4557
if (ni == null) continue;
4558
assert ni.getD().nodeId == nodeId;
4559
assert ni == nodes.get(ni.getNodeIndex());
4562
// check node usages
4563
for (int i = 0; i < cellUsages.length; i++)
4564
assert cellUsages[i] == usages[i];
4565
for (int i = cellUsages.length; i < usages.length; i++)
4566
assert usages[i] == 0;
4652
assert cellRevision.nodes.size() == topology.getNumNodes();
4653
for (int nodeIndex = 0; nodeIndex < topology.getNumNodes(); nodeIndex++) {
4654
NodeInst ni = topology.getNode(nodeIndex);
4655
ImmutableNodeInst n = ni.getD();
4656
assert cellRevision.nodes.get(nodeIndex) == n;
4568
4661
// check group pointers
4569
4662
assert cellGroup.containsCell(this);
4571
// check bounds and RTree
4572
if (boundsDirty == BOUNDS_CORRECT) {
4573
assert computeBounds() == cellBounds;
4574
assert boundsDirty == BOUNDS_CORRECT;
4579
4666
* Method to tell whether an ElectricObject exists in this Cell.
4580
* Used when saving and restoring highlighting to ensure that the object still
4582
* @param eObj the ElectricObject in question
4583
* @return true if that ElectricObject is in this Cell.
4585
public boolean objInCell(ElectricObject eObj)
4587
if (eObj instanceof NodeInst)
4589
for(Iterator<NodeInst> it = getNodes(); it.hasNext(); )
4590
if (it.next() == eObj) return true;
4591
} else if (eObj instanceof ArcInst)
4593
for(Iterator<ArcInst> it = getArcs(); it.hasNext(); )
4594
if (it.next() == eObj) return true;
4595
} else if (eObj instanceof PortInst)
4597
NodeInst ni = ((PortInst)eObj).getNodeInst();
4598
for(Iterator<NodeInst> it = getNodes(); it.hasNext(); )
4599
if (it.next() == ni) return true;
4605
* Method to get the 0-based index of this Cell.
4606
* @return the index of this Cell.
4608
public final int getCellIndex() { return getId().cellIndex; }
4611
* Method to set an arbitrary integer in a temporary location on this Cell.
4612
* @param tempInt the integer to be set on this Cell.
4614
public void setTempInt(int tempInt) { checkChanging(); this.tempInt = tempInt; }
4617
* Method to get the temporary integer on this Cell.
4618
* @return the temporary integer on this Cell.
4620
public int getTempInt() { return tempInt; }
4623
* Method to determine the appropriate Cell associated with this ElectricObject.
4624
* @return the appropriate Cell associated with this ElectricObject..
4625
* Returns null if no Cell can be found.
4627
public Cell whichCell() { return this; }
4630
* Method to get the library to which this Cell belongs.
4631
* @return to get the library to which this Cell belongs.
4633
public Library getLibrary() { return lib; }
4636
* Method to return the Technology of this Cell.
4637
* It can be quite complex to determine which Technology a Cell belongs to.
4638
* The system examines all of the nodes and arcs in it, and also considers
4640
* @return return the Technology of this Cell.
4642
public Technology getTechnology() {
4644
setTechnology(Technology.whatTechnology(this, null, 0, 0, null));
4649
* Method to set the Technology to which this NodeProto belongs
4650
* It can only be called for Cells because PrimitiveNodes have fixed Technology membership.
4651
* @param tech the new technology for this NodeProto (Cell).
4653
public void setTechnology(Technology tech) {
4667
* Used when saving and restoring highlighting to ensure that the object still
4669
* @param eObj the ElectricObject in question
4670
* @return true if that ElectricObject is in this Cell.
4672
public boolean objInCell(ElectricObject eObj) {
4673
if (eObj instanceof NodeInst) {
4674
for (Iterator<NodeInst> it = getNodes(); it.hasNext();) {
4675
if (it.next() == eObj) {
4679
} else if (eObj instanceof ArcInst) {
4680
for (Iterator<ArcInst> it = getArcs(); it.hasNext();) {
4681
if (it.next() == eObj) {
4685
} else if (eObj instanceof PortInst) {
4686
NodeInst ni = ((PortInst) eObj).getNodeInst();
4687
for (Iterator<NodeInst> it = getNodes(); it.hasNext();) {
4688
if (it.next() == ni) {
4697
* Method to get the 0-based index of this Cell.
4698
* @return the index of this Cell.
4700
public final int getCellIndex() {
4701
return getId().cellIndex;
4705
* Method to set an arbitrary integer in a temporary location on this Cell.
4706
* @param tempInt the integer to be set on this Cell.
4708
public void setTempInt(int tempInt) {
4710
this.tempInt = tempInt;
4714
* Method to get the temporary integer on this Cell.
4715
* @return the temporary integer on this Cell.
4717
public int getTempInt() {
4722
* Method to determine the appropriate Cell associated with this ElectricObject.
4723
* @return the appropriate Cell associated with this ElectricObject..
4724
* Returns null if no Cell can be found.
4726
public Cell whichCell() {
4731
* Method to get the library to which this Cell belongs.
4732
* @return to get the library to which this Cell belongs.
4734
public Library getLibrary() {
4739
* Method to return the Technology of this Cell.
4740
* It can be quite complex to determine which Technology a Cell belongs to.
4741
* The system examines all of the nodes and arcs in it, and also considers
4743
* @return return the Technology of this Cell.
4745
public Technology getTechnology() {
4747
NodeProto[] nodeProtos = null;
4748
ArcProto[] arcProtos = null;
4749
if (backup == null && getTopologyOptional() == null) {
4750
nodeProtos = new NodeProto[0];
4751
arcProtos = new ArcProto[0];
4753
setTechnology(Technology.whatTechnology(this, nodeProtos, 0, 0, arcProtos));
4759
* Method to set the Technology to which this NodeProto belongs
4760
* It can only be called for Cells because PrimitiveNodes have fixed Technology membership.
4761
* @param tech the new technology for this NodeProto (Cell).
4763
public void setTechnology(Technology tech) {
4654
4764
TechId techId = null;
4655
4765
if (tech != null) {
4656
4766
techId = tech.getId();
4657
if (database.getTech(techId) != tech)
4767
if (database.getTech(techId) != tech) {
4658
4768
throw new IllegalArgumentException("tech");
4660
4771
setD(getD().withTechId(techId));
4661
4772
this.tech = tech;
4665
* Finds the Schematic Cell associated with this Icon Cell.
4666
* If this Cell is an Icon View then find the schematic Cell in its
4668
* @return the Schematic Cell. Returns null if there is no equivalent.
4669
* If there are multiple versions of the Schematic View then
4670
* return the latest version.
4672
public Cell getEquivalent()
4674
return isIcon() ? getCellGroup().getMainSchematics() : this;
4678
* Use to compare cells in Cross Library Check
4679
* @param obj Object to compare to
4680
* @param buffer To store comparison messages in case of failure
4681
* @return True if objects represent same NodeInst
4683
public boolean compare(Object obj, StringBuffer buffer)
4685
if (this == obj) return (true);
4687
// Consider already obj==null
4688
if (obj == null || getClass() != obj.getClass())
4776
* Finds the Schematic Cell associated with this Icon Cell.
4777
* If this Cell is an Icon View then find the schematic Cell in its
4779
* @return the Schematic Cell. Returns null if there is no equivalent.
4780
* If there are multiple versions of the Schematic View then
4781
* return the latest version.
4783
public Cell getEquivalent() {
4784
return isIcon() ? getCellGroup().getMainSchematics() : this;
4788
* Use to compare cells in Cross Library Check
4789
* @param obj Object to compare to
4790
* @param buffer To store comparison messages in case of failure
4791
* @return True if objects represent same NodeInst
4793
public boolean compare(Object obj, StringBuffer buffer) {
4798
// Consider already obj==null
4799
if (obj == null || getClass() != obj.getClass()) {
4689
4800
return (false);
4691
Cell toCompare = (Cell)obj;
4803
Cell toCompare = (Cell) obj;
4693
4805
// Traversing nodes
4694
4806
// @TODO GVG This should be removed if equals is implemented
4695
4807
Set<Object> noCheckAgain = new HashSet<Object>();
4696
for (Iterator<NodeInst> it = getNodes(); it.hasNext(); )
4808
for (Iterator<NodeInst> it = getNodes(); it.hasNext();) {
4698
4809
boolean found = false;
4699
4810
NodeInst node = it.next();
4701
for (Iterator<NodeInst> i = toCompare.getNodes(); i.hasNext();)
4812
for (Iterator<NodeInst> i = toCompare.getNodes(); i.hasNext();) {
4703
4813
NodeInst n = i.next();
4705
if (noCheckAgain.contains(n)) continue;
4815
if (noCheckAgain.contains(n)) {
4707
if (node.compare(n, buffer))
4819
if (node.compare(n, buffer)) {
4710
4821
// if node is found, remove elem from iterator
4711
4822
// because it was found