LayoutCheckpointImpl.mesa 
Copyright © 1985 by Xerox Corporation. All rights reversed.
Bertrand Serlet June 3, 1986 11:21:55 pm PDT
DIRECTORY CD, CDBasics, CDCleanUp, CDDirectory, CDInstances, CDIO, CDOps, CDProperties, CDRects, CDSimpleRules, CDTexts, CDValue, Core, CoreClasses, CoreIO, CoreOps, CoreProperties, HashTable, IO, LayoutCheckpoint, PW, PWCore, Sinix;
LayoutCheckpointImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCleanUp, CDDirectory, CDInstances, CDIO, CDOps, CDProperties, CDRects, CDSimpleRules, CDTexts, CDValue, CoreClasses, CoreIO, CoreOps, CoreProperties, HashTable, IO, PW, PWCore, Sinix
EXPORTS LayoutCheckpoint
SHARES CDRects, PWCore =
BEGIN OPEN LayoutCheckpoint;
Storing and retrieving entire Core + Layout
Store: PUBLIC PROC [cellType: CellType, withCuteFonts: BOOLFALSE] = {
props: LIST OF ATOM;
classes: LIST OF Core.CellClass;
name: ROPE ← CoreOps.GetCellTypeName[cellType];
PW.WriteF["Saving the Core for cell %g ...\n", IO.rope[name]];
[props, classes] ← CoreIO.ReportSaveCellType[cellType];
PW.WriteF["... core stored in %g.core ...\n", IO.rope[name]];
Checkpoint[cellType, withCuteFonts];
};
Retrieve: PUBLIC PROC [name: ROPE] RETURNS [cellType: CellType] = {
PW.WriteF["Retrieving the Core for cell %g ...\n", IO.rope[name]];
cellType ← CoreIO.RestoreCellType[name];
PW.WriteF["... core retrieved in %g.core ...\n", IO.rope[name]];
SetFromCheckpoint[cellType];
};
Storing and retrieving layout
Checkpoint: PUBLIC PROC [cellType: CellType, withCuteFonts: BOOLFALSE] = {
font: CDTexts.CDFont ← CDTexts.MakeFont["Xerox/TiogaFonts/Helvetica8", 4];
fontTable: HashTable.Table ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
CreateText: PROC [name: ROPE] RETURNS [obj: CD.Object] = {
obj ← NARROW [HashTable.Fetch[fontTable, name].value];
IF obj#NIL THEN RETURN;
obj ← CDTexts.CreateText[name, font];
[] ← HashTable.Store[fontTable, name, obj];
};
EachWirePin: PWCore.EachWirePinProc = {
minW: INT ← CDSimpleRules.MinWidth[layer];
wireName: ROPE ← CoreOps.GetFullWireName[cellType.public, wire];
pos: CD.Position ← SELECT side FROM
left => [0, min],
right => [iSize.x-minW, min],
top => [min, iSize.y-minW],
bottom => [min, 0],
ENDCASE => ERROR;
inst: CD.Instance ← PW.IncludeInCell[shell, CDSimpleRules.Rect[IF side=left OR side=right THEN [minW, max-min] ELSE [max-min, minW], layer], pos];
inst.properties ← CDProperties.DCopyProps[instance.properties];
CDProperties.PutInstanceProp[inst, $InstanceName, wireName];
IF withCuteFonts THEN [] ← PW.IncludeInCell[
shell,
CreateText[wireName],
SELECT side FROM left => [pos.x-300, pos.y], right => [pos.x+minW+10, pos.y], top => [pos.x, pos.y+minW+10], bottom => [pos.x, pos.y-300], ENDCASE => ERROR,
SELECT side FROM left, right => 0, top, bottom => 2, ENDCASE => ERROR
];
};
sourceObj: CD.Object ← PWCore.Layout[cellType];
iSize: CD.Position ← CD.InterestSize[sourceObj];
name: ROPE ← CoreOps.GetCellTypeName[cellType];
layoutFileName: ROPEIO.PutFR["%gLayout", IO.rope[name]];
shellFileName: ROPEIO.PutFR["%gShell", IO.rope[name]];
layoutDesign: CD.Design ← CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
shellDesign: CD.Design ← CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
shell: CD.Object ← PW.CreateEmptyCell[];
PW.WriteF["Making shell for cell %g ...\n", IO.rope[name]];
[] ← PWCore.EnumerateWirePins[cellType, EachWirePin];
PW.SetInterestRect[shell, iSize];
PW.RepositionCell[shell];
layoutDesign.name ← layoutFileName;
shellDesign.name ← shellFileName;
[] ← CDDirectory.Include[layoutDesign, sourceObj, name];
[] ← CDDirectory.Include[shellDesign, shell, name];
CDOps.IncludeObjectI[layoutDesign, sourceObj];
CDOps.IncludeObjectI[shellDesign, shell];
CDValue.Store[layoutDesign, $KeepObjects, $KeepObjects]; -- to avoid finalization!!! Have you ever seen objects of class: GCollected??
CDValue.Store[shellDesign, $KeepObjects, $KeepObjects]; -- to avoid finalization!!! Have you ever seen objects of class: GCollected??
CDCleanUp.CleanUp[layoutDesign];
CDCleanUp.CleanUp[shellDesign];
CleanUp[layoutDesign];
CleanUp[shellDesign];
[] ← CDIO.WriteDesign[layoutDesign, layoutFileName];
[] ← CDIO.WriteDesign[shellDesign, shellFileName];
FlushLayoutProperties[cellType];
PW.FlushSharedCache[];
SetFromCheckpoint[cellType];
PW.WriteF["... layout checkpoint stored in %gLayout.dale and %gShell.dale\n", IO.rope[name], IO.rope[name]];
};
CleanUpOb: PROC [cleaned: HashTable.Table, obj: CD.Object] RETURNS [clean: CD.Object] = {
clean ← NARROW [HashTable.Fetch[cleaned, obj].value];
SELECT TRUE FROM
clean#NIL   => RETURN;
CDCells.IsCell[obj] => {
FOR instList: CD.InstanceList ← NARROW [obj.specificRef, CD.CellPtr].contents, instList.rest WHILE instList#NIL DO
instList.first.ob ← CleanUpOb[cleaned, instList.first.ob];
ENDLOOP;
clean ← obj;
};
obj.class.internalWrite#NIL => RETURN [obj];
ENDCASE   => {
clean ← CDDirectory.Expand[obj].new;
IF clean=NIL THEN ERROR;
clean ← CleanUpOb[cleaned, clean];
};
[] ← HashTable.Insert[cleaned, obj, clean];
};
CleanUp: PROC [design: CD.Design] = {
cleaned: HashTable.Table ← HashTable.Create[];
FOR instList: CD.InstanceList ← CDOps.InstList[design], instList.rest WHILE instList#NIL DO
instList.first.ob ← CleanUpOb[cleaned, instList.first.ob];
ENDLOOP;
};
SetFromCheckpoint: PUBLIC PROC [cellType: CellType] = {
PWCore.SetLayout[cellType, $RetrieveLayout];
};
RetrieveLayout: PWCore.LayoutProc = {
name: ROPE ← CoreOps.GetCellTypeName[cellType];
layoutFileName: ROPEIO.PutFR["%gLayout", IO.rope[name]];
layoutDesign: CD.Design ← PW.OpenDesign[layoutFileName];
obj ← PW.Get[layoutDesign, name];
};
RetrieveDecorate: PWCore.DecorateProc = {
name: ROPE ← CoreOps.GetCellTypeName[cellType];
shellFileName: ROPEIO.PutFR["%gShell", IO.rope[name]];
shellDesign: CD.Design ← PW.OpenDesign[shellFileName];
shell: CD.Object ← PW.Get[shellDesign, name];
cellPtr: CD.CellPtr ← NARROW [shell.specificRef];
offset: CD.Position ← CDBasics.SubPoints[CDBasics.BaseOfRect[CD.InterestRect[obj]], CDBasics.BaseOfRect[CD.InterestRect[shell]]];
IF CD.InterestSize[shell]#CD.InterestSize[obj] THEN ERROR;
FOR list: LIST OF CD.Instance ← cellPtr.contents, list.rest WHILE list#NIL DO
wireName: ROPENARROW [CDProperties.GetInstanceProp[list.first, $InstanceName]];
wire: Wire;
instance: CD.Instance ← CDInstances.Copy[list.first];
IF list.first.ob.class#CDRects.bareRectClass THEN LOOP;
wire ← CoreOps.FindWire[cellType.public, wireName];
IF wireName=NIL OR wire=NIL THEN ERROR;
CDInstances.Translate[instance, offset];
Sinix.AddPinsProp[PWCore.extractMode, wire, instance];
ENDLOOP;
};
Flushing Layout Properties
Warning: it is dangerous to use this function without being aware of PWCore implementation details.
FlushLayoutProperties: PUBLIC PROC [cellType: CellType] = {
FlushPin: PROC [wire: Wire] = {Sinix.PutPinsProp[PWCore.extractMode, wire, NIL]};
IF ~PWCore.HasLayout[cellType] THEN RETURN;
IF CoreProperties.GetCellTypeProp[cellType, PWCore.layoutAtomProp]=NIL THEN RETURN;
CoreOps.VisitAtomicWires[cellType.public, FlushPin];
PWCore.CancelLayout[cellType];
SELECT TRUE FROM
cellType.class=CoreClasses.recordCellClass => {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
FlushGeometry: PROC [wire: Wire] = {
Sinix.PutWireGeometryProp[PWCore.extractMode, wire, NIL];
};
CoreOps.VisitAtomicWires[cellType.public, FlushGeometry];
FOR i: NAT IN [0 .. data.size) DO
CoreProperties.PutCellInstanceProp[data[i], PWCore.extractMode.instanceProp, NIL];
FlushLayoutProperties[data[i].type];
ENDLOOP;
};
CoreOps.Recast[cellType]#NIL => FlushLayoutProperties[CoreOps.Recast[cellType]];
ENDCASE  => PWCore.Signal[];
};
Initialization
[] ← PWCore.RegisterLayoutAtom[$RetrieveLayout, RetrieveLayout, RetrieveDecorate];
END.