<> <> <> <> DIRECTORY CD, CDAtomicObjects, CDCells, CDPrivate, CDRects, CDRoutingObjects, CDTexts, CDSymbolicObjects, Convert, Core, CoreIO, CoreProperties, CoreGeometry, CoreGeometryBackdoor, GList, PW, RefTab, RefTabExtras, Rope; CoreGeometryIOImpl: CEDAR PROGRAM IMPORTS CD, CDAtomicObjects, CDCells, CDPrivate, CDRects, CDSymbolicObjects, CDRoutingObjects, CDTexts, Convert, CoreIO, CoreGeometry, CoreGeometryBackdoor, CoreProperties, GList, PW, RefTab, RefTabExtras, Rope EXPORTS CoreGeometryBackdoor SHARES CDCells, CDRects, CDTexts, CDSymbolicObjects, CoreGeometry = BEGIN OPEN CoreIO, CoreGeometry, CoreGeometryBackdoor; <> <> <> <> <> <> <> <> objectClassRegistry: RefTab.Ref _ RefTab.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: PUBLIC 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 [] _ RefTab.Store[objectClassRegistry, objectClass.objectType, data]; }; <> WritePosition: PUBLIC PROC [h: Handle, position: CD.Position] = { WriteInt[h, position.x]; WriteInt[h, position.y]; }; ReadPosition: PUBLIC PROC [h: Handle] RETURNS [position: CD.Position] = { position.x _ ReadInt[h]; position.y _ ReadInt[h]; }; WriteRect: PUBLIC PROC [h: Handle, rect: CD.Rect] = { WriteInt[h, rect.x1]; WriteInt[h, rect.y1]; WriteInt[h, rect.x2]; WriteInt[h, rect.y2]; }; ReadRect: PUBLIC PROC [h: Handle] RETURNS [rect: CD.Rect] = { rect.x1 _ ReadInt[h]; rect.y1 _ ReadInt[h]; rect.x2 _ ReadInt[h]; rect.y2 _ ReadInt[h]; }; WriteTechnology: PUBLIC PROC [h: Handle, technology: CD.Technology] = { WriteAtom[h, IF technology=NIL THEN $NILTechnology ELSE technology.key]; }; ReadTechnology: PUBLIC PROC [h: Handle] RETURNS [technology: CD.Technology] = { atom: ATOM _ ReadAtom[h]; technology _ IF atom=$NILTechnology THEN NIL ELSE CD.FetchTechnology[atom]; }; WriteLayer: PUBLIC PROC [h: Handle, layer: CD.Layer] = { WriteTechnology[h, CDPrivate.layers[layer].technology]; WriteAtom[h, CD.LayerKey[layer]]; }; ReadLayer: PUBLIC PROC [h: Handle] RETURNS [layer: CD.Layer] = { technology: CD.Technology _ ReadTechnology[h]; layer _ CD.FetchLayer[technology, ReadAtom[h]]; }; WriteOrient: PUBLIC PROC [h: Handle, orient: CD.Orientation] = { WriteInt[h, ORD[orient]]; }; ReadOrient: PUBLIC PROC [h: Handle] RETURNS [orient: CD.Orientation] = { aux: [ORD[FIRST[CD.Orientation]] .. ORD[LAST[CD.Orientation]]] _ NAT [ReadInt[h]]; orient _ LOOPHOLE [aux]; }; WriteTrans: PUBLIC PROC [h: Handle, trans: CD.Transformation] = { WritePosition[h, trans.off]; WriteOrient[h, trans.orient]; }; ReadTrans: PUBLIC PROC [h: Handle] RETURNS [trans: CD.Transformation] = { off: CD.Position _ ReadPosition[h]; trans _ [off, ReadOrient[h]]; }; WriteCDProperties: PUBLIC 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: PUBLIC PROC [h: Handle] RETURNS [properties: CD.PropList _ NIL] = { Consume: PROC [key: ATOM, val: REF] = { properties _ CONS [[key, val], properties]; }; CoreProperties.Enumerate[ReadProperties[h], Consume]; }; <> WriteCDInstance: PUBLIC PROC [h: Handle, instance: CD.Instance] = { WriteObject[h, instance.ob]; WriteTrans[h, instance.trans]; WriteCDProperties[h, instance.properties]; }; ReadCDInstance: PUBLIC PROC [h: Handle] RETURNS [instance: CD.Instance] = { instance _ NEW [CD.InstanceRep _ [ob: ReadObject[h]]]; instance.trans _ ReadTrans[h]; instance.properties _ ReadCDProperties[h]; }; WriteCDInstances: PUBLIC 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: PUBLIC PROC [h: Handle] RETURNS [instances: LIST OF CD.Instance _ NIL] = { THROUGH [1 .. ReadInt[h]] DO instances _ CONS [ReadCDInstance[h], instances]; ENDLOOP; }; WriteInstance: PUBLIC PROC [h: Handle, instance: Instance] = { WriteObject[h, instance.obj]; WriteTrans[h, instance.trans]; }; ReadInstance: PUBLIC PROC [h: Handle] RETURNS [instance: Instance] = { obj: CD.Object _ ReadObject[h]; instance _ [obj, ReadTrans[h]]; }; WriteInstances: PUBLIC PROC [h: Handle, instances: Instances] = { WriteInt[h, Length[instances]]; WHILE instances#NIL DO WriteInstance[h, instances.first]; instances _ instances.rest; ENDLOOP; }; ReadInstances: PUBLIC PROC [h: Handle] RETURNS [instances: Instances _ NIL] = { THROUGH [0 .. ReadInt[h]) DO instances _ CONS [ReadInstance[h], instances]; ENDLOOP; }; 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]; }; < Rope ID] is stored on the handle under the key objectsAtom>> <> WriteObject: PUBLIC PROC [h: Handle, obj: CD.Object] = { objects: RefTab.Ref _ NARROW [CoreProperties.GetProp[h.properties, objectsAtom]]; objectID: ROPE _ NIL; IF objects=NIL THEN { objects _ RefTab.Create[]; h.properties _ CoreProperties.PutProp[h.properties, objectsAtom, objects]; }; objectID _ NARROW [RefTab.Fetch[objects, obj].val]; IF objectID=NIL THEN { classData: ObjectClassData _ NARROW[RefTab.Fetch[objectClassRegistry, obj.class.objectType].val]; objectID _ Rope.Cat["O", Convert.RopeFromInt[from: RefTab.GetSize[objects], base: 16, showRadix: FALSE]]; IF NOT RefTab.Insert[objects, obj, objectID] THEN ERROR; WriteID[h, objectID]; WriteAtom[h, obj.class.objectType]; IF classData=NIL THEN { IF CDAtomicObjects.IsAtomicOb[obj] THEN { WriteTechnology[h, obj.class.technology]; 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]; }; < CD.Object] is stored on the handle under the key objectsAtom>> ReadObject: PUBLIC PROC [h: Handle] RETURNS [obj: CD.Object] = { objects: RefTab.Ref _ NARROW [CoreProperties.GetProp[h.properties, objectsAtom]]; objectID: ROPE; IF objects=NIL THEN { objects _ RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; h.properties _ CoreProperties.PutProp[h.properties, objectsAtom, objects]; }; objectID _ ReadID[h]; IF Rope.Fetch[objectID]#'O THEN ERROR; obj _ NARROW [RefTab.Fetch[objects, objectID].val]; IF obj=NIL THEN { classAtom: ATOM _ ReadAtom[h]; classData: ObjectClassData _ NARROW[RefTab.Fetch[objectClassRegistry, classAtom].val]; IF classData=NIL THEN { technology: CD.Technology _ ReadTechnology[h]; pos: CD.Position _ ReadPosition[h]; layer: CD.Layer _ ReadLayer[h]; obj _ CDAtomicObjects.CreateAtomicOb[classAtom, pos, technology, layer]; } ELSE obj _ classData.read[h]; obj.properties _ ReadCDProperties[h]; IF NOT RefTab.Insert[objects, objectID, obj] THEN ERROR; }; }; <> PinsInstancesPropWrite: PropWriteProc = { count: INT _ 0; Incr: EachInstanceProc = {count _ count+1}; Write: EachInstanceProc = {WriteInstance[h, instance]}; [] _ RawEnumeratePins[prop, value, Incr]; WriteInt[h, count]; [] _ RawEnumeratePins[prop, value, Write]; }; GeometryInstancesPropWrite: PropWriteProc = { count: INT _ 0; Incr: EachInstanceProc = {count _ count+1}; Write: EachInstanceProc = {WriteInstance[h, instance]}; [] _ RawEnumerateGeometry[prop, value, Incr]; WriteInt[h, count]; [] _ RawEnumeratePins[prop, value, Write]; }; 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]]}; WriteObjectsProp: PropWriteProc = { WriteHashTable[h, NARROW [value], WriteObjectIDPair]; }; <<>> ReadObjectsProp: PropReadProc = { value _ ReadHashTable[h, ReadObjectIDPair, RefTabExtras.EqualRope, RefTabExtras.HashRope]; }; <> <> 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] }; <> 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]; WriteReal[h, cellPtr.simplifyOn]; WriteBool[h, cellPtr.drawBorder]; WriteBool[h, cellPtr.specifiedIr]; }; 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.simplifyOn _ ReadReal[h]; cellPtr.drawBorder _ ReadBool[h]; cellPtr.specifiedIr _ ReadBool[h]; obj.specific _ cellPtr; CDCells.ToSequenceMode[obj]; }; <> WriteAbut: ObjectClassWriteProc = { Write: PW.EachSubObjectProc = {WriteObject[h, subObject]}; WriteRect[h, me.bbox]; WriteBool[h, me.class=PW.abutXClass]; WriteInt[h, PW.CountSubObjects[me]]; [] _ PW.EnumerateSubObjects[me, Write]; }; ReadAbut: ObjectClassReadProc = { bbox: CD.Rect _ ReadRect[h]; inX: BOOL _ ReadBool[h]; size: INT _ ReadInt[h]; subObjects: LIST OF CD.Object _ NIL; THROUGH [0 .. size) DO subObjects _ CONS [ReadObject[h], subObjects] ENDLOOP; obj _ (IF inX THEN PW.CreateNewAbutX ELSE PW.CreateNewAbutY)[NARROW [GList.Reverse[subObjects]]]; IF obj.bbox#bbox THEN ERROR; }; <> WriteRotation: ObjectClassWriteProc = { specific: PW.RotationSpecific = NARROW [me.specific]; WriteObject[h, specific.obj]; WriteOrient[h, specific.orientation]; }; ReadRotation: ObjectClassReadProc = { sub: CD.Object _ ReadObject[h]; orient: CD.Orientation _ ReadOrient[h]; obj _ PW.CreateRotation[sub, orient]; }; <> WriteRouting: ObjectClassWriteProc = { routing: CDRoutingObjects.RoutingSpecific _ NARROW [me.specific]; WriteRect[h, me.bbox]; WriteInt[h, routing.size]; WriteRect[h, routing.ir]; WriteReal[h, routing.scaleHint]; FOR i: NAT IN [0 .. routing.size) DO node: CDRoutingObjects.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: CDRoutingObjects.RoutingSpecific _ NEW [CDRoutingObjects.RoutingRep[size]]; routing.ir _ ReadRect[h]; routing.scaleHint _ ReadReal[h]; FOR i: NAT IN [0 .. size) DO nb: NAT _ NAT [ReadInt[h]]; node: CDRoutingObjects.Node = NEW [CDRoutingObjects.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: CDRoutingObjects.routingClass, specific: routing, bbox: bbox]]; }; <> TileArrayRec: TYPE = RECORD [c: SEQUENCE sizeY: NAT OF REF TileLinesRec]; TileLinesRec: TYPE = RECORD [c: SEQUENCE sizeX: NAT OF CD.Object]; WriteTiling: ObjectClassWriteProc = { sizeX, sizeY: NAT; [sizeX, sizeY] _ PW.GetTilingSize[me]; WriteRect[h, me.bbox]; WriteInt[h, sizeX]; WriteInt[h, sizeY]; FOR y: NAT IN [0 .. sizeY) DO FOR x: NAT IN [0 .. sizeX) DO WriteObject[h, PW.GetTile[me, x, y]] ENDLOOP; ENDLOOP; }; ReadTiling: ObjectClassReadProc = { Tiles: PROC [x, y: NAT] RETURNS [CD.Object] = {RETURN [tileArray[y][x]]}; bbox: CD.Rect _ ReadRect[h]; sizeX: NAT _ NAT [ReadInt[h]]; sizeY: NAT _ NAT [ReadInt[h]]; tileArray: REF TileArrayRec _ NEW [TileArrayRec[sizeY]]; FOR y: NAT IN [0 .. sizeY) DO tileArray[y] _ NEW [TileLinesRec[sizeX]]; FOR x: NAT IN [0 .. sizeX) DO tileArray[y][x] _ ReadObject[h] ENDLOOP; ENDLOOP; obj _ PW.CreateTiling[sizeX, sizeY, Tiles]; IF obj.bbox#bbox THEN ERROR; }; <> WriteIndirect: ObjectClassWriteProc = { indirect: CD.Object _ NARROW [me.specific]; WriteRect[h, me.bbox]; WriteObject[h, indirect]; }; ReadIndirect: ObjectClassReadProc = { bbox: CD.Rect _ ReadRect[h]; indirect: CD.Object _ ReadObject[h]; IF indirect.bbox#bbox THEN ERROR; obj _ PW.CreateIndirect[indirect]; }; <> 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]]] }; <> 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]; }; <> WriteLayerRef: PropWriteProc = { WriteLayer[h, NARROW [value, CDPrivate.LayerRef].number]; }; ReadLayerRef: PropReadProc = { value _ CDPrivate.layers[ReadLayer[h]]; }; <> RegisterDecorationIO: PUBLIC PROC [decoration: Decoration] = { [] _ RegisterProperty[decoration.objectProp, ObjectPropWrite, ObjectPropRead]; [] _ RegisterProperty[decoration.pinsProp, PinsInstancesPropWrite, InstancesPropRead]; [] _ RegisterProperty[decoration.geometryProp, GeometryInstancesPropWrite, InstancesPropRead]; [] _ RegisterProperty[decoration.transProp, TransPropWrite, TransPropRead]; }; objectsAtom: ATOM = RegisterProperty[$CoreGeometryIOObjects, WriteObjectsProp, ReadObjectsProp]; <> <<>> [] _ RegisterProperty[$layerOfPin, WriteLayerRef, ReadLayerRef]; RegisterObjectClass[CDRects.bareRectClass, WriteRectangle, ReadRectangle]; RegisterObjectClass[CDRects.wellRectClass, WriteRectangle, ReadRectangle]; RegisterObjectClass[CDCells.pCellClass, WriteCell, ReadCell]; RegisterObjectClass[PW.abutXClass, WriteAbut, ReadAbut]; RegisterObjectClass[PW.abutYClass, WriteAbut, ReadAbut]; RegisterObjectClass[PW.rotationClass, WriteRotation, ReadRotation]; RegisterObjectClass[CDRoutingObjects.routingClass, WriteRouting, ReadRouting]; RegisterObjectClass[PW.tilingClass, WriteTiling, ReadTiling]; RegisterObjectClass[PW.indirectClass, WriteIndirect, ReadIndirect]; RegisterObjectClass[CDSymbolicObjects.markClass, WriteMark, ReadMark]; RegisterObjectClass[CDSymbolicObjects.segmentClass, WriteSegment, ReadSegment]; RegisterObjectClass[CDSymbolicObjects.pinClass, WritePin, ReadPin]; RegisterObjectClass[CDTexts.flipTextClass, WriteText, ReadText]; RegisterObjectClass[CDTexts.rigidTextClass, WriteText, ReadText]; END.