<> <> <> <> <> <> <> <> DIRECTORY Atom, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties, Commander, Core, CoreClasses, CoreCreate, CoreFlat, CoreIO, CoreOps, CoreProperties, CoreGeometry, CoreGeometryBackdoor, GList, HashTable, IO, PW, PWCore, PWObjects, Rope, Sinix, SinixOps, Sisyph, TerminalIO; PWCoreImpl: CEDAR PROGRAM IMPORTS Atom, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties, CoreClasses, CoreCreate, CoreIO, CoreOps, CoreProperties, CoreGeometry, CoreGeometryBackdoor, GList, HashTable, IO, PW, PWCore, PWObjects, Rope, Sinix, SinixOps, Sisyph, TerminalIO EXPORTS PWCore SHARES CDCells, CDDirectory = BEGIN OPEN PWCore; <> VisitAtomicPairs: PROC [wire1, wire2: Wire, eachPair: PROC [Wire, Wire]] = { VisitInternal: PROC [wire1, wire2: Wire] = { IF wire1.size#wire2.size THEN ERROR; IF wire1.size=0 THEN eachPair[wire1, wire2] ELSE FOR i: NAT IN [0 .. wire1.size) DO VisitInternal[wire1[i], wire2[i]] ENDLOOP; }; IF wire1.size#wire2.size THEN ERROR; FOR i: NAT IN [0 .. wire1.size) DO VisitInternal[wire1[i], wire2[i]] ENDLOOP; }; <> 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: HashTable.Table _ HashTable.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 ~HashTable.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 [HashTable.Fetch[layoutAtomsTable, layoutAtom].value]; IF layoutAtomData#NIL THEN RETURN; CDEnvironment.ExecFileEntry[Atom.GetPName[layoutAtom], NIL, "PWCore"]; layoutAtomData _ NARROW [HashTable.Fetch[layoutAtomsTable, layoutAtom].value]; }; 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.GetCellTypeProp[cellType, layoutAtomProp]]; IF layoutAtom#NIL THEN RETURN; layoutAtom _ NARROW [CoreProperties.GetCellClassProp[cellType.class, layoutAtomProp]]; }; FakeExtract: Sinix.ExtractProc = {result _ CDProperties.GetObjectProp[obj, $PWCoreCellType]}; SmashPins: PROC [wire: Wire] = {CoreGeometry.PutPins[extractMode.decoration, wire, NIL]}; <> 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.VisitRootAtomics[to.public, SmashPins]; VisitAtomicPairs[to.public, from.public, CopyPins]; }; layoutProp: PRIVATE ATOM _ CoreProperties.RegisterProperty[$PWCoreLayout]; <> Layout: PUBLIC PROC [cellType: CellType] RETURNS [obj: Object] = { obj _ NARROW [CoreProperties.GetCellTypeProp[cellType, layoutProp]]; IF obj#NIL THEN RETURN; BEGIN layoutAtom: ATOM _ GetLayoutAtom[cellType]; layoutAtomData: LayoutAtomData; layoutData: LayoutData; layoutCellType: CellType; IF layoutAtom=NIL THEN IF cellType.class.recast=NIL THEN ERROR Error[$NoLayoutAtom, "Impossible to find a layoutAtom for this cellType", cellType] ELSE { recasted: CellType = CoreOps.Recast[cellType]; obj _ Layout[recasted]; CopyDecorations[cellType, recasted, obj]; CoreGeometry.PutObject[extractMode.decoration, cellType, obj]; RETURN; }; layoutAtomData _ GetLayoutAtomData[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]; <> CoreGeometry.PutObject[extractMode.decoration, cellType, obj]; layoutData _ NEW [LayoutDataRec _ [cellType: cellType, obj: obj, mode: extractMode]]; layoutCellType _ CoreOps.CreateCellType[class: layoutClass, public: CoreOps.CopyWire[cellType.public], data: layoutData]; <> IF layoutAtomData.decorateProc#NIL THEN layoutAtomData.decorateProc[cellType, obj]; <> CopyDecorations[layoutCellType, cellType, obj]; CoreGeometry.PutObject[extractMode.decoration, layoutCellType, obj]; <> obj _ PWObjects.CreateIndirect[obj]; CDProperties.PutObjectProp[obj, $PWCoreCellType, layoutCellType]; CDProperties.PutObjectProp[obj, extractMode.extractProcProp, $FakeExtract]; CoreGeometry.PutObject[extractMode.decoration, cellType, obj]; CoreProperties.PutCellTypeProp[cellType, layoutProp, obj]; <> IF Sinix.Extract[obj, extractMode].result#layoutCellType THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; IF CorrespondingCellType[obj]#layoutCellType THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; END; }; FromLayoutWithoutPublic: PUBLIC PROC [obj: Object] RETURNS [cellType: CellType] = { cellType _ NARROW [Sinix.Extract[obj, extractMode].result]; SetLayoutAndDecoration[cellType, obj]; }; <> extractMode: PUBLIC Sinix.Mode _ SinixOps.GetExtractMode[$cmosB]; <<$Get, $GetAndFlatten, $Value and $ValueNoDecorate>> maskSuffix: PUBLIC ROPE _ ".mask"; GetAndAddSuffix: PROC [source: CD.Design, name: ROPE] RETURNS [obj: Object] = { obj _ PW.Get[source, IO.PutR[IO.rope[name], IO.rope[maskSuffix]]]; }; Get: LayoutProc = { source: CD.Design _ NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]]; obj _ GetAndAddSuffix[source, CoreOps.GetCellTypeName[cellType]]; }; GetAndFlatten: LayoutProc = { source: CD.Design _ NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]]; obj _ PW.Flatten[GetAndAddSuffix[source, CoreOps.GetCellTypeName[cellType]]]; }; Value: LayoutProc = { obj _ NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreValue]]; }; DecorateValue: PUBLIC DecorateProc = { extractedCT: CellType _ NARROW [Sinix.Extract[obj, extractMode].result]; extractedToSource: HashTable.Table _ HashTable.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 [HashTable.Fetch[extractedToSource, extractedWire].value]; 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]; [] _ HashTable.Store[extractedToSource, extractedWire, wire]; ENDLOOP; }; CoreOps.VisitRootAtomics[cellType.public, SmashPins]; [] _ CoreOps.VisitWire[cellType.public, FindInExtractedPublic]; }; <> 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]; }; 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 _ Layout[recasted]; }; ArrayY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutY]; obj _ Layout[recasted]; }; ReverseArrayX: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawReverseAbutX]; obj _ Layout[recasted]; }; ReverseArrayY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawReverseAbutY]; obj _ Layout[recasted]; }; Recast: LayoutProc = { obj _ 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.Expand[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.Expand[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]; }; SortInstances: PUBLIC PROC [decoration: CoreGeometry.Decoration, cellType: CellType, sort: SortProc] = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; FOR i: NAT IN [0 .. data.size-1) DO FOR j: NAT IN (i .. data.size) DO IF ~sort[ InstanceBase[decoration, data[i].type, CoreGeometry.GetTrans[decoration, data[i]]], InstanceBase[decoration, data[j].type, CoreGeometry.GetTrans[decoration, data[j]]] ] THEN { w: CoreClasses.CellInstance _ data[i]; data[i] _ data[j]; data[j] _ w; }; ENDLOOP; ENDLOOP; }; DecorateFlatten: PUBLIC PROC [cellType: CellType, obj: Object, sort: PROC [CD.Position, CD.Position] RETURNS [BOOL]] = { ir: CD.Rect _ CD.InterestRect[obj]; extractedCT: CellType _ NARROW [Sinix.Extract[obj, extractMode].result]; extractedToSource: HashTable.Table _ HashTable.Create[CoreOps.WireBits[extractedCT.public]]; -- table of publics of extracted to publics of source extractedCTData: CoreClasses.RecordCellType _ NARROW [extractedCT.data]; cellTypeData: CoreClasses.RecordCellType _ NARROW [cellType.data]; positionnedInstances: LIST OF PositionnedInstance; positionnedWires: LIST OF PositionnedWire; DecorateActual: PROC [bindings: HashTable.Table, sourceActual, deepPublic: Wire] = { wireBind: CoreFlat.FlatWire _ NARROW [HashTable.Fetch[bindings, deepPublic].value]; -- bindings=NIL would mean that extractedCT is a leaf, which is impossible extractedActual: Wire; wire: Wire; FOR i: NAT IN [0 .. sourceActual.size) DO DecorateActual[bindings, sourceActual[i], deepPublic[i]] ENDLOOP; IF deepPublic.size#0 THEN RETURN; IF wireBind=NIL THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; -- something is really wrong! IF wireBind.flatCell#[] THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; -- a deep internal wire extractedActual _ wireBind.wire; IF sourceActual.size#extractedActual.size THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; wire _ NARROW [HashTable.Fetch[extractedToSource, extractedActual].value]; IF wire=sourceActual THEN RETURN; IF wire#NIL THEN SIGNAL PinsCorrespondingToSeveralPublics[cellType, obj, LIST [wire, sourceActual], CoreGeometry.GetPins[extractMode.decoration, extractedActual]]; CoreGeometry.AddIndirectLazyPins[extractMode.decoration, sourceActual, extractedActual]; [] _ HashTable.Insert[extractedToSource, extractedActual, sourceActual]; }; [positionnedInstances, positionnedWires] _ GetPositionnedInstances[extractedCT, sort]; IF cellTypeData.size#GList.Length[positionnedInstances] THEN ERROR Error[$CallerBug, IO.PutFR["Mismatch between extracted layout (%g instances) and source description (%g instances)", IO.int[GList.Length[positionnedInstances]], IO.int[cellTypeData.size]], cellType]; CoreOps.VisitRootAtomics[cellType.public, SmashPins]; FOR i: NAT IN [0 .. cellTypeData.size) DO positionnedInstance: PositionnedInstance = positionnedInstances.first; cell: CellType = positionnedInstance.cell; sourceCellType: CellType = NARROW [cell.data, LayoutData].cellType; IF Layout[cellTypeData[i].type]#Layout[sourceCellType] THEN ERROR Error[$CallerBug, IO.PutFR["Mismatch between the %gth instance of the extracted layout and the %gth instance of the source description: cellTypes are different", IO.int[i], IO.int[i]], cellType]; CoreGeometry.PutTrans[extractMode.decoration, cellTypeData[i], positionnedInstance.trans]; IF ~ CoreOps.CorrectConform[cellTypeData[i].actual, cell.public] THEN ERROR Error[$InternalBug, "Call Implementor!", cellType]; FOR j: NAT IN [0 .. cell.public.size) DO DecorateActual[positionnedInstance.bindings, cellTypeData[i].actual[j], cell.public[j]]; ENDLOOP; positionnedInstances _ positionnedInstances.rest; ENDLOOP; <> <> WHILE positionnedWires#NIL DO AddExtraPins: CoreGeometry.EachInstanceProc = { IF CoreGeometry.TransfedNotAtEdge[positionnedWire.trans, ir, instance] THEN RETURN; CoreGeometry.PutPins[ extractMode.decoration, source, CONS [CoreGeometry.Transform[positionnedWire.trans, instance], CoreGeometry.GetPins[extractMode.decoration, source]] ]; }; positionnedWire: PositionnedWire = positionnedWires.first; wire: Wire = positionnedWire.wire; flatWire: CoreFlat.FlatWireRec = positionnedWire.flatWire; name: ROPE = CoreOps.GetShortWireName[wire]; source: Wire _ NARROW [HashTable.Fetch[extractedToSource, flatWire.wire].value]; IF flatWire.flatCell#[] THEN ERROR Error[$InternalBug, "Call implementor!", cellType]; -- not yet implemented if it is not part of the internal of extractedCT <> <> IF source=NIL THEN source _ CoreOps.FindWire[cellTypeData.internal, name]; <> IF source=NIL THEN SIGNAL Signal[cellType]; <> IF source#NIL AND CoreOps.RecursiveMember[cellType.public, source] THEN [] _ CoreGeometry.EnumerateGeometry[extractMode.decoration, wire, AddExtraPins]; positionnedWires _ positionnedWires.rest; ENDLOOP; }; PositionnedInstance: TYPE = REF PositionnedInstanceRec; PositionnedInstanceRec: TYPE = RECORD [ cell: CellType, -- flat CT (of class layoutClass) flatCell: CoreFlat.FlatCellTypeRec, bindings: CoreFlat.Bindings, -- [public of cellType -> CoreFlat.WireBind] trans: CoreGeometry.Transformation ]; PositionnedWire: TYPE = REF PositionnedWireRec; PositionnedWireRec: TYPE = RECORD [ wire: Wire, flatWire: CoreFlat.FlatWireRec, trans: CoreGeometry.Transformation ]; <> <> GetPositionnedInstances: PROC [extractedCT: CellType, sort: SortProc] RETURNS [positionnedInstances: LIST OF PositionnedInstance _ NIL, positionnedWires: LIST OF PositionnedWire _ NIL] = { Leaf: CoreGeometry.LeafProc = {RETURN [cellType.class=layoutClass]}; EachFlatWire: CoreGeometry.EachFlatWireProc = { positionnedWires _ CONS [ NEW [PositionnedWireRec _ [wire: wire, flatWire: flatWire, trans: trans]], positionnedWires]; }; EachFlatCell: CoreGeometry.EachFlatCellProc = { positionnedInstances _ CONS [ NEW [PositionnedInstanceRec _ [ cell: cell, flatCell: flatCell, bindings: bindings, trans: trans ]], positionnedInstances]; }; Compare: GList.CompareProc = { pi1: PositionnedInstance = NARROW [ref1]; pi2: PositionnedInstance = NARROW [ref2]; RETURN [IF sort[InstanceBase[extractMode.decoration, pi1.cell, pi1.trans], InstanceBase[extractMode.decoration, pi2.cell, pi2.trans]] THEN less ELSE greater]; }; CoreGeometry.EnumerateFlatGeometry[decoration: extractMode.decoration, root: extractedCT, leafProc: Leaf, eachFlatWire: EachFlatWire, eachFlatCell: EachFlatCell]; positionnedInstances _ NARROW [GList.Sort[positionnedInstances, Compare]]; }; <> 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]; }; <> AbutCell: PUBLIC PROC [public: Wire, abutInstances: LIST OF AbutInstance, inX: BOOL, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [recordCell: CellType] = { positionnedInstances: LIST OF PositionnedInstance _ NIL; ObjectsFromAbutInstances: PROC [abutInstances: LIST OF AbutInstance] RETURNS [LIST OF Object] = { IF abutInstances=NIL THEN RETURN [NIL]; BEGIN obj: Object _ abutInstances.first.object; -- to allow 2 instances of the same object to have different bindings ct: CellType _ FromLayoutWithoutPublic[obj]; RETURN [CONS [Layout[ct], ObjectsFromAbutInstances[abutInstances.rest]]]; END; }; RegisterExtractedToSource: PROC [extracted, source: Wire, checkPins: BOOL] = { prevAct: Wire _ NARROW [HashTable.Fetch[extractedToSource, extracted].value]; IF extracted.size#source.size THEN ERROR Error[$CallerBug, "Extracted wire and truth public do not have same structure. You may call implementor for help!", extractedCT]; FOR i: NAT IN [0 .. extracted.size) DO RegisterExtractedToSource[extracted[i], source[i], checkPins] ENDLOOP; IF prevAct=source THEN RETURN; IF prevAct#NIL THEN SIGNAL PinsCorrespondingToSeveralPublics[extractedCT, obj, LIST [prevAct, source], CoreGeometry.GetPins[extractMode.decoration, extracted]]; [] _ HashTable.Store[extractedToSource, extracted, source]; IF source.size#0 THEN RETURN; IF checkPins AND NOT CoreGeometry.HasPins[extractMode.decoration, extracted] THEN IF checkPins THEN SIGNAL NoPinsOnAtomicPublic[extractedCT, obj, extracted] ELSE RETURN; -- sub-public should have pins! CoreGeometry.AddIndirectLazyPins[extractMode.decoration, source, extracted]; }; Replace: PROC [extractedWire: Wire] RETURNS [wire: Wire] = { wire _ NARROW [HashTable.Fetch[extractedToSource, extractedWire].value]; IF wire#NIL THEN RETURN; wire _ CoreOps.CreateWires[size: extractedWire.size]; internals _ CONS [wire, internals]; FOR i: NAT IN [0 .. extractedWire.size) DO wire[i] _ Replace[extractedWire[i]]; ENDLOOP; RegisterExtractedToSource[extractedWire, wire, FALSE]; }; CheckPinsNonNil: PROC [wire: Wire] = { IF NOT CoreGeometry.HasPins[extractMode.decoration, wire] THEN SIGNAL NoPinsOnAtomicPublic[extractedCT, obj, wire, "Some atomic publics have no associated geometry, probably because you forgot to specify in each abutInstance the sub-public bound to it."]; }; internals: Wires _ LIST [public]; instances: LIST OF CoreClasses.CellInstance; obj: Object _ (IF inX THEN PW.AbutListX ELSE PW.AbutListY)[ObjectsFromAbutInstances[abutInstances]]; extractedCT: CellType _ NARROW [Sinix.Extract[obj, extractMode].result]; extractedData: CoreClasses.RecordCellType _ NARROW [extractedCT.data]; extractedToSource: HashTable.Table _ HashTable.Create[CoreOps.WireBits[public]]; i: NAT _ 0; CoreOps.VisitRootAtomics[public, SmashPins]; SortInstances[extractMode.decoration, extractedCT, IF inX THEN SortInX ELSE SortInY]; FOR list: LIST OF AbutInstance _ abutInstances, list.rest WHILE list#NIL DO instance: CoreClasses.CellInstance = extractedData[i]; FOR pas: LIST OF CoreCreate.PA _ list.first.pas, pas.rest WHILE pas#NIL DO pub: Wire = CoreCreate.FindWire[instance.type.public, pas.first.public]; act: Wire = CoreCreate.FindWire[public, pas.first.actual]; IF pub=NIL THEN ERROR Error[$CallerBug, "Some public specified in some PA in your call to AbutCell is not really a public of the cellTYpe. You may call the maintainor of this package for help!", extractedCT]; IF act=NIL THEN ERROR Error[$CallerBug, "Call implementor for help!", extractedCT]; RegisterExtractedToSource[CoreClasses.CorrespondingActual[instance, pub], act, TRUE]; ENDLOOP; i _ i + 1; ENDLOOP; IF i#extractedData.size THEN Error[$CallerBug, "Call implementor for help!", extractedCT]; <> CoreOps.VisitRootAtomics[public, CheckPinsNonNil]; <> FOR i: NAT DECREASING IN [0 .. extractedData.size) DO actual: Wire _ CoreOps.CreateWires[size: extractedData[i].actual.size]; FOR j: NAT IN [0 .. extractedData[i].actual.size) DO actual[j] _ Replace[extractedData[i].actual[j]]; ENDLOOP; instances _ CONS [CoreClasses.CreateInstance[actual: actual, type: extractedData[i].type, props: extractedData[i].properties], instances]; ENDLOOP; recordCell _ CoreClasses.CreateRecordCell[public, CoreOps.CreateWire[internals], instances, name, props]; SetLayoutAndDecoration[recordCell, obj]; }; <> Store: PUBLIC PROC [cellType: CellType, withCuteFonts: BOOL _ FALSE] = { name: ROPE _ CoreOps.GetCellTypeName[cellType]; layout: CD.Object _ Layout[cellType]; layoutFileName: ROPE _ Rope.Cat[name, "Layout"]; shellFileName: ROPE _ Rope.Cat[name, "Shell"]; layoutDesign: CD.Design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]]; shellDesign: CD.Design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]]; shell: CD.Object; <> TerminalIO.PutF["Saving the Core for cell %g ...\n", IO.rope[name]]; [] _ CoreIO.ReportSaveCellType[cellType]; <> TerminalIO.PutF["Making 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]; TerminalIO.PutF["Storing Shell for cell %g ...\n", IO.rope[name]]; [] _ CDIO.WriteDesign[shellDesign, shellFileName]; <> layoutDesign.name _ layoutFileName; layout _ PWObjects.CreateCell[LIST [CDInstances.NewInst[layout]], CD.InterestRect[layout], name]; [] _ CDDirectory.Include[layoutDesign, layout, name]; CDOps.IncludeObjectI[layoutDesign, layout]; TerminalIO.PutF["Storing Layout for cell %g ...\n", IO.rope[name]]; [] _ CDIO.WriteDesign[layoutDesign, layoutFileName]; TerminalIO.PutF["... layout checkpoint stored in %g.core, %gLayout.dale and %gShell.dale\n", IO.rope[name], IO.rope[name], IO.rope[name]]; }; Retrieve: PUBLIC PROC [name: ROPE] RETURNS [cellType: CellType] = { TerminalIO.PutF["Retrieving the Core for cell %g ...\n", IO.rope[name]]; cellType _ CoreIO.RestoreCellType[name]; TerminalIO.PutF["... core retrieved in %g.core ...\n", IO.rope[name]]; }; <> layoutClass: PUBLIC Core.CellClass _ NEW [Core.CellClassRec _ [name: "Layout", recast: RecastLayout]]; RecastLayout: Core.RecastProc = { FillTable: PROC [extractedWire: Wire] = { FillTableInternal: PROC [sourcePublic, newPublic: Wire] = { prevSource: Wire; sourcePins: CoreGeometry.Instances _ CoreGeometry.GetPins[data.mode.decoration, sourcePublic]; CoreGeometry.PutPins[data.mode.decoration, sourcePublic, sourcePins]; -- to avoid all that lazyness IF NOT CoreGeometry.TouchListList[sourcePins, extractedPins] THEN RETURN; prevSource _ NARROW [HashTable.Fetch[table, extractedWire].value]; IF prevSource#NIL AND prevSource#newPublic THEN SIGNAL PinsCorrespondingToSeveralPublics[data.cellType, data.obj, LIST [prevSource, sourcePublic], extractedPins]; [] _ HashTable.Store[table, extractedWire, newPublic]; [] _ HashTable.Store[extractedToSource, extractedWire, sourcePublic]; }; extractedPins: CoreGeometry.Instances _ CoreGeometry.GetPins[data.mode.decoration, extractedWire]; VisitAtomicPairs[data.cellType.public, public, FillTableInternal]; }; recordData: CoreClasses.RecordCellType; data: LayoutData _ NARROW [me.data]; extractedCT: CellType _ NARROW [Sinix.Extract[data.obj, data.mode].result]; public: Wire = CoreOps.CopyWire[me.public]; table: HashTable.Table _ HashTable.Create[]; extractedToSource: HashTable.Table _ HashTable.Create[]; CoreOps.VisitRootAtomics[extractedCT.public, FillTable]; new _ CoreClasses.CreatePermutedRecordCell[iconPublic: public, schCell: extractedCT, table: table, name: Rope.Cat["LayoutRecastOf", CoreOps.GetCellTypeName[data.cellType]]]; recordData _ NARROW [new.data]; IF recordData.size#1 THEN ERROR Error[$InternalBug, "Internal invariant failed", data.cellType]; CoreProperties.PutCellTypeProp[extractedCT, $ExtractedToSource, extractedToSource]; CoreGeometry.PutTrans[data.mode.decoration, recordData[0], []]; }; LayoutCellTypeInfo: PUBLIC PROC [layoutCellType: CellType] RETURNS [obj: Object, sourceCellType, extractedCellType: CellType, extractedToSource: HashTable.Table] = { data: LayoutData _ NARROW [layoutCellType.data]; obj _ data.obj; sourceCellType _ data.cellType; extractedCellType _ NARROW [CoreOps.Recast[layoutCellType].data, CoreClasses.RecordCellType][0].type; extractedToSource _ NARROW [CoreProperties.GetCellTypeProp[extractedCellType, $ExtractedToSource]]; }; CorrespondingCellType: PUBLIC PROC [obj: Object] RETURNS [layoutCellType: CellType _ NIL] = { IF CDProperties.GetObjectProp[obj, extractMode.extractProcProp]=$FakeExtract THEN layoutCellType _ NARROW [CDProperties.GetObjectProp[obj, $PWCoreCellType]]; }; <> WriteLayoutCache: CoreIO.PropWriteProc = {CoreGeometryBackdoor.WriteObject[h, NARROW [value]]}; ReadLayoutCache: CoreIO.PropReadProc = {value _ CoreGeometryBackdoor.ReadObject[h]}; [] _ CoreIO.RegisterProperty[layoutProp, WriteLayoutCache, ReadLayoutCache]; Sinix.RegisterExtractProc[$FakeExtract, FakeExtract]; [] _ 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[$RawReverseAbutX, ReverseAbutX, DecorateReverseAbutX]; [] _ RegisterLayoutAtom[$RawReverseAbutY, ReverseAbutY, DecorateReverseAbutY]; [] _ RegisterLayoutAtom[$AbutX, AbutX, DecorateAbutX, AttributeX]; [] _ RegisterLayoutAtom[$AbutY, AbutY, DecorateAbutY, AttributeY]; [] _ RegisterLayoutAtom[$ReverseAbutX, ReverseAbutX, DecorateReverseAbutX, AttributeX]; [] _ RegisterLayoutAtom[$ReverseAbutY, ReverseAbutY, DecorateReverseAbutY, AttributeY]; [] _ RegisterLayoutAtom[$ArrayX, ArrayX, DecorateRecasted]; [] _ RegisterLayoutAtom[$ArrayY, ArrayY, 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. <<>>