PWCLayoutCheckpointImpl.mesa 
Copyright © 1985 by Xerox Corporation. All rights reversed.
Bertrand Serlet July 22, 1986 2:45:27 am PDT
Curry, September 21, 1986 1:48:47 pm PDT
DIRECTORY CD, CDBasics, CDDirectory, CDInstances, CDIO, CDOps, CDProperties, CDRects, CDValue, CDViewer, Convert, Core, CoreIO, CoreOps, CoreGeometry, CoreProperties, HashTable, IO, PWCLayoutCheckpoint, PW, PWC, Rope;
PWCLayoutCheckpointImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDDirectory, CDInstances, CDIO, CDOps, CDProperties, CDRects, CDValue, CDViewer, Convert, CoreIO, CoreOps, CoreGeometry, CoreProperties, HashTable, IO, PW, PWC, Rope
EXPORTS PWCLayoutCheckpoint
SHARES CDRects =
BEGIN
CellType: TYPE = Core.CellType;
ROPE:  TYPE = Core.ROPE;
Wire:  TYPE = Core.Wire;
Storing and retrieving entire Core + Layout
Store: PUBLIC PROC [cellType: CellType] = {
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]};
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 from %g.core\n", IO.rope[name]];
SetFromCheckpoint[cellType]};
Storing and retrieving layout
Checkpoint: PUBLIC PROC [cellType: CellType, withCuteFonts: BOOLFALSE] = {
sourceObj:  CD.Object  ← PWC.Layout[cellType];
ir:     CD.Rect  ← PWC.InterestRect[cellType];
name:    ROPE   ← CoreOps.GetCellTypeName[cellType];
layoutFileName: ROPE   ← IO.PutFR["%gLayout", IO.rope[name]];
shellFileName: ROPE   ← IO.PutFR["%gShell", IO.rope[name]];
layoutDesign: CD.Design ← CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
shellDesign:  CD.Design ← CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
layout:   CD.Object  ← PW.CreateEmptyCell[];
shell:    CD.Object;
tCount: INTPWC.CountTransistors[cellType];
PW.WriteF["Making shell for cell %g\n", IO.rope[name]];
shell ← PWC.CellShell[cellType];
[] ← PW.IncludeInCell[layout, sourceObj];
PW.SetInterestRect[layout, CD.InterestSize[sourceObj]];
PW.RepositionCell[layout];
layoutDesign.name ← layoutFileName;
shellDesign.name ← shellFileName;
[] ← CDDirectory.Include[layoutDesign, layout, name];
[] ← CDDirectory.Include[shellDesign, shell,  name];
CDOps.IncludeObjectI[layoutDesign, sourceObj];
CDOps.IncludeObjectI[shellDesign, shell];
CDValue.Store[layoutDesign, $KeepObjects, $KeepObjects]; -- to avoid finalization!!!
CDValue.Store[shellDesign, $KeepObjects, $KeepObjects]; -- to avoid finalization!!!
We want to store the ir and tCnt Props of the CellType on the Shell
CDProperties.PutDesignProp[shellDesign, PWC.transistorCount, NEW [INT ← tCount]];
CDProperties.PutDesignProp[shellDesign, $IRX1, NEW [INT ← ir.x1]];
CDProperties.PutDesignProp[shellDesign, $IRX2, NEW [INT ← ir.x2]];
CDProperties.PutDesignProp[shellDesign, $IRY1, NEW [INT ← ir.y1]];
CDProperties.PutDesignProp[shellDesign, $IRY2, NEW [INT ← ir.y2]];
PW.WriteF["Writing layout for cell %g\n", IO.rope[name]];
[] ← CDIO.WriteDesign[layoutDesign, layoutFileName];
PW.WriteF["Writing shell for cell %g\n", IO.rope[name]];
[] ← CDIO.WriteDesign[shellDesign, shellFileName];
PW.WriteF["Layout checkpoint stored in %g.dale and %g.dale\n",
IO.rope[layoutFileName], IO.rope[shellFileName]]};
SetFromCheckpoint: PROC [cellType: CellType] = {
we hack a lit bit to be lazy
RetrieveDecorate[cellType, NIL];
PWC.SetLayout[cellType, $RetrieveLayout]};
designs: HashTable.Table ←
HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
OpenDesign: PROC[name: ROPE] RETURNS[design: CD.Design] = {
design ← NARROW[HashTable.Fetch[designs, name].value];
IF design#NIL THEN RETURN[design];
design ← CDViewer.FindDesign[name];  [] ← HashTable.Store[designs, name, design];
IF design#NIL THEN RETURN[design];
design ← PW.OpenDesign[name];    [] ← HashTable.Store[designs, name, design]};
RetrieveLayout: PWC.LayoutProc = {
fileName: ROPENARROW [cellType.data];
name:  ROPE ← Rope.Substr[fileName, 0 , Rope.Length[fileName]-5]; -- strip ".core"
layoutFileName: ROPEIO.PutFR["%gLayout", IO.rope[name]];
layoutDesign: CD.Design ← OpenDesign[layoutFileName];
obj ← PW.Get[layoutDesign, name];
IF CD.InterestRect[obj]#PWC.InterestRect[cellType] THEN ERROR};
RetrieveDecorate: PWC.DecorateProc = {
fileName:   ROPENARROW [cellType.data];
name:    ROPE ← Rope.Substr[fileName, 0 , Rope.Length[fileName]-5]; -- strip ".core"
shellFileName: ROPEIO.PutFR["%gShell", IO.rope[name]];
shellDesign:  CD.Design ← OpenDesign[shellFileName];
tCountRef:  REF INT
NARROW [CDProperties.GetDesignProp[shellDesign, PWC.transistorCount]];
ir:     CD.Rect ← [
x1: NARROW [CDProperties.GetDesignProp[shellDesign, $IRX1], REF INT]^,
x2: NARROW [CDProperties.GetDesignProp[shellDesign, $IRX2], REF INT]^,
y1: NARROW [CDProperties.GetDesignProp[shellDesign, $IRY1], REF INT]^,
y2: NARROW [CDProperties.GetDesignProp[shellDesign, $IRY2], REF INT]^ ];
shell:  CD.Object  ← PW.Get  [shellDesign, name];
cellPtr: CD.CellPtr ← NARROW [shell.specificRef];
offset:  CD.Position ← CDBasics.SubPoints
[CDBasics.BaseOfRect[ir], CDBasics.BaseOfRect[CD.InterestRect[shell]]];
IF CD.InterestSize[shell]#CDBasics.SizeOfRect[ir] THEN ERROR;
CoreProperties.PutCellTypeProp[cellType, $PWCShell, shell];
CoreGeometry.PutIR[PWC.extractMode.decoration, cellType, ir];
IF tCountRef#NIL THEN CoreProperties.PutCellTypeProp
[cellType, PWC.transistorCount, NEW [INT ← tCountRef^]];
FOR list: LIST OF CD.Instance ← cellPtr.contents, list.rest WHILE list#NIL DO
wireName: ROPE;
wire:   Wire;
instance:  CD.Instance;
IF list.first.ob.class # CDRects.bareRectClass THEN LOOP;
instance ← NEW [CD.InstanceRep ← list.first^]; instance.properties ← NIL;
wireName ← NARROW [CDProperties.GetInstanceProp[list.first, $InstanceName]];
wire  ← FindWire[cellType.public, wireName];
IF wireName=NIL OR wire=NIL THEN ERROR;
CDInstances.Translate[instance, offset];
AddUniquePinsProp[PWC.extractMode.decoration, wire, instance];
ENDLOOP};
FindWire: PROC[wire: Wire, name: ROPE] RETURNS[Wire] = {
base:  ROPE;
names: LIST OF ROPE;
IF (wire ← CoreOps.FindWire[wire, name]) # NIL THEN
RETURN[wire];
[base, names] ← CoreOps.ParseWireName[name];
names ← CONS[base, names];
FOR names ← names, names.rest WHILE names # NIL DO
SELECT names.first.Fetch[] FROM
IN ['0..'9] => wire ← wire[Convert.IntFromRope[names.first]];
ENDCASE => {
FOR i: NAT IN [0..wire.size) DO
IF ~Rope.Equal[names.first, CoreOps.GetShortWireName[wire[i]]] THEN LOOP;
wire ← wire[i]; EXIT;
REPEAT FINISHED => ERROR ENDLOOP};
ENDLOOP;
RETURN[wire]};
AddUniquePinsProp: PROC
[decoration: CoreGeometry.Decoration, wire: Wire, pin: CD.Instance] = {
FOR pins: LIST OF CD.Instance ← CoreGeometry.GetPins[decoration, wire], pins.rest
WHILE pins#NIL DO IF pins.first^=pin^ THEN RETURN ENDLOOP;
CoreGeometry.PutPins[decoration, wire, CONS[pin, CoreGeometry.GetPins[decoration, wire]]]};
Initialization
[] ← PWC.RegisterLayoutAtom[$RetrieveLayout, RetrieveLayout, RetrieveDecorate];
END.