<> <> <> <> <> <> <> <> <> DIRECTORY Atom, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties, Commander, Core, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, CoreGeometry, GList, InstanceTable, IO, PW, PWCore, RefTab, Rope, Sinix, SinixOps, Sisyph, TerminalIO; PWCoreImpl: CEDAR PROGRAM IMPORTS Atom, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties, CoreClasses, CoreIO, CoreOps, CoreProperties, CoreGeometry, GList, RefTab, InstanceTable, IO, PW, PWCore, Rope, Sinix, SinixOps, Sisyph, TerminalIO EXPORTS PWCore SHARES CDCells, CDDirectory = BEGIN OPEN PWCore; <> Signal: PUBLIC SIGNAL [cellType: CellType] = CODE; Error: PUBLIC ERROR [type: ATOM, message: ROPE, cellType: CellType] = CODE; PinsCorrespondingToSeveralPublics: PUBLIC SIGNAL [cellType: CellType, obj: Object, publics: Wires, geometry: CoreGeometry.Instances] = CODE; NoPinsOnAtomicPublic: PUBLIC SIGNAL [cellType: CellType, obj: Object, public: Wire, message: ROPE _ NIL] = CODE; <> layoutAtomsTable: RefTab.Ref _ RefTab.Create[]; LayoutAtomData: TYPE = REF LayoutAtomDataRec; LayoutAtomDataRec: TYPE = RECORD [layoutProc: LayoutProc, decorateProc: DecorateProc, attributesProc: AttributesProc _ NIL]; RegisterLayoutAtom: PUBLIC PROC [layoutAtom: ATOM, layoutProc: LayoutProc, decorateProc: DecorateProc _ NIL, attributesProc: AttributesProc _ NIL] RETURNS [sameAtom: ATOM] = { sameAtom _ layoutAtom; IF ~RefTab.Store[layoutAtomsTable, layoutAtom, NEW [LayoutAtomDataRec _ [layoutProc: layoutProc, decorateProc: decorateProc, attributesProc: attributesProc]]] THEN TerminalIO.PutF["LayoutProc and DecorateProc for %g overwritten\n", IO.atom[layoutAtom]]; }; GetLayoutAtomData: PROC [layoutAtom: ATOM] RETURNS [layoutAtomData: LayoutAtomData] = { layoutAtomData _ NARROW [RefTab.Fetch[layoutAtomsTable, layoutAtom].val]; IF layoutAtomData#NIL THEN RETURN; CDEnvironment.ExecFileEntry[Atom.GetPName[layoutAtom], NIL, "PWCore"]; layoutAtomData _ NARROW [RefTab.Fetch[layoutAtomsTable, layoutAtom].val]; }; GetLayoutAtomRegistration: PUBLIC PROC [layoutAtom: ATOM] RETURNS [layoutProc: LayoutProc _ NIL, decorateProc: DecorateProc _ NIL, attributesProc: AttributesProc _ NIL] = { layoutAtomData: LayoutAtomData _ GetLayoutAtomData[layoutAtom]; IF layoutAtomData=NIL THEN RETURN; layoutProc _ layoutAtomData.layoutProc; decorateProc _ layoutAtomData.decorateProc; attributesProc _ layoutAtomData.attributesProc; }; <> layoutAtomProp: PUBLIC ATOM _ CoreProperties.RegisterProperty[$Layout]; GetLayoutAtom: PUBLIC PROC [cellType: CellType] RETURNS [layoutAtom: ATOM _ NIL] = { layoutAtom _ NARROW [CoreProperties.InheritCellTypeProp[cellType, layoutAtomProp]]; }; <> CopyDecorations: PROC [to, from: CellType, obj: Object] = { CopyPins: PROC [toWire, fromWire: Wire] = { IF NOT CoreGeometry.HasPins[extractMode.decoration, fromWire] THEN SIGNAL NoPinsOnAtomicPublic[from, obj, fromWire, CoreOps.GetFullWireName[from.public, fromWire]]; CoreGeometry.AddIndirectLazyPins[extractMode.decoration, toWire, fromWire]; }; <> CoreOps.VisitAtomicPairs[to.public, from.public, CopyPins]; }; <> CheckDecorations: PROC [ct: CellType, obj: Object] = { CheckPins: PROC [wire: Wire] = { IF NOT CoreGeometry.HasPins[extractMode.decoration, wire] THEN SIGNAL NoPinsOnAtomicPublic[ct, obj, wire, CoreOps.GetFullWireName[ct.public, wire]]; }; CoreOps.VisitRootAtomics[ct.public, CheckPins]; }; fromPWCoreProp: PRIVATE ATOM _ $FromPWCoreLayout; -- on CD.Objects FromPWCoreRecord: TYPE = RECORD [int: INT]; SetFromPWCore: PRIVATE PROC [cellType: CellType] = { obj: CD.Object _ CoreGeometry.GetObject[extractMode.decoration, cellType]; int: INT _ LOOPHOLE [cellType]; IF CDProperties.GetObjectProp[obj, fromPWCoreProp]#NIL THEN Signal[cellType]; -- same object is stuffed on two different cells! That breaks the invariants, and Lichen will not work! CDProperties.PutObjectProp[obj, fromPWCoreProp, NEW [FromPWCoreRecord _ [int]]]; }; Layout: PUBLIC PROC [cellType: CellType] RETURNS [obj: Object] = { layoutAtom: ATOM; layoutAtomData: LayoutAtomData; obj _ CoreGeometry.GetObject[extractMode.decoration, cellType]; IF obj#NIL THEN RETURN; layoutAtom _ NARROW [CoreProperties.GetCellTypeProp[cellType, layoutAtomProp]]; IF layoutAtom=NIL THEN layoutAtom _ NARROW [CoreProperties.GetCellClassProp[cellType.class, layoutAtomProp]]; IF layoutAtom=NIL AND cellType.class.recast=NIL THEN ERROR Error[$NoLayoutAtom, "Impossible to find a layoutAtom for this cellType", cellType]; layoutAtomData _ GetLayoutAtomData[IF layoutAtom=NIL THEN $Recast ELSE layoutAtom]; IF layoutAtomData=NIL THEN ERROR Error[$NoRegistration, IO.PutFR["LayoutAtom %g has not been registered", IO.atom[layoutAtom]], cellType]; <> IF layoutAtomData.attributesProc#NIL THEN layoutAtomData.attributesProc[cellType]; <> obj _ layoutAtomData.layoutProc[cellType]; PW.SetName[obj, CoreOps.GetCellTypeName[cellType]]; <> CoreGeometry.PutObject[extractMode.decoration, cellType, obj]; <> IF layoutAtomData.decorateProc#NIL THEN layoutAtomData.decorateProc[cellType, obj]; <> CheckDecorations[cellType, obj]; <> SetFromPWCore[cellType]; }; GetPWCoreExtractedCTKey: PUBLIC PROC [extractedCT: CellType] RETURNS [key: INT _ 0] = { obj: CD.Object _ CoreGeometry.GetObject[extractMode.decoration, extractedCT]; ref: REF FromPWCoreRecord _ NARROW [CDProperties.GetObjectProp[obj, fromPWCoreProp]]; IF ref#NIL THEN key _ ref.int; }; IsPWCoreGenerated: PUBLIC PROC [obj: Object] RETURNS [BOOL] = { RETURN [CDProperties.GetObjectProp[obj, fromPWCoreProp]#NIL]; }; FromLayoutWithoutPublic: PUBLIC PROC [obj: Object] RETURNS [cellType: CellType] = { cellType _ NARROW [Sinix.Extract[obj, extractMode].result]; IF IsPWCoreGenerated[obj] THEN RETURN; -- done twice! SetLayoutAndDecoration[cellType, obj]; CheckDecorations[cellType, obj]; SetFromPWCore[cellType]; }; <> extractMode: PUBLIC Sinix.Mode _ SinixOps.GetExtractMode[$cmosB]; <<$Get, $GetAndFlatten, $Value and $ValueNoDecorate>> maskSuffix: PUBLIC ROPE _ ".mask"; GetAndAddSuffix: PROC [cellType: CellType] RETURNS [obj: Object] = { source: CD.Design _ NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]]; <> obj _ PW.Get[source, IO.PutR[IO.rope[CoreOps.GetCellTypeName[cellType]], IO.rope[maskSuffix]]]; }; <> <> Get: LayoutProc = { obj _ PW.CreateIndirect[GetAndAddSuffix[cellType]]; }; GetAndFlatten: LayoutProc = { obj _ PW.Flatten[GetAndAddSuffix[cellType]]; }; Value: LayoutProc = { obj _ NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreValue]]; }; DecorateValue: PUBLIC DecorateProc = { extractedCT: CellType _ NARROW [Sinix.Extract[obj, extractMode].result]; extractedToSource: RefTab.Ref _ RefTab.Create[extractedCT.public.size]; FindInExtractedPublic: CoreOps.EachWireProc = { FOR names: LIST OF ROPE _ CoreOps.GetFullWireNames[cellType.public, wire], names.rest WHILE names#NIL DO name: ROPE _ names.first; extractedWire: Wire _ CoreOps.FindWire[extractedCT.public, name]; previousSourceWire: Wire _ NARROW [RefTab.Fetch[extractedToSource, extractedWire].val]; IF extractedWire=NIL OR extractedWire.size#0 THEN LOOP; IF previousSourceWire#NIL AND previousSourceWire#wire THEN SIGNAL PinsCorrespondingToSeveralPublics[cellType, obj, LIST [previousSourceWire, wire], CoreGeometry.GetPins[extractMode.decoration, extractedWire]]; IF NOT CoreGeometry.HasPins[extractMode.decoration, extractedWire] THEN SIGNAL NoPinsOnAtomicPublic[cellType, obj, extractedWire, name]; CoreGeometry.AddIndirectLazyPins[extractMode.decoration, wire, extractedWire]; [] _ RefTab.Store[extractedToSource, extractedWire, wire]; ENDLOOP; }; [] _ CoreOps.VisitWire[cellType.public, FindInExtractedPublic]; }; <> sisyphFudge: INT _ CD.FetchTechnology[$cmosB].lambda/2; -- Not very clean here! AttributeAbutXorY: AttributesProc = { ambiguous, inX: BOOL; [ambiguous, inX] _ InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge]; IF ambiguous THEN ERROR Error[$CallerBug, "*** Ambiguity for deciding between AbutX and AbutY.\n", cellType]; SortInstances[Sisyph.mode.decoration, cellType, IF inX THEN SortInX ELSE SortInY]; }; LayoutAbutXorY: LayoutProc = { obj _ (IF InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge].inX THEN AbutX ELSE AbutY)[cellType]; }; DecorateAbutXorY: DecorateProc = { (IF InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge].inX THEN DecorateAbutX ELSE DecorateAbutY)[cellType, obj]; }; AttributeX: AttributesProc = {SortInstances[Sisyph.mode.decoration, cellType, SortInX]}; AttributeY: AttributesProc = {SortInstances[Sisyph.mode.decoration, cellType, SortInY]}; AbutX: LayoutProc = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; subObjects: LIST OF Object _ NIL; FOR i: NAT DECREASING IN [0 .. data.size) DO subObjects _ CONS [Layout[data[i].type], subObjects]; ENDLOOP; obj _ PW.AbutListX[subObjects]; }; AbutY: LayoutProc = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; subObjects: LIST OF Object _ NIL; FOR i: NAT DECREASING IN [0 .. data.size) DO subObjects _ CONS [Layout[data[i].type], subObjects]; ENDLOOP; obj _ PW.AbutListY[subObjects]; }; AbutFlipXAndDecorate: LayoutProc = {obj _ AbutFlipAndDecorate[cellType, TRUE]}; AbutFlipYAndDecorate: LayoutProc = {obj _ AbutFlipAndDecorate[cellType, FALSE]}; AbutFlipAndDecorate: PROC [cellType: CellType, inX: BOOL] RETURNS [obj: Object] = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; flip: BOOL _ FALSE; -- indicates polarity of the coming flip instances: CD.InstanceList _ NIL; -- instances for constructing the cell layout0: CD.Object _ Layout[data[0].type]; isize0: CD.Position _ CD.InterestSize[layout0]; pos: CD.Position _ [0, 0]; -- position (in ir coordonnates) of the coming cell FOR i: NAT IN [0 .. data.size) DO orientation: CD.Orientation _ IF flip THEN IF inX THEN mirrorX ELSE rotate180X ELSE original; layout: CD.Object _ Layout[data[i].type]; ir: CD.Rect = CDBasics.MapRect[CD.InterestRect[layout], [[0, 0], orientation]]; isize: CD.Position _ CDBasics.SizeOfRect[ir]; trans: CD.Transformation = [CDBasics.SubPoints[pos, CDBasics.BaseOfRect[ir]], orientation]; -- translation, in the CD coordonnate system IF NOT (IF inX THEN isize.y=isize0.y ELSE isize.x=isize0.x) THEN ERROR; -- incompatible y dimension for an abutX instances _ CONS [CDInstances.NewInst[layout, trans], instances]; <> CoreGeometry.PutTrans[extractMode.decoration, data[i], trans]; IF inX THEN pos.x _ pos.x + isize.x ELSE pos.y _ pos.y + isize.y; flip _ NOT flip; ENDLOOP; obj _ PW.CreateCell[instances: instances]; CoreGeometry.PutRecordLazyPins[extractMode.decoration, cellType, CD.InterestRect[obj]]; }; ReverseAbutX: LayoutProc = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; subObjects: LIST OF Object _ NIL; FOR i: NAT IN [0 .. data.size) DO subObjects _ CONS [Layout[data[i].type], subObjects]; ENDLOOP; obj _ PW.AbutListX[subObjects]; }; ReverseAbutY: LayoutProc = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; subObjects: LIST OF Object _ NIL; FOR i: NAT IN [0 .. data.size) DO subObjects _ CONS [Layout[data[i].type], subObjects]; ENDLOOP; obj _ PW.AbutListY[subObjects]; }; ArrayX: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutX]; obj _ PW.CreateIndirect[Layout[recasted]]; }; ArrayY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutY]; obj _ PW.CreateIndirect[Layout[recasted]]; }; ArrayFlipX: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutFlipX]; obj _ PW.CreateIndirect[Layout[recasted]]; }; ArrayFlipY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutFlipY]; obj _ PW.CreateIndirect[Layout[recasted]]; }; ReverseArrayX: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawReverseAbutX]; obj _ PW.CreateIndirect[Layout[recasted]]; }; ReverseArrayY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawReverseAbutY]; obj _ PW.CreateIndirect[Layout[recasted]]; }; Recast: LayoutProc = { obj _ PW.CreateIndirect[Layout[CoreOps.Recast[cellType]]]; }; DecorateAbut: PUBLIC PROC [cellType: CellType, obj: Object, sort: SortProc] = { InsertInst: CDCells.InstEnumerator = { IF inst.trans.orient#original THEN ERROR Error[$CallerBug, "DecorateAbut is only applicable to objects expanding into cells without rotation", cellType]; sorted _ CONS [inst, sorted]; }; CompareInst: GList.CompareProc = { inst1: CD.Instance = NARROW [ref1]; inst2: CD.Instance = NARROW [ref2]; RETURN [IF sort[ObjectBase[inst1.ob, inst1.trans], ObjectBase[inst2.ob, inst2.trans]] THEN less ELSE greater]; }; sorted: LIST OF CD.Instance; recordData: CoreClasses.RecordCellType _ NARROW [cellType.data]; WHILE obj.class#CDCells.pCellClass DO obj _ CDDirectory.Expand1[obj].new ENDLOOP; [] _ CDCells.EnumerateInstances[obj, InsertInst]; sorted _ NARROW [GList.Sort[sorted, CompareInst]]; <> FOR i: NAT IN [0 .. recordData.size) DO CoreGeometry.PutTrans[extractMode.decoration, recordData[i], sorted.first.trans]; sorted _ sorted.rest; ENDLOOP; IF sorted#NIL THEN ERROR Error[$CallerBug, "DecorateAbut assumption not valid: CD cell has more instances than record CellType", cellType]; CoreGeometry.PutRecordLazyPins[extractMode.decoration, cellType, CD.InterestRect[obj]]; }; DecorateAbutX: PUBLIC DecorateProc = { DecorateAbut[cellType, obj, SortInX]; }; DecorateAbutY: PUBLIC DecorateProc = { DecorateAbut[cellType, obj, SortInY]; }; DecorateReverseAbutX: PUBLIC DecorateProc = { DecorateAbut[cellType, obj, ReverseSortInX]; }; DecorateReverseAbutY: PUBLIC DecorateProc = { DecorateAbut[cellType, obj, ReverseSortInY]; }; DecorateRecasted: PUBLIC DecorateProc = { CopyDecorations[cellType, CoreOps.Recast[cellType], obj]; }; <> Rotated: PROC [cellType: CellType] RETURNS [rotatedCT: CellType] = { rct: CoreClasses.RecordCellType; IF cellType.class#CoreClasses.recordCellClass THEN ERROR Error[$CallerBug, "Rotation CellType expected [RecordCell with one instance]", cellType]; rct _ NARROW [cellType.data]; IF rct.size#1 THEN ERROR Error[$CallerBug, "Rotation CellType expected [RecordCell with one instance]", cellType]; rotatedCT _ rct[0].type; }; FlipX: LayoutProc = {obj _ PW.FlipX[Layout[Rotated[cellType]]]}; FlipY: LayoutProc = {obj _ PW.FlipY[Layout[Rotated[cellType]]]}; Rot90: LayoutProc = {obj _ PW.Rot90[Layout[Rotated[cellType]]]}; Rot180: LayoutProc = {obj _ PW.Rot180[Layout[Rotated[cellType]]]}; Rot270: LayoutProc = {obj _ PW.Rot270[Layout[Rotated[cellType]]]}; DecorateRotated: PUBLIC DecorateProc = { rotatedCT: CellType = Rotated[cellType]; trans: CoreGeometry.Transformation; DecorateUniqueInst: CDCells.InstEnumerator = {trans _ inst.trans}; <> WHILE obj.class#CDCells.pCellClass DO obj _ CDDirectory.Expand1[obj].new ENDLOOP; IF CDCells.CountInstances[obj]#1 THEN ERROR Error[$CallerBug, "DecorateRotated is not supposed to be called with an obj that does not expand into a one instance cell", cellType]; [] _ CDCells.EnumerateInstances[obj, DecorateUniqueInst]; CoreGeometry.PutTrans[extractMode.decoration, NARROW [cellType.data, CoreClasses.RecordCellType][0], trans]; CoreGeometry.PutRecordLazyPins[extractMode.decoration, cellType, CD.InterestRect[obj]]; }; <> SortInX: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.xpos2.x]}; ReverseSortInY: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.y>pos2.y]}; ObjectBase: PROC [obj: CD.Object, trans: CoreGeometry.Transformation] RETURNS [pos: CD.Position] = { pos _ CDBasics.BaseOfRect[CDBasics.MapRect[CD.InterestRect[obj], trans]]; }; InstanceBase: PROC [decoration: CoreGeometry.Decoration, cellType: CellType, trans: CoreGeometry.Transformation] RETURNS [pos: CD.Position] = { pos _ ObjectBase[CoreGeometry.GetObject[decoration, cellType], trans]; }; InstancesInXOrY: PUBLIC PROC [decoration: CoreGeometry.Decoration, record: CellType, fudge: INT _ 0] RETURNS [ambiguous, inX: BOOL] = { data: CoreClasses.RecordCellType _ NARROW [record.data]; overlappingInX, overlappingInY: BOOL _ FALSE; FOR i: NAT IN [0 .. data.size-1) DO rect1: CD.Rect _ CDBasics.MapRect[ CD.InterestRect[CoreGeometry.GetObject[decoration, data[i].type]], CoreGeometry.GetTrans[decoration, data[i]] ]; FOR j: NAT IN (i .. data.size) DO rect2: CD.Rect _ CDBasics.MapRect[ CD.InterestRect[CoreGeometry.GetObject[decoration, data[j].type]], CoreGeometry.GetTrans[decoration, data[j]] ]; IF rect1.x1+fudge> SetLayout: PUBLIC PROC [cellType: CellType, layoutAtom: ATOM, userDataProp: ATOM _ NIL, userData: REF _ NIL] = { CoreProperties.PutCellTypeProp[cellType, layoutAtomProp, layoutAtom]; IF userDataProp#NIL THEN CoreProperties.PutCellTypeProp[cellType, userDataProp, userData]; }; RotateCellType: PUBLIC PROC [rotatedCellType: CellType, orientation: ATOM] RETURNS [cellType: CellType] = { public: Wire = CoreOps.CreateWires[size: rotatedCellType.public.size]; internal: Wire = CoreOps.CreateWires[size: rotatedCellType.public.size]; FOR i: NAT IN [0 .. rotatedCellType.public.size) DO new: Wire = CoreOps.CopyWire[rotatedCellType.public[i]]; public[i] _ internal[i] _ new; ENDLOOP; cellType _ CoreClasses.CreateRecordCell[public: public, internal: internal, instances: LIST [CoreClasses.CreateInstance[actual: internal, type: rotatedCellType]]]; SetLayout[cellType, orientation]; }; <> <> IncludeDescribedObjects: PROC [design: CD.Design, ob: CD.Object] = { EachObject: CDDirectory.EachObjectProc = { IF me.class.composed THEN { name: Rope.ROPE _ CDDirectory.Name[me, design]; IF name#NIL THEN RETURN; name _ NARROW [CDProperties.GetObjectProp[me, $Describe]]; IF name=NIL THEN RETURN; <> IF CDProperties.GetObjectProp[me, $OwnerDesign]#NIL AND NOT me.immutable THEN RETURN; [] _ CDDirectory.Include[design, me, name, TRUE]; } }; [] _ CDDirectory.EnumerateObject[ob: ob, proc: EachObject] }; Store: PUBLIC PROC [cellType: CellType, withCuteFonts: BOOL _ FALSE] = { name: ROPE _ CoreOps.GetCellTypeName[cellType]; TerminalIO.PutF["Saving the Core for cell %g ...\n", IO.rope[name]]; [] _ CoreIO.ReportSaveCellType[cellType]; StoreShell[cellType, withCuteFonts]; StoreLayout[cellType]; TerminalIO.PutF["\nLayout checkpoint:\n %g.core\n %gLayout.dale\n %gShell.dale\n", IO.rope[name], IO.rope[name], IO.rope[name]]}; StoreShell: PUBLIC PROC [cellType: CellType, withCuteFonts: BOOL _ FALSE] = { name: ROPE _ CoreOps.GetCellTypeName[cellType]; shellFileName: ROPE _ Rope.Cat[name, "Shell"]; shellDesign: CD.Design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]]; shell: CD.Object; TerminalIO.PutF["Saving the Shell for cell %g ...\n", IO.rope[name]]; shell _ CoreGeometry.CreateShell[extractMode.decoration, cellType, withCuteFonts]; shellDesign.name _ shellFileName; [] _ CDDirectory.Include[shellDesign, shell, name]; [] _ CDOps.IncludeObjectI[shellDesign, shell]; [] _ CDIO.WriteDesign[shellDesign, shellFileName]; CDOps.SetMutability[shellDesign, inaccessible]}; -- to avoid GCollected objects! StoreLayout: PUBLIC PROC [cellType: CellType] = { name: ROPE _ CoreOps.GetCellTypeName[cellType]; layoutFileName: ROPE _ Rope.Cat[name, "Layout"]; layoutDesign: CD.Design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]]; layout: CD.Object _ Layout[cellType]; TerminalIO.PutF["Saving the Layout for cell %g ...\n", IO.rope[name]]; layoutDesign.name _ layoutFileName; layout _ PW.CreateCell [LIST [CDInstances.NewInst[layout]], CD.InterestRect[layout], name.Cat[".mask"]]; [] _ CDDirectory.Include[layoutDesign, layout, name.Cat[".mask"]]; [] _ CDOps.IncludeObjectI[layoutDesign, layout]; IncludeDescribedObjects[layoutDesign, layout]; [] _ CDIO.WriteDesign[layoutDesign, layoutFileName]; CDOps.SetMutability[layoutDesign, inaccessible]}; -- to avoid GCollected objects! Retrieve: PUBLIC PROC [name: ROPE] RETURNS [cellType: CellType] = { obj: CD.Object; TerminalIO.PutF["Retrieving %g.core\n", IO.rope[name]]; cellType _ CoreIO.RestoreCellType[name]; obj _ CoreGeometry.GetObject[extractMode.decoration, cellType]; SetFromPWCore[cellType]; TerminalIO.PutF["%g.core Retrieved\n", IO.rope[name]]}; <> LayoutInfo: PUBLIC PROC [sourceCT: CellType] RETURNS [layout: Object, extractedCT: CellType, extractedToSource: RefTab.Ref, key: INT] = { FillTable: PROC [sourcePublic: Wire] = { EachSourcePin: CoreGeometry.EachInstanceProc = { Action: PROC [extractedInstance: CoreGeometry.Instance, value: InstanceTable.Value] = { extractedWire: Wire = NARROW [value]; prevSource: Wire _ NARROW [RefTab.Fetch[extractedToSource, extractedWire].val]; IF prevSource=sourcePublic THEN RETURN; -- already considered IF NOT extractMode.touchProc[extractMode.touchProc, instance, extractedInstance] THEN RETURN; IF prevSource#NIL THEN SIGNAL PinsCorrespondingToSeveralPublics[sourceCT, layout, LIST [prevSource, sourcePublic], LIST [instance, extractedInstance]]; [] _ RefTab.Store[extractedToSource, extractedWire, sourcePublic]; }; InstanceTable.Enumerate[extractedInstances, Action, CoreGeometry.BBox[instance]]; }; [] _ CoreGeometry.EnumeratePins[extractMode.decoration, sourcePublic, EachSourcePin]; }; extractedInstances: InstanceTable.Table; -- table instance -> extractedPublic layout _ PWCore.Layout[sourceCT]; extractedCT _ NARROW [Sinix.Extract[layout, extractMode].result]; extractedToSource _ RefTab.Create[]; -- maps extractedWire to source extractedInstances _ InstanceTableFromPublic[extractMode.decoration, layout.bbox, extractedCT.public]; key _ GetPWCoreExtractedCTKey[extractedCT]; CoreOps.VisitRootAtomics[sourceCT.public, FillTable]; }; < public>> InstanceTableFromPublic: PROC [decoration: CoreGeometry.Decoration, bbox: CD.Rect, public: WireSeq] RETURNS [table: InstanceTable.Table] = { FillInstanceTable: PROC [wire: Wire] = { AddPinInTable: CoreGeometry.EachInstanceProc = { InstanceTable.Insert[table, instance, wire]; }; [] _ CoreGeometry.EnumeratePins[decoration, wire, AddPinInTable]; }; table _ InstanceTable.Create[bbox]; CoreOps.VisitRootAtomics[public, FillInstanceTable]; }; <> [] _ RegisterLayoutAtom[$Get, Get, DecorateValue]; [] _ RegisterLayoutAtom[$GetAndFlatten, GetAndFlatten, DecorateValue]; [] _ RegisterLayoutAtom[$Value, Value, DecorateValue]; [] _ RegisterLayoutAtom[$ValueNoDecorate, Value]; [] _ RegisterLayoutAtom[$AbutListXNoDecorate, AbutX]; [] _ RegisterLayoutAtom[$AbutListYNoDecorate, AbutY]; [] _ RegisterLayoutAtom[$RawAbutX, AbutX, DecorateAbutX]; [] _ RegisterLayoutAtom[$RawAbutY, AbutY, DecorateAbutY]; [] _ RegisterLayoutAtom[$RawAbutFlipX, AbutFlipXAndDecorate]; [] _ RegisterLayoutAtom[$RawAbutFlipY, AbutFlipYAndDecorate]; [] _ RegisterLayoutAtom[$AbutFlipX, AbutFlipXAndDecorate, NIL, AttributeX]; [] _ RegisterLayoutAtom[$AbutFlipY, AbutFlipYAndDecorate, NIL, AttributeY]; [] _ RegisterLayoutAtom[$RawReverseAbutX, ReverseAbutX, DecorateReverseAbutX]; [] _ RegisterLayoutAtom[$RawReverseAbutY, ReverseAbutY, DecorateReverseAbutY]; [] _ RegisterLayoutAtom[$AbutX, AbutX, DecorateAbutX, AttributeX]; [] _ RegisterLayoutAtom[$AbutY, AbutY, DecorateAbutY, AttributeY]; [] _ RegisterLayoutAtom[$Abut, LayoutAbutXorY, DecorateAbutXorY, AttributeAbutXorY]; [] _ RegisterLayoutAtom[$ReverseAbutX, ReverseAbutX, DecorateReverseAbutX, AttributeX]; [] _ RegisterLayoutAtom[$ReverseAbutY, ReverseAbutY, DecorateReverseAbutY, AttributeY]; [] _ RegisterLayoutAtom[$ArrayX, ArrayX, DecorateRecasted]; [] _ RegisterLayoutAtom[$ArrayY, ArrayY, DecorateRecasted]; [] _ RegisterLayoutAtom[$ArrayFlipX, ArrayFlipX, DecorateRecasted]; [] _ RegisterLayoutAtom[$ArrayFlipY, ArrayFlipY, DecorateRecasted]; [] _ RegisterLayoutAtom[$ReverseArrayX, ReverseArrayX, DecorateRecasted]; [] _ RegisterLayoutAtom[$ReverseArrayY, ReverseArrayY, DecorateRecasted]; [] _ RegisterLayoutAtom[$Recast, Recast, DecorateRecasted]; [] _ RegisterLayoutAtom[$FlipX, FlipX, DecorateRotated]; [] _ RegisterLayoutAtom[$FlipY, FlipY, DecorateRotated]; [] _ RegisterLayoutAtom[$Rot90, Rot90, DecorateRotated]; [] _ RegisterLayoutAtom[$Rot180, Rot180, DecorateRotated]; [] _ RegisterLayoutAtom[$Rot270, Rot270, DecorateRotated]; END. <<>>