PWSqueezeImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet, February 3, 1985 12:49:51 pm PST
Last edited by Bertrand Serlet, April 23, 1987 3:34:11 pm PDT
DIRECTORY
CD, CDAtomicObjects, CDBasics, CDCells, CDDirectory, CDDirectoryOps, CDIO, CDProperties, CDRects, CDRoutingObjects,
CMosB,
Core, CoreFlat, CoreGeometry,
IO, PW, Rope, Sinix, SinixRawCMosB, SymTab, TerminalIO;
PWSqueezeImpl: CEDAR PROGRAM
IMPORTS CD, CDAtomicObjects, CDBasics, CDCells, CDDirectory, CDDirectoryOps, CDIO, CDProperties, CDRects, CDRoutingObjects, CMosB, CoreFlat, CoreGeometry, IO, PW, Rope, Sinix, SinixRawCMosB, SymTab, TerminalIO
SHARES CDCells, CDRects =
BEGIN
ROPE: TYPE = Rope.ROPE;
Count Transistors
CountTransistors: PROC [obj: CD.Object] RETURNS [count: INT ← 0] = {
value: REF INTNARROW [CDProperties.GetObjectProp[obj, $TransistorCount]];
IF value#NIL THEN RETURN [value^];
SELECT obj.class FROM
CDCells.pCellClass  => {
EachSub: CDCells.InstEnumerator = {count ← count + CountTransistors[inst.ob]};
[] ← CDCells.EnumerateInstances[obj, EachSub];
CDProperties.PutObjectProp[obj, $TransistorCount, NEW [INT ← count]];
};
CDRoutingObjects.routingClass => {};
CD.FetchObjectClass[$C2Trans, CMosB.cmosB], CD.FetchObjectClass[$C2WellTrans, CMosB.cmosB], CD.FetchObjectClass[$C2LTrans, CMosB.cmosB], CD.FetchObjectClass[$C2LWellTrans, CMosB.cmosB] => RETURN [1];
ENDCASE => RETURN [IF obj.class.composed THEN CountTransistors[CDDirectory.Expand1[obj].new] ELSE 0];
};
Transform into a RoutingCell
Leaf: CoreGeometry.LeafProc = {RETURN [FALSE]};
PObj: TYPE = CDRoutingObjects.PlacedObject;
IntanceToPObj: PROC [instance: CoreGeometry.Instance] RETURNS [po: PObj] = {
IF instance.trans.orient=original THEN RETURN [[instance.obj, instance.trans.off]];
po.object ← SELECT TRUE FROM
instance.obj.class=CDRects.bareRectClass => CDRects.CreateRect[CDBasics.OrientedSize[CD.InterestSize[instance.obj], instance.trans.orient], instance.obj.layer],
instance.obj.class.atomicOb  => CDAtomicObjects.CreateAtomicOb[instance.obj.class.objectType, CDBasics.OrientedSize[CD.InterestSize[instance.obj], instance.trans.orient], CMosB.cmosB, instance.obj.layer],
ENDCASE => PW.CreateRotation[instance.obj, instance.trans.orient];
po.position ← CDBasics.SubPoints[CDBasics.BaseOfRect[CoreGeometry.BBox[instance]], CDBasics.BaseOfRect[CoreGeometry.BBox[[po.object, []]]]];
};
Translator1: Rope.TranslatorType = {
RETURN [SELECT old FROM '*, '[, '], '., '/ => '$, ENDCASE => old];
};
Translator2: Rope.TranslatorType = {
RETURN [SELECT old FROM '*, '/ => '$, ENDCASE => old];
};
Area: PROC [rect: CD.Rect] RETURNS [INT] = {RETURN [(rect.y2-rect.y1)*(rect.x2-rect.x1)]};
Serlet's third theorem: rect1 and rect2 are fusable (i.e. all points belonging to the surround belong either to rect1 or to rect2 or to both) iff their area follow the strange law in the code.
Fusable: PROC [rect1, rect2: CD.Rect] RETURNS [BOOL] = {
RETURN [Area[CDBasics.Surround[rect1, rect2]] + Area[CDBasics.Intersection[rect1, rect2]] = Area[rect1] + Area[rect2]];
};
BBox: PROC [pobj: PObj] RETURNS [rect: CD.Rect] = {
RETURN [CDBasics.MapRect[CD.InterestRect[pobj.object], [pobj.position]]];
};
PObjSeq: TYPE = RECORD [c: SEQUENCE size: NAT OF PObj];
SimplifyPObj: PROC [pobjs: LIST OF PObj] RETURNS [news: LIST OF PObj ← NIL]= {
changed: BOOLTRUE;
count: NAT ← 0;
seq: REF PObjSeq;
FOR list: LIST OF PObj ← pobjs, list.rest WHILE list#NIL DO count ← count + 1 ENDLOOP;
seq ← NEW [PObjSeq[count]];
FOR i: NAT IN [0 .. count) DO seq[i] ← pobjs.first; pobjs ← pobjs.rest ENDLOOP;
WHILE changed AND count>0 DO
changed ← FALSE;
FOR i: NAT IN [0 .. count-1) DO
IF seq[i].object#NIL THEN FOR j: NAT IN (i .. count) DO
The following statement does NOT work!!!
IF seq[j].object#NIL AND seq[i].object.class=CDRects.bareRectClass AND seq[j].object.class=CDRects.bareRectClass AND seq[i].object.layer=seq[j].object.layer AND Fusable[BBox[seq[i]], BBox[seq[j]]]
THEN {
fused: CD.Rect = CDBasics.Surround[BBox[seq[i]], BBox[seq[j]]];
seq[i] ← [
object: CDRects.CreateRect[CDBasics.SizeOfRect[fused], seq[i].object.layer],
position: CDBasics.BaseOfRect[fused]
];
seq[j].object ← NIL; changed ← TRUE;
}
ENDLOOP;
ENDLOOP;
ENDLOOP;
FOR i: NAT IN [0 .. count) DO
IF seq[i].object#NIL THEN news ← CONS [seq[i], news];
ENDLOOP;
};
ToRoutingCell: PROC [obj: CD.Object] RETURNS [routing: CD.Object] = {
FiddleName: SymTab.EachPairAction = {
name: ROPE = IF Rope.Find[key, "public."]=0 THEN Rope.Substr[key, 7] ELSE key;
pobjs: REF LIST OF PObj = NARROW [val];
new: ROPE = SELECT TRUE FROM
Rope.Fetch[name]='[ => Rope.Translate[base: name, translator: Translator1],
Rope.Find[name, "*"]<0 AND Rope.Find[name, "/"]<0 => name,
ENDCASE  => Rope.Translate[base: name, translator: Translator2];
IF pobjs^=NIL THEN ERROR; -- there should be at least one piece of geometry per wire.
IF NOT Rope.Equal[new, name] THEN
TerminalIO.PutF["** Flat wire %g replaced by %g.\n", IO.rope[key], IO.rope[new]];
pobjs^ ← SimplifyPObj[pobjs^];
[] ← SymTab.Store[nodes, new, val];
};
EachFlatWire: CoreGeometry.EachFlatWireProc = {
EachInstance: CoreGeometry.EachInstanceProc = {
geometry^ ← CONS [IntanceToPObj[CoreGeometry.Transform[trans, instance]], geometry^];
};
name: ROPE ← CoreFlat.WirePathRope[ct, flatWire];
geometry: REF LIST OF PObj ← NARROW [SymTab.Fetch[table, name].val];
IF geometry=NIL THEN {geometry ← NEW [LIST OF PObj ← NIL]; [] ← SymTab.Store[table, name, geometry]};
[] ← CoreGeometry.EnumerateGeometry[SinixRawCMosB.mode.decoration, wire, EachInstance];
};
table: SymTab.Ref ← SymTab.Create[]; -- Table FlatWireRope -> REF LIST OF PObj
nodes: SymTab.Ref ← SymTab.Create[]; -- Table Real names -> REF LIST OF PObj
result: REF = Sinix.Extract[obj, SinixRawCMosB.mode, NIL, NEW [INT ← 40]].result;
ct: Core.CellType;
IF result=NIL OR NOT ISTYPE[result, Core.CellType] THEN ERROR;
ct ← NARROW [result];
[] ← CoreGeometry.EnumerateFlatGeometry[SinixRawCMosB.mode.decoration, ct, Leaf, EachFlatWire];
We change all names that contain *[]/. if any!
[] ← SymTab.Pairs[table, FiddleName];
The final cell
routing ← CDRoutingObjects.CreateRoutingObject[CDRoutingObjects.CreateNodes[nodes], CD.InterestRect[obj]];
TerminalIO.PutF["Object %g translated to routing: %g nodes.\n", IO.rope[PW.Name[obj]], IO.int[SymTab.GetSize[table]]];
};
Replacing RoutingCells throughout the design
Prune: PROC [design: CD.Design] = {
TerminalIO.PutF["Pruning ... "];
CDDirectoryOps.PruneDirectory[design];
TerminalIO.PutF["done.\n"];
};
PruneAndSave: PROC [design: CD.Design, file: ROPE] = {
Prune[design];
[] ← CDIO.WriteDesign[design: design, to: file];
};
ReplaceAllRoutingCells: PROC [design: CD.Design, file: ROPE, saveEach: INT ← 10] RETURNS [replaced: INT ← 0] = {
toBeReplaced: CD.Object;
firstPass: BOOLTRUE;
ReplaceRoutingCells: CDDirectory.EachObjectProc = {
name: Rope.ROPE ← CDDirectory.Name[me, design];
IF NOT CDCells.IsCell[me] THEN RETURN;
IF CountTransistors[me]#0 THEN RETURN;
IF CDCells.CountInstances[me]=1 THEN RETURN; -- this is to deal with unnamed cells just containing a pin and other junk
IF name=NIL AND firstPass THEN RETURN;
IF CDProperties.GetObjectProp[me, $RawCMosBExtractProc]#NIL THEN RETURN;
toBeReplaced ← me;
TerminalIO.PutF["### Replacing routing cell '%g'...\n", IO.rope[name]];
quit ← TRUE;
};
WHILE CDDirectory.EnumerateDesign[design: design, proc: ReplaceRoutingCells, top: FALSE] DO
name: Rope.ROPE ← CDDirectory.Name[toBeReplaced, design];
new: CD.Object ← ToRoutingCell[toBeReplaced];
CDDirectory.ReplaceObject[design, toBeReplaced, new];
[] ← CDDirectory.Remove[design, name, toBeReplaced];
IF Rope.Fetch[name]#'- THEN [] ← CDDirectory.Include[design, new, name];
TerminalIO.PutF["Done replacing routing cell '%g'!\n", IO.rope[name]];
replaced ← replaced + 1;
IF replaced MOD saveEach = 0 THEN PruneAndSave[design, file];
ENDLOOP;
TerminalIO.PutF["=== %g objects replaced in the directory.\nPruning ... ", IO.int[replaced]];
Prune[design];
firstPass ← FALSE;
WHILE CDDirectory.EnumerateDesign[design: design, proc: ReplaceRoutingCells, dir: FALSE] DO
name: Rope.ROPECD.Describe[toBeReplaced];
new: CD.Object ← ToRoutingCell[toBeReplaced];
CDDirectory.ReplaceObject[design, toBeReplaced, new];
TerminalIO.PutF["Done replacing routing cell '%g'!\n", IO.rope[name]];
replaced ← replaced + 1;
IF replaced MOD saveEach = 0 THEN PruneAndSave[design, file];
ENDLOOP;
CDDirectoryOps.RemoveProperties[design, $TransistorCount];
PruneAndSave[design, file];
};
END.