60
60
* Handles the fixed-angle and rigid constraints.
61
61
* Also propagates these constraints up the hierarchy.
63
public class Layout extends Constraints
63
public class Layout extends Constraints {
65
64
// private static final Layout layoutConstraint = new Layout();
67
static final boolean DEBUG = false;
66
static final boolean DEBUG = false;
69
67
private static boolean doChangesQuietly;
70
68
private static Snapshot oldSnapshot;
71
69
private static long revisionDate;
72
70
private static String userName;
73
71
private static Set<Cell> goodSpacingDRCCells, goodAreaDRCCells;
74
72
private static Variable goodSpacingDRCDate, goodSpacingDRCBit, goodAreaDRCDate;
76
73
/** Shadow Cell info */
77
74
private static final ArrayList<LayoutCell> cellInfos = new ArrayList<LayoutCell>();
78
75
/** Map which contains temporary rigidity of ArcInsts. */
79
private static final HashMap<ArcInst,Boolean> tempRigid = new HashMap<ArcInst,Boolean>();
76
private static final HashMap<ArcInst, Boolean> tempRigid = new HashMap<ArcInst, Boolean>();
80
77
/** key of Variable for last valid DRC date on a Cell. Only spacing rules */
81
78
public static final Variable.Key DRC_LAST_GOOD_DATE_SPACING = Variable.newKey("DRC_last_good_drc_date");
82
79
/** key of Variable for last valid DRC bit on a Cell. Only spacing rules */
86
83
/** No need of bit for area since it is only 1 mode */
87
84
public static final Variable.Key DRC_LAST_GOOD_DATE_AREA = Variable.newKey("DRC_last_good_drc_area_date");
92
90
// * Method to return the current constraint solver.
93
91
// * @return the current constraint solver.
95
93
// public static Layout getConstraint() { return layoutConstraint; }
98
* Method to set the subsequent changes to be "quiet".
99
* Quiet changes are not passed to constraint satisfaction, not recorded for Undo and are not broadcast.
95
* Method to set the subsequent changes to be "quiet".
96
* Quiet changes are not passed to constraint satisfaction, not recorded for Undo and are not broadcast.
100
97
* This method is used to suppress endBatch.
102
public static void changesQuiet(boolean quiet) {
99
public static void changesQuiet(boolean quiet) {
103
100
doChangesQuietly = true;
107
* Method to start a batch of changes.
104
* Method to start a batch of changes.
108
105
* @param initialSnapshot snapshot before job changes.
111
public void startBatch(Snapshot initialSnapshot)
113
// force every cell to remember its current bounds
108
public void startBatch(Snapshot initialSnapshot) {
109
// force every cell to remember its current bounds
114
110
doChangesQuietly = false;
115
111
oldSnapshot = initialSnapshot;
116
112
tempRigid.clear();
117
113
goodSpacingDRCCells = null;
118
114
goodAreaDRCCells = null;
119
115
makeLayoutCells();
123
* Method to do hierarchical update on any cells that changed
119
* Method to do hierarchical update on any cells that changed
126
public void endBatch(String userName)
122
public void endBatch(String userName) {
129
124
System.out.println("Temporary rigid:");
130
for (Map.Entry<ArcInst,Boolean> e : tempRigid.entrySet()) {
125
for (Map.Entry<ArcInst, Boolean> e : tempRigid.entrySet()) {
131
126
System.out.println("\t" + e.getKey() + " --> " + e.getValue());
134
129
Layout.userName = userName;
135
130
revisionDate = System.currentTimeMillis();
136
if (goodSpacingDRCCells != null)
131
if (goodSpacingDRCCells != null) {
138
132
TextDescriptor td = TextDescriptor.getCellTextDescriptor().withDisplay(false);
139
133
goodSpacingDRCDate = Variable.newInstance(DRC_LAST_GOOD_DATE_SPACING, new Long(revisionDate + 1), td); // If cell is changed during this 1 millisecond ???
142
if (goodAreaDRCCells != null)
136
if (goodAreaDRCCells != null) {
144
137
TextDescriptor td = TextDescriptor.getCellTextDescriptor().withDisplay(false);
145
138
goodAreaDRCDate = Variable.newInstance(DRC_LAST_GOOD_DATE_AREA, new Long(revisionDate + 1), td); // If cell is changed during this 1 millisecond ???
147
140
if (!doChangesQuietly) {
148
141
// Propagate changes and mark changed cells.
149
for(Iterator<Library> it = Library.getLibraries(); it.hasNext(); ) {
142
for (Iterator<Library> it = Library.getLibraries(); it.hasNext();) {
150
143
Library lib = it.next();
151
for(Iterator<Cell> cIt = lib.getCells(); cIt.hasNext(); ) {
144
for (Iterator<Cell> cIt = lib.getCells(); cIt.hasNext();) {
152
145
Cell cell = cIt.next();
153
146
assert cell.isLinked();
154
147
LayoutCell cellInfo = getCellInfo(cell);
180
173
goodSpacingDRCCells = null;
181
174
goodAreaDRCCells = null;
182
175
oldSnapshot = null;
186
* Method to handle a change to a NodeInst.
187
* @param ni the NodeInst that was changed.
188
* @param oD the old contents of the NodeInst.
179
* Method to handle a change to a NodeInst.
180
* @param ni the NodeInst that was changed.
181
* @param oD the old contents of the NodeInst.
191
public void modifyNodeInst(NodeInst ni, ImmutableNodeInst oD) {
192
if (doChangesQuietly) return;
184
public void modifyNodeInst(NodeInst ni, ImmutableNodeInst oD) {
185
if (doChangesQuietly) {
193
188
getCellInfo(ni.getParent()).modifyNodeInst(ni, oD);
197
* Method to handle a change to an ArcInst.
198
* @param ai the ArcInst that changed.
192
* Method to handle a change to an ArcInst.
193
* @param ai the ArcInst that changed.
199
194
* @param oD the old contents of the ArcInst.
202
public void modifyArcInst(ArcInst ai, ImmutableArcInst oD) {
203
if (doChangesQuietly) return;
197
public void modifyArcInst(ArcInst ai, ImmutableArcInst oD) {
198
if (doChangesQuietly) {
204
201
getCellInfo(ai.getParent()).modifyArcInst(ai, oD);
208
* Method to handle a change to an Export.
209
* @param pp the Export that moved.
210
* @param oldD the old contents of the Export.
205
* Method to handle a change to an Export.
206
* @param pp the Export that moved.
207
* @param oldD the old contents of the Export.
213
public void modifyExport(Export pp, ImmutableExport oldD) {
214
if (doChangesQuietly) return;
210
public void modifyExport(Export pp, ImmutableExport oldD) {
211
if (doChangesQuietly) {
215
214
PortInst oldPi = pp.getParent().getPortInst(oldD.originalNodeId, oldD.originalPortId);
216
if (oldPi == pp.getOriginalPort()) return;
215
if (oldPi == pp.getOriginalPort()) {
217
218
getCellInfo(pp.getParent()).modifyExport(pp, oldPi);
221
* Method to handle a change to a Cell.
222
* @param cell the Cell that was changed.
223
* @param oD the old contents of the Cell.
226
public void modifyCell(Cell cell, ImmutableCell oD) {}
229
* Method to handle a change to a Library.
230
* @param lib the Library that was changed.
231
* @param oldD the old contents of the Library.
234
public void modifyLibrary(Library lib, ImmutableLibrary oldD) {}
237
* Method to handle the creation of a new ElectricObject.
238
* @param obj the ElectricObject that was just created.
241
public void newObject(ElectricObject obj) {
242
if (doChangesQuietly) return;
222
* Method to handle a change to a Cell.
223
* @param cell the Cell that was changed.
224
* @param oD the old contents of the Cell.
227
public void modifyCell(Cell cell, ImmutableCell oD) {
231
* Method to handle a change to a Library.
232
* @param lib the Library that was changed.
233
* @param oldD the old contents of the Library.
236
public void modifyLibrary(Library lib, ImmutableLibrary oldD) {
240
* Method to handle the creation of a new ElectricObject.
241
* @param obj the ElectricObject that was just created.
244
public void newObject(ElectricObject obj) {
245
if (doChangesQuietly) {
243
248
Cell cell = obj.whichCell();
245
250
newCellInfo(cell, null);
246
else if (cell != null)
251
} else if (cell != null) {
247
252
getCellInfo(cell).newObject(obj);
251
257
* Method to announce than Ids were renamed.
255
261
public void renameIds(IdMapper idMapper) {
256
262
EDatabase database = EDatabase.serverDatabase();
257
for (CellId cellId: idMapper.getNewCellIds())
263
for (CellId cellId : idMapper.getNewCellIds()) {
258
264
newObject(cellId.inDatabase(database));
259
266
// for (ExportId exportId: idMapper.getNewExportIds())
260
267
// newObject(exportId.inDatabase(database));
264
* Method to set temporary rigidity on an ArcInst.
265
* @param ai the ArcInst to make temporarily rigid/not-rigid.
266
* @param tempRigid true to make the ArcInst temporarily rigid;
267
* false to make it temporarily not-rigid.
269
public static void setTempRigid(ArcInst ai, boolean tempRigid)
271
if (DEBUG) System.out.println("setTempRigid " + ai + " " + tempRigid);
271
* Method to set temporary rigidity on an ArcInst.
272
* @param ai the ArcInst to make temporarily rigid/not-rigid.
273
* @param tempRigid true to make the ArcInst temporarily rigid;
274
* false to make it temporarily not-rigid.
276
public static void setTempRigid(ArcInst ai, boolean tempRigid) {
278
System.out.println("setTempRigid " + ai + " " + tempRigid);
272
280
ai.checkChanging();
273
281
Layout.tempRigid.put(ai, Boolean.valueOf(tempRigid));
274
282
// if (tempRigid)
280
288
// if (ai.getChangeClock() == changeClock + 3) return;
281
289
// ai.setChangeClock(changeClock + 3);
286
* Method to remove temporary rigidity on an ArcInst.
287
* @param ai the ArcInst to remove temporarily rigidity.
289
public static void removeTempRigid(ArcInst ai)
294
* Method to remove temporary rigidity on an ArcInst.
295
* @param ai the ArcInst to remove temporarily rigidity.
297
public static void removeTempRigid(ArcInst ai) {
291
298
ai.checkChanging();
292
299
tempRigid.remove(ai);
293
300
// if (ai.getChangeClock() != changeClock + 3 && ai.getChangeClock() != changeClock + 2) return;
294
301
// ai.setChangeClock(changeClock - 3);
298
305
* Method to request to set
300
public static void setGoodDRCCells(Set<Cell> goodDRCCells, Variable.Key key, int activeBits, boolean inMemory)
302
assert(!inMemory); // call only if you are storing in disk
307
public static void setGoodDRCCells(Set<Cell> goodDRCCells, Variable.Key key, int activeBits, boolean inMemory) {
308
assert (!inMemory); // call only if you are storing in disk
304
if (key == DRC_LAST_GOOD_DATE_SPACING)
310
if (key == DRC_LAST_GOOD_DATE_SPACING) {
306
311
Layout.goodSpacingDRCCells = goodDRCCells;
307
312
TextDescriptor td = TextDescriptor.getCellTextDescriptor().withDisplay(false);
308
313
goodSpacingDRCBit = Variable.newInstance(DRC_LAST_GOOD_BIT_SPACING, new Integer(activeBits), td);
312
316
Layout.goodAreaDRCCells = goodDRCCells;
326
330
private static void makeLayoutCells() {
327
331
cellInfos.clear();
328
for(Iterator<Library> it = Library.getLibraries(); it.hasNext(); )
330
Library lib = it.next();
331
for(Iterator<Cell> cIt = lib.getCells(); cIt.hasNext(); )
333
Cell cell = cIt.next();
332
for (Iterator<Library> it = Library.getLibraries(); it.hasNext();) {
333
Library lib = it.next();
334
for (Iterator<Cell> cIt = lib.getCells(); cIt.hasNext();) {
335
Cell cell = cIt.next();
334
336
newCellInfo(cell, oldSnapshot.getCell(cell.getId()));
339
/******************** NODE MODIFICATION CODE *************************/
342
* Method to compute the position of portinst "pi" and
343
* place the center of the area in the parameters "x" and "y". The position
344
* is the "old" position, as determined by any changes that may have occured
345
* to the nodeinst (and any sub-nodes).
347
static Poly oldPortPosition(PortInst pi)
341
/******************** NODE MODIFICATION CODE *************************/
343
* Method to compute the position of portinst "pi" and
344
* place the center of the area in the parameters "x" and "y". The position
345
* is the "old" position, as determined by any changes that may have occured
346
* to the nodeinst (and any sub-nodes).
348
static Poly oldPortPosition(PortInst pi) {
349
349
NodeInst ni = pi.getNodeInst();
350
350
PortProto pp = pi.getPortProto();
351
// descend to the primitive node
352
AffineTransform subrot = makeOldRot(ni);
353
if (subrot == null) return null;
354
NodeInst bottomNi = ni;
355
PortProto bottomPP = pp;
356
while (bottomNi.isCellInstance())
358
AffineTransform localtran = makeOldTrans(bottomNi);
359
subrot.concatenate(localtran);
361
PortInst bottomPi = getOldOriginalPort((Export)bottomPP);
362
bottomNi = bottomPi.getNodeInst();
363
bottomPP = bottomPi.getPortProto();
364
localtran = makeOldRot(bottomNi);
365
subrot.concatenate(localtran);
368
// if the node hasn't changed, use its current values
351
// descend to the primitive node
352
AffineTransform subrot = makeOldRot(ni);
353
if (subrot == null) {
356
NodeInst bottomNi = ni;
357
PortProto bottomPP = pp;
358
while (bottomNi.isCellInstance()) {
359
AffineTransform localtran = makeOldTrans(bottomNi);
360
subrot.concatenate(localtran);
362
PortInst bottomPi = getOldOriginalPort((Export) bottomPP);
363
bottomNi = bottomPi.getNodeInst();
364
bottomPP = bottomPi.getPortProto();
365
localtran = makeOldRot(bottomNi);
366
subrot.concatenate(localtran);
369
// if the node hasn't changed, use its current values
369
370
ImmutableNodeInst d = Layout.getOldD(bottomNi);
370
371
assert d != null;
371
372
if (d != bottomNi.getD()) {
372
// create a fake node with these values
373
// create a fake node with these values
373
374
bottomNi = NodeInst.makeDummyInstance(bottomNi.getProto());
374
375
bottomNi.lowLevelModify(d);
376
PrimitiveNode np = (PrimitiveNode)bottomNi.getProto();
377
Technology tech = np.getTechnology();
378
Poly poly = tech.getShapeOfPort(bottomNi, (PrimitivePort)bottomPP);
379
poly.transform(subrot);
377
PrimitiveNode np = (PrimitiveNode) bottomNi.getProto();
378
Technology tech = np.getTechnology();
379
Poly poly = tech.getShapeOfPort(bottomNi, (PrimitivePort) bottomPP);
380
poly.transform(subrot);
383
private static AffineTransform makeOldRot(NodeInst ni)
385
// if the node has not been modified, just use the current transformation
384
private static AffineTransform makeOldRot(NodeInst ni) {
385
// if the node has not been modified, just use the current transformation
386
386
ImmutableNodeInst d = getOldD(ni);
387
if (d == null) return null;
389
// get the old values
391
// get the old values
390
392
double cX = d.anchor.getX();
391
393
double cY = d.anchor.getY();
392
394
return d.orient.rotateAbout(cX, cY);
395
private static AffineTransform makeOldTrans(NodeInst ni)
397
private static AffineTransform makeOldTrans(NodeInst ni) {
397
398
ImmutableNodeInst d = getOldD(ni);
398
if (d == null) return null;
400
// create the former translation matrix
401
AffineTransform transform = new AffineTransform();
403
// create the former translation matrix
404
AffineTransform transform = new AffineTransform();
402
405
double cX = d.anchor.getX();
403
406
double cY = d.anchor.getY();
404
transform.translate(cX, cY);
407
transform.translate(cX, cY);
408
411
static PortInst getOldOriginalPort(Export e) {
409
412
return getCellInfo(e.getParent()).getOldOriginalPort(e);