PWCoreImpl.mesa
Copyright © 1985, 1987 by Xerox Corporation. All rights reserved.
Louis Monier May 17, 1986 1:35:25 pm PDT
Bertrand Serlet March 16, 1987 11:05:11 pm PST
Barth, April 22, 1986 7:30:28 pm PST
Spreitzer, April 11, 1986 10:52:25 am PST
Last Edited by: Louis Monier April 19, 1987 7:59:37 pm PDT
Last edited by: Christian Jacobi, January 9, 1987 12:16:44 pm PST
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;
Soon in Core ?
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;
};
Exceptions
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: ROPENIL] = CODE;
LayoutAtomsTable
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;
};
Primitives
layoutAtomProp: PUBLIC ATOM ← CoreProperties.RegisterProperty[$Layout];
GetLayoutAtom: PUBLIC PROC [cellType: CellType] RETURNS [layoutAtom: ATOMNIL] = {
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]};
copies decorations from from to to
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];
};
We check that the public of the source and the public of the recasted layout are similar, and we copy properties from one to the other
CoreOps.VisitRootAtomics[to.public, SmashPins];
VisitAtomicPairs[to.public, from.public, CopyPins];
};
layoutProp: PRIVATE ATOM ← CoreProperties.RegisterProperty[$PWCoreLayout];
cache on CellTypes
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];
We compute the attributes (if any)
IF layoutAtomData.attributesProc#NIL THEN layoutAtomData.attributesProc[cellType];
Now the layout
obj ← layoutAtomData.layoutProc[cellType];
We decorate temporarily for lazy decorations
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];
Now we decorate the source cellType
IF layoutAtomData.decorateProc#NIL THEN layoutAtomData.decorateProc[cellType, obj];
We check those decorations, and we decorate layoutCellType. We need to do that in order to be able to return layoutCellType as the result of the extraction.
CopyDecorations[layoutCellType, cellType, obj];
CoreGeometry.PutObject[extractMode.decoration, layoutCellType, obj];
We make an indirect object to allow the same layout to be returned on 2 different calls of Layout
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];
Consistency check
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];
};
Global Variable
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];
};
Abuts, Arrays and Recast
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]];
We decorate each instance with the appropriate trans, so that the Lazy GetPins can find the location
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];
};
Rotations
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]];
};
Help for writing DecorateProcs
SortInX: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.x<pos2.x]};
SortInY: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.y<pos2.y]};
ReverseSortInX: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.x>pos2.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;
We copy the pins for all publics. For now, we only do it for wires which have the same name as some internal of cellType.
All this code stinks ....
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
The following lines are to pass PWCoreRoute test
All this code stinks ....
IF source=NIL THEN source ← CoreOps.FindWire[cellTypeData.internal, name];
If source is NIL, crash!
IF source=NIL THEN SIGNAL Signal[cellType];
If it is an internal only, let's forget it!
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
];
positionnedInstances is the sorted list of all instances that have associated layout.
positionnedWires is the list of all wires having their own geometry.
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]];
};
Short cut
SetLayout: PUBLIC PROC [cellType: CellType, layoutAtom: ATOM, userDataProp: ATOMNIL, userData: REFNIL] = {
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];
};
Tentative help for regular structures
AbutCell: PUBLIC PROC [public: Wire, abutInstances: LIST OF AbutInstance, inX: BOOL, name: ROPENIL, 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];
We check now that every atomic public has pins
CoreOps.VisitRootAtomics[public, CheckPinsNonNil];
We replace the actuals
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];
};
Saving "Checkpoints"
Store: PUBLIC PROC [cellType: CellType, withCuteFonts: BOOLFALSE] = {
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;
Core
TerminalIO.PutF["Saving the Core for cell %g ...\n", IO.rope[name]];
[] ← CoreIO.ReportSaveCellType[cellType];
Shell
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];
Layout
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]];
};
Backdoor for clients such as PWCoreLichen
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]];
};
Registering layoutAtoms
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.