CoreGeometryIOImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Bertrand Serlet March 10, 1987 3:12:24 am PST
Barth, December 4, 1986 6:01:02 pm PST
DIRECTORY
CD, CDAtomicObjects, CDCells, CDPrivate, CDRects, CDTexts, CDSymbolicObjects,
CMosB, CMosBWellDifImpl,
Convert,
Core, CoreIO, CoreClasses, CoreOps, CoreProperties, CoreGeometry, CoreGeometryImpl,
GList, HashTable, Rope, PWObjects, Sinix;
CoreGeometryIOImpl:
CEDAR
PROGRAM
IMPORTS CD, CDAtomicObjects, CDCells, CDPrivate, CDRects, CDSymbolicObjects, CDTexts, CMosB, CMosBWellDifImpl, Convert, CoreIO, CoreClasses, CoreGeometry, CoreOps, CoreProperties, GList, HashTable, Rope, PWObjects, Sinix
SHARES CDCells, CDRects, CDTexts, CDSymbolicObjects, CoreGeometry, CoreGeometryImpl, CMosBWellDifImpl =
BEGIN OPEN CoreIO;
The following classes are not saved even though they are loaded with CMosB. This assumes that they are not atomic objects.
CDImportsImpl $Import
CDRepetitionsImpl $Repetitions
CDRectsImpl $SaveRect
CDCurvesImpl $FilledCurve0, $Line0, $Polygon0, $Spline0
CDOpsImpl $GCollected
CDPolygonsImpl $Polygon
Object Class Registration
objectClassRegistry: HashTable.Table ← HashTable.Create[];
ObjectClassData: TYPE = REF ObjectClassDataRec;
ObjectClassDataRec:
TYPE =
RECORD [
write: ObjectClassWriteProc ← NIL,
read: ObjectClassReadProc ← NIL];
ObjectClassWriteProc:
TYPE =
PROC [h: Handle, me:
CD.Object];
ObjectClassReadProc:
TYPE =
PROC [h: Handle]
RETURNS [obj:
CD.Object];
RegisterObjectClass:
PROC [objectClass:
CD.ObjectClass, write: ObjectClassWriteProc, read: ObjectClassReadProc] = {
data: ObjectClassData ← NEW[ObjectClassDataRec ← [write, read]];
IF write=NIL OR read=NIL THEN ERROR; -- if only one NIL then invariant for object write/read is broken
[] ← HashTable.Store[objectClassRegistry, objectClass.objectType, data];
};
Low Level IO Utilities
WritePosition:
PROC [h: Handle, position:
CD.Position] = {
WriteInt[h, position.x];
WriteInt[h, position.y];
};
ReadPosition:
PROC [h: Handle]
RETURNS [position:
CD.Position] = {
position.x ← ReadInt[h];
position.y ← ReadInt[h];
};
WriteRect:
PROC [h: Handle, rect:
CD.Rect] = {
WriteInt[h, rect.x1]; WriteInt[h, rect.y1];
WriteInt[h, rect.x2]; WriteInt[h, rect.y2];
};
ReadRect:
PROC [h: Handle]
RETURNS [rect:
CD.Rect] = {
rect.x1 ← ReadInt[h]; rect.y1 ← ReadInt[h];
rect.x2 ← ReadInt[h]; rect.y2 ← ReadInt[h];
};
WriteLayer:
PROC [h: Handle, layer:
CD.Layer] = {
WriteAtom[h, CD.LayerKey[layer]];
};
ReadLayer:
PROC [h: Handle]
RETURNS [layer:
CD.Layer] = {
layer ← CD.FetchLayer[CMosB.cmosB, ReadAtom[h]];
};
WriteOrient:
PROC [h: Handle, orient:
CD.Orientation] = {
WriteInt[h, ORD[orient]];
};
ReadOrient:
PROC [h: Handle]
RETURNS [orient:
CD.Orientation] = {
aux: [ORD[FIRST[CD.Orientation]] .. ORD[LAST[CD.Orientation]]] ← NAT [ReadInt[h]];
orient ← LOOPHOLE [aux];
};
WriteTrans:
PROC [h: Handle, trans:
CD.Transformation] = {
WritePosition[h, trans.off];
WriteOrient[h, trans.orient];
};
ReadTrans:
PROC [h: Handle]
RETURNS [trans:
CD.Transformation] = {
off: CD.Position ← ReadPosition[h];
trans ← [off, ReadOrient[h]];
};
WriteCDProperties:
PROC [h: Handle, properties:
CD.PropList] = {
props: Core.Properties ← NIL;
WHILE properties#
NIL
DO
IF ISTYPE [properties.first.key, ATOM] THEN props ← CoreProperties.PutProp[props, NARROW [properties.first.key], properties.first.val];
properties ← properties.rest;
ENDLOOP;
WriteProperties[h, props];
};
ReadCDProperties:
PROC [h: Handle]
RETURNS [properties:
CD.PropList ←
NIL] = {
Consume:
PROC [key:
ATOM, val:
REF] = {
properties ← CONS [[key, val], properties];
};
CoreProperties.Enumerate[ReadProperties[h], Consume];
};
Object Class IO Utilities
WriteCDInstance:
PROC [h: Handle, instance:
CD.Instance] = {
WriteObject[h, instance.ob];
WriteTrans[h, instance.trans];
WriteCDProperties[h, instance.properties];
};
ReadCDInstance:
PROC [h: Handle]
RETURNS [instance:
CD.Instance] = {
instance ← NEW [CD.InstanceRep ← [ob: ReadObject[h]]];
instance.trans ← ReadTrans[h];
instance.properties ← ReadCDProperties[h];
};
WriteCDInstances:
PROC [h: Handle, instances:
LIST
OF
CD.Instance] = {
WriteInt[h, GList.Length[instances]];
WHILE instances#
NIL
DO
WriteCDInstance[h, instances.first];
instances ← instances.rest;
ENDLOOP;
};
ReadCDInstances:
PROC [h: Handle]
RETURNS [instances:
LIST
OF
CD.Instance ←
NIL] = {
THROUGH [1 .. ReadInt[h]]
DO
instances ← CONS [ReadCDInstance[h], instances];
ENDLOOP;
};
WriteInstance:
PROC [h: Handle, instance: CoreGeometry.Instance] = {
WriteObject[h, instance.obj];
WriteTrans[h, instance.trans];
};
ReadInstance:
PROC [h: Handle]
RETURNS [instance: CoreGeometry.Instance] = {
obj: CD.Object ← ReadObject[h];
instance ← [obj, ReadTrans[h]];
};
WriteInstances:
PROC [h: Handle, instances: CoreGeometry.Instances] = {
WriteInt[h, CoreGeometry.Length[instances]];
WHILE instances#
NIL
DO
WriteInstance[h, instances.first];
instances ← instances.rest;
ENDLOOP;
};
ReadInstances:
PROC [h: Handle]
RETURNS [instances: CoreGeometry.Instances ←
NIL] = {
THROUGH [0 .. ReadInt[h])
DO
instances ← CONS [ReadInstance[h], instances];
ENDLOOP;
};
CoreGeometryImpl.InstanceSeq Should be exported properly
WriteInstanceSeq:
PROC [h: Handle, instances: CoreGeometryImpl.InstanceSeq] = {
WriteInt[h, instances.size];
FOR i: NAT IN [0 .. instances.size) DO WriteInstance[h, instances[i]] ENDLOOP;
};
objectsAtom:
ATOM = RegisterProperty[$CoreGeometryIOObjects, WriteObjectsProp, ReadObjectsProp];
The prop write and read procedures are only called when the hash tables are initialized for reading, never for writing.
WriteObjectsProp: PropWriteProc = {
WriteHashTable[h, NARROW[value], WriteObjectIDPair];
};
ReadObjectsProp: PropReadProc = {
value ← ReadHashTable[h, ReadObjectIDPair, HashTable.RopeEqual, HashTable.HashRope];
};
WriteObjectIDPair: HashWriteProc = {
id: ROPE ← NARROW[key];
object: CD.Object ← NARROW[value];
WriteID[h, id];
WriteObject[h, object];
};
ReadObjectIDPair: HashReadProc = {
key ← ReadID[h];
value ← ReadObject[h];
};
A HashTable [CD.Object -> Rope ID] is stored on the handle under the key objectsAtom
CMosBObsImpl $C2DifShortCon, $C2LargeSimpleCon, $C2LargeVia, $C2LargeWellSimpleCon, $C2LTrans, $C2LWellTrans, $C2SimpleCon, $C2Trans, $C2Via, $C2WellDifShortCon, $C2WellSimpleCon, $C2WellTrans, $CLWellTrans
WriteObject:
PROC [h: Handle, obj:
CD.Object] = {
objects: HashTable.Table ← NARROW [CoreProperties.GetProp[h.properties, objectsAtom]];
objectID: ROPE ← NIL;
IF objects=
NIL
THEN {
objects ← HashTable.Create[];
h.properties ← CoreProperties.PutProp[h.properties, objectsAtom, objects];
};
objectID ← NARROW [HashTable.Fetch[objects, obj].value];
IF objectID=
NIL
THEN {
classData: ObjectClassData ← NARROW[HashTable.Fetch[objectClassRegistry, obj.class.objectType].value];
objectID ← Rope.Cat["O", Convert.RopeFromInt[from: HashTable.GetSize[objects], base: 16, showRadix: FALSE]];
IF NOT HashTable.Insert[objects, obj, objectID] THEN ERROR;
WriteID[h, objectID];
WriteAtom[h, obj.class.objectType];
IF classData=
NIL
THEN {
IF CDAtomicObjects.IsAtomicOb[obj]
THEN {
WritePosition[h, CD.InterestSize[obj]];
WriteLayer[h, obj.layer];
}
ELSE ERROR; -- no write proc and not atomic
}
ELSE classData.write[h, obj];
WriteCDProperties[h, obj.properties];
}
ELSE WriteID[h, objectID];
};
A HashTable [Rope ID -> CD.Object] is stored on the handle under the key objectsAtom
ReadObject:
PROC [h: Handle]
RETURNS [obj:
CD.Object] = {
objects: HashTable.Table ← NARROW [CoreProperties.GetProp[h.properties, objectsAtom]];
objectID: ROPE;
IF objects=
NIL
THEN {
objects ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
h.properties ← CoreProperties.PutProp[h.properties, objectsAtom, objects];
};
objectID ← ReadID[h];
IF Rope.Fetch[objectID]#'O THEN ERROR;
obj ← NARROW [HashTable.Fetch[objects, objectID].value];
IF obj=
NIL
THEN {
classAtom: ATOM ← ReadAtom[h];
classData: ObjectClassData ← NARROW[HashTable.Fetch[objectClassRegistry, classAtom].value];
IF classData=
NIL
THEN {
pos: CD.Position ← ReadPosition[h];
layer: CD.Layer ← ReadLayer[h];
obj ← CDAtomicObjects.CreateAtomicOb[classAtom, pos, CMosB.cmosB, layer];
}
ELSE obj ← classData.read[h];
obj.properties ← ReadCDProperties[h];
IF NOT HashTable.Insert[objects, objectID, obj] THEN ERROR;
};
};
CoreIO Object Property IO
InstancesPropWrite: PropWriteProc = {
WITH value
SELECT
FROM
instances: CoreGeometryImpl.InstanceSeq => WriteInstanceSeq[h, instances];
instances: CoreGeometry.Instances => WriteInstances[h, instances];
lazyProc:
REF CoreGeometry.LazyEnumerateProc => {
Hack for routing cell
instances: CoreGeometry.Instances ← NIL;
AddEach: CoreGeometry.EachInstanceProc = {instances ← CONS [instance, instances]};
[] ← lazyProc[NIL, h.wire, AddEach];
WriteInstances[h, instances];
};
ENDCASE => ERROR;
};
InstancesPropRead: PropReadProc = {value ← ReadInstances[h]};
ObjectPropWrite: PropWriteProc = {WriteObject[h, NARROW [value]]};
ObjectPropRead: PropReadProc = {value ← ReadObject[h]};
TransPropWrite: PropWriteProc = {WriteTrans[h, NARROW [value, REF CD.Transformation]^]};
TransPropRead: PropReadProc = {value ← NEW [CD.Transformation ← ReadTrans[h]]};
Object Class IO
CMosBWellDifImpl $C2NDifRect, $C2PDifRect; CDRectsImpl $Rect
WriteRectangle: ObjectClassWriteProc = {
WritePosition[h, CD.InterestSize[me]];
WriteLayer[h, me.layer];
};
ReadRectangle: ObjectClassReadProc = {
sz: CD.Position = ReadPosition[h];
l: CD.Layer = ReadLayer[h];
ob: CD.Object = CDRects.CreateRect[sz, l];
RETURN [ob]
};
CDCellsImpl $Cell
WriteCell: ObjectClassWriteProc = {
ConsInstance: CDCells.InstEnumerator = {insts ← CONS [inst, insts]};
insts: LIST OF CD.Instance ← NIL;
cellPtr: CD.CellSpecific ← NARROW [me.specific];
[] ← CDCells.EnumerateInstances[me, ConsInstance];
WriteRect[h, me.bbox];
WriteCDInstances[h, insts];
WriteRect[h, cellPtr.ir];
WriteRope[h, cellPtr.name];
WriteReal[h, cellPtr.simplifyOn];
WriteAtom[h, IF cellPtr.drawBorder THEN $TRUE ELSE $FALSE];
WriteAtom[h, IF cellPtr.specifiedIr THEN $TRUE ELSE $FALSE];
};
ReadCell: ObjectClassReadProc = {
cellPtr: CD.CellSpecific ← NEW [CD.CellRep];
obj ← NEW [CD.ObjectRep ← [class: CDCells.pCellClass]];
obj.bbox ← ReadRect[h];
cellPtr.contents ← ReadCDInstances[h];
cellPtr.ir ← ReadRect[h];
cellPtr.name ← ReadRope[h];
cellPtr.simplifyOn ← ReadReal[h];
cellPtr.drawBorder ← ReadAtom[h]=$TRUE;
cellPtr.specifiedIr ← ReadAtom[h]=$TRUE;
obj.specific ← cellPtr;
CDCells.ToSequenceMode[obj];
};
PWObjects $RoutingClass
WriteRouting: ObjectClassWriteProc = {
routing: PWObjects.RoutingSpecific ← NARROW [me.specific];
WriteRect[h, me.bbox];
WriteInt[h, routing.size];
WriteRect[h, routing.ir];
FOR i:
NAT
IN [0 .. routing.size)
DO
node: PWObjects.Node = routing[i];
WriteInt[h, node.size];
WriteCDProperties[h, node.properties];
FOR j:
NAT
IN [0 .. node.size)
DO
WriteObject[h, node[j].object];
WritePosition[h, node[j].position];
ENDLOOP;
ENDLOOP;
};
ReadRouting: ObjectClassReadProc = {
bbox: CD.Rect ← ReadRect[h];
size: NAT ← NAT [ReadInt[h]];
routing: PWObjects.RoutingSpecific ← NEW [PWObjects.RoutingRep[size]];
routing.ir ← ReadRect[h];
FOR i:
NAT
IN [0 .. size)
DO
nb: NAT ← NAT [ReadInt[h]];
node: PWObjects.Node = NEW [PWObjects.NodeRep[nb]];
node.properties ← ReadCDProperties[h];
FOR j:
NAT
IN [0 .. nb)
DO
object: CD.Object ← ReadObject[h];
node[j] ← [object: object, position: ReadPosition[h]];
ENDLOOP;
routing[i] ← node;
ENDLOOP;
obj ← NEW [CD.ObjectRep ← [class: PWObjects.routingClass, specific: routing, bbox: bbox]];
};
CDSymbolicObjectsImpl $AlignmentMarkOb, $PinOb0, $SymbolicSegment
WriteMark: ObjectClassWriteProc = {
};
ReadMark: ObjectClassReadProc = {
RETURN[CDSymbolicObjects.CreateMark[]];
};
WriteSegment: ObjectClassWriteProc = {
WritePosition[h, CD.InterestSize[me]];
};
ReadSegment: ObjectClassReadProc = {
p: CD.Position ← ReadPosition[h];
RETURN [CDSymbolicObjects.CreateSegment[p.y, p.x]]
};
WritePin: ObjectClassWriteProc = {
WritePosition[h, CD.InterestSize[me]];
};
ReadPin: ObjectClassReadProc = {
RETURN [CDSymbolicObjects.CreatePin[ReadPosition[h]]]
};
CDTextsImpl $FlipText, $RigidText
WriteText: ObjectClassWriteProc = {
text: CDTexts.TextSpecific ← NARROW [me.specific];
WriteRope[h, text.text];
WriteRope[h, text.cdFont.supposedName];
WriteInt[h, text.cdFont.scaleI];
};
ReadText: ObjectClassReadProc = {
text: ROPE ← ReadRope[h];
fontName: ROPE ← ReadRope[h];
scale: INT ← ReadInt[h];
font: CDTexts.CDFont ← CDTexts.MakeFont[fontName, scale];
obj ← CDTexts.Create[text, font];
};
Making Decorations Explicit and test function
Explicit:
PROC [decoration: CoreGeometry.Decoration, cellType: Core.CellType] = {
ExplicitWire: CoreOps.EachWireProc = {
CoreGeometry.PutPins[decoration, wire, CoreGeometry.GetPins[decoration, wire]];
CoreGeometry.PutGeometry[decoration, wire, CoreGeometry.GetGeometry[decoration, wire]];
};
IF CoreProperties.GetCellTypeProp[cellType, $Explicit]#NIL THEN RETURN;
CoreProperties.PutCellTypeProp[cellType, $Explicit, $Explicit];
[] ← CoreOps.VisitWireSeq[cellType.public, ExplicitWire];
SELECT cellType.class
FROM
CoreClasses.recordCellClass => {
rct: CoreClasses.RecordCellType = NARROW [cellType.data];
[] ← CoreOps.VisitWireSeq[rct.internal, ExplicitWire];
FOR i: NAT IN [0 .. rct.size) DO Explicit[decoration, rct[i].type] ENDLOOP;
};
ENDCASE => {};
};
Test:
PROC [obj:
CD.Object, mode: Sinix.Mode]
RETURNS [new:
CD.Object] = {
ct: Core.CellType ← NARROW [Sinix.Extract[obj, mode].result];
name: ROPE ← CoreOps.GetCellTypeName[ct];
Explicit[mode.decoration, ct];
[] ← CoreIO.ReportSaveCellType[ct];
ct ← CoreIO.RestoreCellType[name];
ct ← CoreOps.Recast[ct];
new ← CoreGeometry.GetObject[mode.decoration, ct];
};
Hack for Pins (one more time!)
WriteLayerRef: PropWriteProc = {
WriteLayer[h, NARROW [value, CDPrivate.LayerRef].number];
};
ReadLayerRef: PropReadProc = {
value ← CDPrivate.layers[ReadLayer[h]];
};
Initialization
Register:
PROC [decoration: CoreGeometry.Decoration] = {
[] ← RegisterProperty[decoration.objectProp, ObjectPropWrite, ObjectPropRead];
[] ← RegisterProperty[decoration.pinsProp, InstancesPropWrite, InstancesPropRead];
[] ← RegisterProperty[decoration.geometryProp, InstancesPropWrite, InstancesPropRead];
[] ← RegisterProperty[decoration.transProp, TransPropWrite, TransPropRead];
};
[] ← RegisterProperty[$layerOfPin, WriteLayerRef, ReadLayerRef];
RegisterObjectClass[CDRects.bareRectClass, WriteRectangle, ReadRectangle];
RegisterObjectClass[CDCells.pCellClass, WriteCell, ReadCell];
RegisterObjectClass[PWObjects.routingClass, WriteRouting, ReadRouting];
RegisterObjectClass[CDSymbolicObjects.markClass, WriteMark, ReadMark];
RegisterObjectClass[CDSymbolicObjects.segmentClass, WriteSegment, ReadSegment];
RegisterObjectClass[CDSymbolicObjects.pinClass, WritePin, ReadPin];
RegisterObjectClass[CMosBWellDifImpl.wndifClass, WriteRectangle, ReadRectangle];
RegisterObjectClass[CMosBWellDifImpl.wpdifClass, WriteRectangle, ReadRectangle];
RegisterObjectClass[CDTexts.flipTextClass, WriteText, ReadText];
RegisterObjectClass[CDTexts.rigidTextClass, WriteText, ReadText];
END.