<> <> <> <> <> <> <> DIRECTORY CD, CDBasics, CDCells, CDDirectory, CDInstances, CDOrient, CDProperties, Commander, Core, CoreClasses, CoreCreate, CoreFlat, CoreOps, CoreProperties, CoreGeometry, GList, HashTable, IO, PW, PWCore, PWObjects, Rope, Sinix, SinixOps, Sisyph; PWCoreImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDDirectory, CDInstances, CDProperties, CoreClasses, CoreCreate, CoreOps, CoreProperties, CoreGeometry, GList, HashTable, IO, PW, PWObjects, Rope, Sinix, SinixOps, Sisyph 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; }; SmashProps: CoreOps.EachWireProc = { name: ROPE = CoreOps.GetShortWireName[wire]; wire.properties _ NIL; [] _ CoreOps.SetShortWireName[wire, name]; }; CopyWire: PROC [old: Wire] RETURNS [new: Wire] = { new _ CoreOps.CopyWire[old]; [] _ CoreOps.VisitWire[new, SmashProps]; }; <> 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: LIST OF CD.Instance] = CODE; NoPinsOnAtomicPublic: PUBLIC SIGNAL [cellType: CellType, obj: Object, public: Wire, message: ROPE _ NIL] = CODE; NoInterestRectDecoration: PUBLIC SIGNAL [cellType: CellType, obj: Object] = 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 PW.WriteF["LayoutProc and DecorateProc for %g overwritten\n", IO.atom[layoutAtom]]; }; GetLayoutAtomRegistration: PUBLIC PROC [layoutAtom: ATOM] RETURNS [layoutProc: LayoutProc _ NIL, decorateProc: DecorateProc _ NIL, attributesProc: AttributesProc _ NIL] = { layoutAtomData: LayoutAtomData _ NARROW [HashTable.Fetch[layoutAtomsTable, layoutAtom].value]; 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]]; }; layoutProp: PRIVATE ATOM _ CoreProperties.RegisterProperty[$PWCoreLayout]; -- cache on CellTypes 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]; CoreGeometry.PutIR[extractMode.decoration, to, CD.InterestRect[obj]]; VisitAtomicPairs[to.public, from.public, CopyPins]; }; 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]; RETURN; }; layoutAtomData _ NARROW [HashTable.Fetch[layoutAtomsTable, layoutAtom].value]; 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]; layoutData _ NEW [LayoutDataRec _ [cellType: cellType, obj: obj, mode: extractMode]]; layoutCellType _ CoreOps.CreateCellType[class: layoutClass, public: CopyWire[cellType.public], data: layoutData]; <> IF layoutAtomData.decorateProc#NIL THEN layoutAtomData.decorateProc[cellType, obj]; <> IF NOT CoreGeometry.HasIR[extractMode.decoration, cellType] OR CoreGeometry.GetIR[extractMode.decoration, cellType]#CD.InterestRect[obj] THEN SIGNAL NoInterestRectDecoration[cellType, obj]; CopyDecorations[layoutCellType, cellType, obj]; <> obj _ PWObjects.CreateIndirect[obj]; CDProperties.PutObjectProp[obj, $PWCoreCellType, layoutCellType]; CDProperties.PutObjectProp[obj, extractMode.extractProcProp, $FakeExtract]; CoreProperties.PutCellTypeProp[cellType, layoutProp, obj]; IF CoreOps.GetCellTypeName[cellType]#NIL AND CDDirectory.Name[obj]=NIL THEN NARROW [obj.class.directoryProcs, REF CDDirectory.DirectoryProcs].setName[obj, CoreOps.GetCellTypeName[cellType]]; <> 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; }; InterestRect: PUBLIC PROC [cellType: CellType] RETURNS [ir: CD.Rect] = { IF NOT CoreGeometry.HasIR[extractMode.decoration, cellType] THEN [] _ Layout[cellType]; ir _ CoreGeometry.GetIR[extractMode.decoration, cellType]; }; <<>> 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]; CoreGeometry.PutIR[extractMode.decoration, cellType, CD.InterestRect[obj]]; [] _ 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] = { InsertInOrder: PROC [element: CD.Instance, sorted: LIST OF CD.Instance] RETURNS [new: LIST OF CD.Instance] = { IF element.orientation#0 THEN ERROR Error[$CallerBug, "DecorateAbut is only applicable for CD Cells without rotations", cellType]; IF sorted=NIL THEN RETURN [LIST [element]]; IF sort[CDBasics.BaseOfRect[CDInstances.InstRectO[element]], CDBasics.BaseOfRect[CDInstances.InstRectO[sorted.first]]] THEN RETURN [CONS [element, sorted]]; RETURN [CONS [sorted.first, InsertInOrder[element, sorted.rest]]]; }; SetLazyPins: PROC [wire: Wire] = {CoreGeometry.PutRecordLazyPins[extractMode.decoration, wire, cellType]}; instances: LIST OF CD.Instance; recordData: CoreClasses.RecordCellType _ NARROW [cellType.data]; WHILE obj.class#CDCells.cellClass DO obj _ CDDirectory.Expand[obj].new ENDLOOP; CoreGeometry.PutIR[extractMode.decoration, cellType, CD.InterestRect[obj]]; FOR list: LIST OF CD.Instance _ NARROW [obj.specificRef, CD.CellPtr].contents, list.rest WHILE list#NIL DO instances _ InsertInOrder[list.first, instances]; ENDLOOP; <> FOR i: NAT IN [0 .. recordData.size) DO CoreGeometry.PutTransf[extractMode.decoration, recordData[i], instances.first]; instances _ instances.rest; ENDLOOP; IF instances#NIL THEN ERROR Error[$CallerBug, "DecorateAbut assumption not valid: CD cell has more instances than record CellType", cellType]; CoreOps.VisitRootAtomics[cellType.public, SetLazyPins]; }; 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; IF NOT CoreOps.CorrectConform[cellType.public, rotatedCT.public] THEN ERROR Error[$CallerBug, "Rotation CellType expected [RecordCell with one instance]", cellType]; }; 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]; transf: CD.Instance; CopyPinsFromRotated: PROC [wire1, wire2: Wire] = { CoreGeometry.PutTransfWireIRLazyPins[ decoration: extractMode.decoration, public: wire1, indirect: wire2, transf: transf, ir: ir ]; }; instances: LIST OF CD.Instance; ir: CD.Rect = CD.InterestRect[obj]; WHILE obj.class#CDCells.cellClass DO obj _ CDDirectory.Expand[obj].new ENDLOOP; CoreGeometry.PutIR[extractMode.decoration, cellType, ir]; instances _ NARROW [obj.specificRef, CD.CellPtr].contents; IF instances=NIL OR instances.rest#NIL THEN ERROR Error[$CallerBug, "DecorateRotated is not supposed to be called with an obj that does not expand into a one instance cell", cellType]; transf _ instances.first; <> VisitAtomicPairs[cellType.public, rotatedCT.public, CopyPinsFromRotated]; }; <> 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]}; InstanceLocation: PROC [decoration: CoreGeometry.Decoration, cellInst: CoreClasses.CellInstance] RETURNS [location: CD.Position] = { location _ CDBasics.BaseOfRect[CDInstances.InstRectO[CoreGeometry.GetTransf[decoration, cellInst]]]; }; 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[InstanceLocation[decoration, data[i]], InstanceLocation[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]; CoreGeometry.PutIR[extractMode.decoration, cellType, CD.InterestRect[obj]]; 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.PutTransf[extractMode.decoration, cellTypeData[i], positionnedInstance.transf]; 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 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 FOR list: LIST OF CD.Instance _ positionnedWire.geometry, list.rest WHILE list#NIL DO IF NOT CoreGeometry.AtEdge[ir, list.first] THEN LOOP; CoreGeometry.PutPins[ extractMode.decoration, source, CONS [list.first, CoreGeometry.GetPins[extractMode.decoration, source]] ]; ENDLOOP; 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] transf: CD.Instance ]; PositionnedWire: TYPE = REF PositionnedWireRec; PositionnedWireRec: TYPE = RECORD [ wire: Wire, flatWire: CoreFlat.FlatWireRec, geometry: LIST OF CD.Instance ]; <> <> GetPositionnedInstances: PROC [extractedCT: CellType, sort: SortProc] RETURNS [positionnedInstances: LIST OF PositionnedInstance _ NIL, positionnedWires: LIST OF PositionnedWire _ NIL] = { InsertInOrdered: PROC [element: PositionnedInstance, sorted: LIST OF PositionnedInstance] RETURNS [new: LIST OF PositionnedInstance] = { IF sorted=NIL THEN RETURN [LIST [element]]; IF sort[CDBasics.BaseOfRect[CDInstances.InstRectO[element.transf]], CDBasics.BaseOfRect[CDInstances.InstRectO[sorted.first.transf]]] THEN RETURN [CONS [element, sorted]]; RETURN [CONS [sorted.first, InsertInOrdered[element, sorted.rest]]]; }; Leaf: CoreGeometry.LeafProc = {RETURN [cellType.class=layoutClass]}; EachFlatWire: CoreGeometry.EachFlatWireProc = { positionnedWires _ CONS [ NEW [PositionnedWireRec _ [wire: wire, flatWire: flatWire, geometry: geometry]], positionnedWires]; }; EachFlatCell: CoreGeometry.EachFlatCellProc = { positionnedInstances _ CONS [ NEW [PositionnedInstanceRec _ [ cell: cell, flatCell: flatCell, bindings: bindings, transf: transf ]], positionnedInstances]; }; Compare: GList.CompareProc = { pi1: PositionnedInstance = NARROW [ref1]; pi2: PositionnedInstance = NARROW [ref2]; RETURN [IF sort[CDBasics.BaseOfRect[CDInstances.InstRectO[pi1.transf]], CDBasics.BaseOfRect[CDInstances.InstRectO[pi2.transf]]] 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]; }; SetLayoutAndDecoration: PUBLIC PROC [cellType: CellType, layout: CD.Object] = { SetLayout[cellType, $ValueNoDecorate, $PWCoreValue, layout]; }; 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 = 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]; CoreGeometry.PutIR[extractMode.decoration, recordCell, CD.InterestRect[obj]]; SetLayoutAndDecoration[recordCell, obj]; }; AbutList: PUBLIC PROC [cellTypes: LIST OF CellType, inX: BOOL] RETURNS [recordCell: CellType] = { lobj: LIST OF CD.Object _ NIL; WHILE cellTypes#NIL DO ct: CellType _ cellTypes.first; obj: CD.Object _ CDCells.CreateEmptyCell[]; CDCells.SetInterestRect[obj, InterestRect[ct]]; CDProperties.PutObjectProp[obj, $PWCoreCellType, ct]; CDProperties.PutObjectProp[obj, extractMode.extractProcProp, $FakeExtract]; lobj _ CONS [obj, lobj]; cellTypes _ cellTypes.rest; ENDLOOP; recordCell _ NARROW [Sinix.Extract[(IF inX THEN PW.AbutListX ELSE PW.AbutListY)[PW.Reverse[lobj]], extractMode].result]; SetLayout[recordCell, IF inX THEN $AbutListXNoDecorate ELSE $AbutListYNoDecorate]; }; <> 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: LIST OF CD.Instance _ 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: LIST OF CD.Instance _ 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 = 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.PutTransf[data.mode.decoration, recordData[0], CDInstances.NewInst[data.obj]]; }; 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]]; }; <> 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. <<>>