PWCoreImpl.mesa
Copyright Ó 1985, 1987 by Xerox Corporation. All rights reserved.
Louis Monier May 17, 1986 1:35:25 pm PDT
Bertrand Serlet August 15, 1988 1:52:12 pm PDT
Barth, April 22, 1986 7:30:28 pm PST
Spreitzer, April 11, 1986 10:52:25 am PST
Last Edited by: Louis Monier July 26, 1988 7:14:55 pm PDT
Jean-Marc Frailong December 28, 1987 10:00:21 am PST
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, CoreFlat, CoreIO, CoreOps, CoreProperties,
CoreGeometry,
GList, IO,
PW, PWCore,
RefTab, Rope,
Sinix, SinixOps, Sisyph, TerminalIO;
PWCoreImpl: CEDAR PROGRAM
IMPORTS Atom, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties, CoreClasses, CoreIO, CoreOps, CoreProperties, CoreGeometry, GList, RefTab, IO, PW, PWCore, Rope, Sinix, SinixOps, Sisyph, TerminalIO
EXPORTS PWCore
SHARES CDCells, CDDirectory =
BEGIN OPEN PWCore;
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: RefTab.Ref ← RefTab.Create[];
LayoutAtomData: TYPE = REF LayoutAtomDataRec;
LayoutAtomDataRec: TYPE = RECORD [layoutProc: LayoutProc, decorateProc: DecorateProc, attributesProc: AttributesProc ← NIL];
RegisterLayoutAtom: PUBLIC PROC [layoutAtom: ATOM, layoutProc: LayoutProc, decorateProc: DecorateProc ← NIL, attributesProc: AttributesProc ← NIL] RETURNS [sameAtom: ATOM] = {
sameAtom ← layoutAtom;
IF ~RefTab.Store[layoutAtomsTable, layoutAtom, NEW [LayoutAtomDataRec ← [layoutProc: layoutProc, decorateProc: decorateProc, attributesProc: attributesProc]]]
THEN TerminalIO.PutF["LayoutProc and DecorateProc for %g overwritten\n", IO.atom[layoutAtom]];
};
GetLayoutAtomData: PROC [layoutAtom: ATOM] RETURNS [layoutAtomData: LayoutAtomData] = {
layoutAtomData ← NARROW [RefTab.Fetch[layoutAtomsTable, layoutAtom].val];
IF layoutAtomData#NIL THEN RETURN;
CDEnvironment.ExecFileEntry[Atom.GetPName[layoutAtom], NIL, "PWCore"];
layoutAtomData ← NARROW [RefTab.Fetch[layoutAtomsTable, layoutAtom].val];
};
GetLayoutAtomRegistration: PUBLIC PROC [layoutAtom: ATOM] RETURNS [layoutProc: LayoutProc ← NIL, decorateProc: DecorateProc ← NIL, attributesProc: AttributesProc ← NIL] = {
layoutAtomData: LayoutAtomData ← GetLayoutAtomData[layoutAtom];
IF layoutAtomData=NIL THEN RETURN;
layoutProc ← layoutAtomData.layoutProc;
decorateProc ← layoutAtomData.decorateProc;
attributesProc ← layoutAtomData.attributesProc;
};
Primitives
layoutAtomProp: PUBLIC ATOM ← CoreProperties.RegisterProperty[$Layout];
GetLayoutAtom: PUBLIC PROC [cellType: CellType] RETURNS [layoutAtom: ATOMNIL] = {
layoutAtom ← NARROW [CoreProperties.InheritCellTypeProp[cellType, layoutAtomProp]];
};
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.PutIndirectsLazyPins[extractMode.decoration, toWire, LIST [fromWire]]; -- replaced AddIndirectLazyPins by PutIndirectsLazyPins on August 15, 1988 12:14:12 pm PDT [BS]
};
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.VisitAtomicPairs[to.public, from.public, CopyPins];
};
Checks that's ct is properly decorated.
CheckDecorations: PROC [ct: CellType, obj: Object] = {
CheckPins: PROC [wire: Wire] = {
IF NOT CoreGeometry.HasPins[extractMode.decoration, wire] THEN
SIGNAL NoPinsOnAtomicPublic[ct, obj, wire, CoreOps.GetFullWireName[ct.public, wire]];
};
CoreOps.VisitRootAtomics[ct.public, CheckPins];
};
fromPWCoreProp: PRIVATE ATOM ← $FromPWCoreLayout; -- on CD.Objects
FromPWCoreRecord: TYPE = RECORD [int: INT];
SetFromPWCore: PRIVATE PROC [cellType: CellType] = {
obj: CD.Object ← CoreGeometry.GetObject[extractMode.decoration, cellType];
int: INTLOOPHOLE [cellType];
IF CDProperties.GetObjectProp[obj, fromPWCoreProp]#NIL THEN Signal[cellType]; -- same object is stuffed on two different cells! That breaks the invariants, and Lichen will not work!
CDProperties.PutObjectProp[obj, fromPWCoreProp, NEW [FromPWCoreRecord ← [int]]];
};
Layout: PUBLIC PROC [cellType: CellType] RETURNS [obj: Object] = {
layoutAtom: ATOM;
layoutAtomData: LayoutAtomData;
obj ← CoreGeometry.GetObject[extractMode.decoration, cellType];
IF obj#NIL THEN RETURN;
layoutAtom ← NARROW [CoreProperties.GetCellTypeProp[cellType, layoutAtomProp]];
IF layoutAtom=NIL THEN
layoutAtom ← NARROW [CoreProperties.GetCellClassProp[cellType.class, layoutAtomProp]];
IF layoutAtom=NIL AND cellType.class.recast=NIL THEN
ERROR Error[$NoLayoutAtom, "Impossible to find a layoutAtom for this cellType", cellType];
layoutAtomData ← GetLayoutAtomData[IF layoutAtom=NIL THEN $Recast ELSE layoutAtom];
IF layoutAtomData=NIL THEN
ERROR Error[$NoRegistration, IO.PutFR["LayoutAtom %g has not been registered", IO.atom[layoutAtom]], cellType];
We compute the attributes (if any)
IF layoutAtomData.attributesProc#NIL THEN layoutAtomData.attributesProc[cellType];
Now the layout
obj ← layoutAtomData.layoutProc[cellType];
PW.SetName[obj, CoreOps.GetCellTypeName[cellType]];
We decorate for lazy decorations
CoreGeometry.PutObject[extractMode.decoration, cellType, obj];
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.
CheckDecorations[cellType, obj];
We mark obj as coming from Layout
SetFromPWCore[cellType];
};
GetPWCoreExtractedCTKey: PUBLIC PROC [extractedCT: CellType] RETURNS [key: INT ← 0] = {
obj: CD.Object ← CoreGeometry.GetObject[extractMode.decoration, extractedCT];
ref: REF FromPWCoreRecord ← NARROW [CDProperties.GetObjectProp[obj, fromPWCoreProp]];
IF ref#NIL THEN key ← ref.int;
};
IsPWCoreGenerated: PUBLIC PROC [obj: Object] RETURNS [BOOL] = {
RETURN [CDProperties.GetObjectProp[obj, fromPWCoreProp]#NIL];
};
FromLayoutWithoutPublic: PUBLIC PROC [obj: Object] RETURNS [cellType: CellType] = {
cellType ← NARROW [Sinix.Extract[obj, extractMode].result];
IF IsPWCoreGenerated[obj] THEN RETURN; -- done twice!
SetLayoutAndDecoration[cellType, obj];
CheckDecorations[cellType, obj];
SetFromPWCore[cellType];
};
Global Variable
extractMode: PUBLIC Sinix.Mode ← SinixOps.GetExtractMode[$cmosB];
$Get, $GetAndFlatten, $Value and $ValueNoDecorate
maskSuffix: PUBLIC ROPE ← ".mask";
GetAndAddSuffix: PROC [cellType: CellType] RETURNS [obj: Object] = {
source: CD.Design ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]];
Here could be added the code for searching in a "Design" property if source=NIL?
obj ← PW.Get[source, IO.PutR[IO.rope[CoreOps.GetCellTypeName[cellType]], IO.rope[maskSuffix]]];
};
Question for the reader: Why are we making an indirect here???
Answer: because two different cellTypes can have the exact same name, Layout: $Get and $PWCoreSourceDesign: design. For example two icons extracted in different Sisyph contexts will yield two different (but identical!) cellTypes.
Get: LayoutProc = {
obj ← PW.CreateIndirect[GetAndAddSuffix[cellType]];
};
GetAndFlatten: LayoutProc = {
obj ← PW.Flatten[GetAndAddSuffix[cellType]];
};
Value: LayoutProc = {
obj ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreValue]];
};
DecorateValue: PUBLIC DecorateProc = {
extractedCT: CellType ← NARROW [Sinix.Extract[obj, extractMode].result];
extractedToSource: RefTab.Ref ← RefTab.Create[extractedCT.public.size];
FindInExtractedPublic: CoreOps.EachWireProc = {
FOR names: LIST OF ROPE ← CoreOps.GetFullWireNames[cellType.public, wire], names.rest WHILE names#NIL DO
name: ROPE ← names.first;
extractedWire: Wire ← CoreOps.FindWire[extractedCT.public, name];
previousSourceWire: Wire ← NARROW [RefTab.Fetch[extractedToSource, extractedWire].val];
IF extractedWire=NIL OR extractedWire.size#0 THEN LOOP;
IF previousSourceWire#NIL AND previousSourceWire#wire THEN SIGNAL PinsCorrespondingToSeveralPublics[cellType, obj, LIST [previousSourceWire, wire], CoreGeometry.GetPins[extractMode.decoration, extractedWire]];
IF NOT CoreGeometry.HasPins[extractMode.decoration, extractedWire]
THEN SIGNAL NoPinsOnAtomicPublic[cellType, obj, extractedWire, name];
CoreGeometry.AddIndirectLazyPins[extractMode.decoration, wire, extractedWire];
[] ← RefTab.Store[extractedToSource, extractedWire, wire];
ENDLOOP;
};
[] ← CoreOps.VisitWire[cellType.public, FindInExtractedPublic];
};
Abuts, Arrays and Recast
sisyphFudge: INTCD.FetchTechnology[$cmosB].lambda/2; -- Not very clean here!
AttributeAbutXorY: AttributesProc = {
ambiguous, inX: BOOL;
[ambiguous, inX] ← InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge];
IF ambiguous THEN ERROR Error[$CallerBug, "*** Ambiguity for deciding between AbutX and AbutY.\n", cellType];
SortInstances[Sisyph.mode.decoration, cellType, IF inX THEN SortInX ELSE SortInY];
};
LayoutAbutXorY: LayoutProc = {
obj ← (IF InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge].inX THEN AbutX ELSE AbutY)[cellType];
};
DecorateAbutXorY: DecorateProc = {
(IF InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge].inX THEN DecorateAbutX ELSE DecorateAbutY)[cellType, obj];
};
AttributeX: AttributesProc = {SortInstances[Sisyph.mode.decoration, cellType, SortInX]};
AttributeY: AttributesProc = {SortInstances[Sisyph.mode.decoration, cellType, SortInY]};
AbutX: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i: NAT DECREASING IN [0 .. data.size) DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListX[subObjects];
};
AbutY: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i: NAT DECREASING IN [0 .. data.size) DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListY[subObjects];
};
AbutFlipXAndDecorate: LayoutProc = {obj ← AbutFlipAndDecorate[cellType, TRUE]};
AbutFlipYAndDecorate: LayoutProc = {obj ← AbutFlipAndDecorate[cellType, FALSE]};
AbutFlipAndDecorate: PROC [cellType: CellType, inX: BOOL] RETURNS [obj: Object] = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
flip: BOOLFALSE; -- indicates polarity of the coming flip
instances: CD.InstanceList ← NIL; -- instances for constructing the cell
layout0: CD.Object ← Layout[data[0].type];
isize0: CD.Position ← CD.InterestSize[layout0];
pos: CD.Position ← [0, 0]; -- position (in ir coordonnates) of the coming cell
FOR i: NAT IN [0 .. data.size) DO
orientation: CD.Orientation ← IF flip THEN IF inX THEN mirrorX ELSE rotate180X ELSE original;
layout: CD.Object ← Layout[data[i].type];
ir: CD.Rect = CDBasics.MapRect[CD.InterestRect[layout], [[0, 0], orientation]];
isize: CD.Position ← CDBasics.SizeOfRect[ir];
trans: CD.Transformation = [CDBasics.SubPoints[pos, CDBasics.BaseOfRect[ir]], orientation]; -- translation, in the CD coordonnate system
IF NOT (IF inX THEN isize.y=isize0.y ELSE isize.x=isize0.x) THEN ERROR; -- incompatible y dimension for an abutX
instances ← CONS [CDInstances.NewInst[layout, trans], instances];
We decorate each instance with the appropriate trans, so that the Lazy GetPins can find the location
CoreGeometry.PutTrans[extractMode.decoration, data[i], trans];
IF inX THEN pos.x ← pos.x + isize.x ELSE pos.y ← pos.y + isize.y;
flip ← NOT flip;
ENDLOOP;
obj ← PW.CreateCell[instances: instances];
CoreGeometry.PutRecordLazyPins[extractMode.decoration, cellType, CD.InterestRect[obj]];
};
ReverseAbutX: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i: NAT IN [0 .. data.size) DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListX[subObjects];
};
ReverseAbutY: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i: NAT IN [0 .. data.size) DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListY[subObjects];
};
ArrayX: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawAbutX]; obj ← PW.CreateIndirect[Layout[recasted]];
};
ArrayY: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawAbutY]; obj ← PW.CreateIndirect[Layout[recasted]];
};
ArrayFlipX: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawAbutFlipX]; obj ← PW.CreateIndirect[Layout[recasted]];
};
ArrayFlipY: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawAbutFlipY]; obj ← PW.CreateIndirect[Layout[recasted]];
};
ReverseArrayX: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawReverseAbutX]; obj ← PW.CreateIndirect[Layout[recasted]];
};
ReverseArrayY: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawReverseAbutY]; obj ← PW.CreateIndirect[Layout[recasted]];
};
Recast: LayoutProc = {
obj ← PW.CreateIndirect[Layout[CoreOps.Recast[cellType]]];
};
DecorateAbut: PUBLIC PROC [cellType: CellType, obj: Object, sort: SortProc] = {
InsertInst: CDCells.InstEnumerator = {
IF inst.trans.orient#original THEN ERROR Error[$CallerBug, "DecorateAbut is only applicable to objects expanding into cells without rotation", cellType];
sorted ← CONS [inst, sorted];
};
CompareInst: GList.CompareProc = {
inst1: CD.Instance = NARROW [ref1];
inst2: CD.Instance = NARROW [ref2];
RETURN [IF sort[ObjectBase[inst1.ob, inst1.trans], ObjectBase[inst2.ob, inst2.trans]]
THEN less ELSE greater];
};
sorted: LIST OF CD.Instance;
recordData: CoreClasses.RecordCellType ← NARROW [cellType.data];
WHILE obj.class#CDCells.pCellClass DO obj ← CDDirectory.Expand1[obj].new ENDLOOP;
[] ← CDCells.EnumerateInstances[obj, InsertInst];
sorted ← NARROW [GList.Sort[sorted, CompareInst]];
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;
};
LayoutRotated: LayoutProc = {
orientation: CD.Orientation ← SELECT GetLayoutAtom[cellType] FROM
$FlipX  => mirrorX,
$FlipY  => rotate180X,
$Rot90  => rotate90,
$Rot90X  => rotate90X,
$Rot180  => rotate180,
$Rot180X  => rotate180X,
$Rot270  => rotate270,
$Rot270X  => rotate270X,
ENDCASE  => ERROR;
obj ← PW.CreateRotation[Layout[Rotated[cellType]], orientation];
};
DecorateRotated: PUBLIC DecorateProc = {
rotatedCT: CellType = Rotated[cellType];
trans: CoreGeometry.Transformation;
DecorateUniqueInst: CDCells.InstEnumerator = {trans ← inst.trans};
This line is important since obj can be of the class "Rotation" itself.
WHILE obj.class#CDCells.pCellClass DO obj ← CDDirectory.Expand1[obj].new ENDLOOP;
IF CDCells.CountInstances[obj]#1 THEN ERROR Error[$CallerBug, "DecorateRotated is not supposed to be called with an obj that does not expand into a one instance cell", cellType];
[] ← CDCells.EnumerateInstances[obj, DecorateUniqueInst];
CoreGeometry.PutTrans[extractMode.decoration, NARROW [cellType.data, CoreClasses.RecordCellType][0], trans];
CoreGeometry.PutRecordLazyPins[extractMode.decoration, cellType, CD.InterestRect[obj]];
};
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];
};
InstancesInXOrY: PUBLIC PROC [decoration: CoreGeometry.Decoration, record: CellType, fudge: INT ← 0] RETURNS [ambiguous, inX: BOOL] = {
data: CoreClasses.RecordCellType ← NARROW [record.data];
overlappingInX, overlappingInY: BOOLFALSE;
FOR i: NAT IN [0 .. data.size-1) DO
rect1: CD.Rect ← CDBasics.MapRect[
CD.InterestRect[CoreGeometry.GetObject[decoration, data[i].type]],
CoreGeometry.GetTrans[decoration, data[i]]
];
FOR j: NAT IN (i .. data.size) DO
rect2: CD.Rect ← CDBasics.MapRect[
CD.InterestRect[CoreGeometry.GetObject[decoration, data[j].type]],
CoreGeometry.GetTrans[decoration, data[j]]
];
IF rect1.x1+fudge<rect2.x2 AND rect2.x1+fudge<rect1.x2 THEN overlappingInX ← TRUE;
IF rect1.y1+fudge<rect2.y2 AND rect2.y1+fudge<rect1.y2 THEN overlappingInY ← TRUE;
ENDLOOP;
ENDLOOP;
ambiguous ← overlappingInX=overlappingInY;
inX ← overlappingInY;
};
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;
};
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];
};
Saving "Checkpoints"
Slight modification of CDDirectoryOps.IncludeDescribedObjects to avoid problems when dealing with objects inclkuded in 2 designs.
IncludeDescribedObjects: PROC [design: CD.Design, ob: CD.Object] = {
EachObject: CDDirectory.EachObjectProc = {
IF me.class.composed THEN {
name: Rope.ROPE ← CDDirectory.Name[me, design];
IF name#NIL THEN RETURN;
name ← NARROW [CDProperties.GetObjectProp[me, $Describe]];
IF name=NIL THEN RETURN;
Hack, of course!
IF CDProperties.GetObjectProp[me, $OwnerDesign]#NIL AND NOT me.immutable THEN RETURN;
[] ← CDDirectory.Include[design, me, name, TRUE];
}
};
[] ← CDDirectory.EnumerateObject[ob: ob, proc: EachObject]
};
Store: PUBLIC PROC [cellType: CellType, withCuteFonts: BOOLFALSE] = {
name: ROPE ← CoreOps.GetCellTypeName[cellType];
[] ← Layout[cellType]; -- necessary in order to generate layout
TerminalIO.PutF["Saving the Core for cell %g ...\n", IO.rope[name]];
[] ← CoreIO.ReportSaveCellType[cellType];
StoreShell[cellType, withCuteFonts];
StoreLayout[cellType];
TerminalIO.PutF["\nLayout checkpoint:\n %g.core\n %gLayout.dale\n %gShell.dale\n",
IO.rope[name], IO.rope[name], IO.rope[name]];
};
StoreShell: PUBLIC PROC [cellType: CellType, withCuteFonts: BOOLFALSE] = {
name: ROPE ← CoreOps.GetCellTypeName[cellType];
shellFileName: ROPE ← Rope.Cat[name, "Shell"];
shellDesign: CD.Design ← CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
shell: CD.Object;
TerminalIO.PutF["Saving the Shell for cell %g ...\n", IO.rope[name]];
shell ← CoreGeometry.CreateShell[extractMode.decoration, cellType, withCuteFonts];
shellDesign.name ← shellFileName;
[] ← CDDirectory.Include[shellDesign, shell, name];
[] ← CDOps.IncludeObjectI[shellDesign, shell];
[] ← CDIO.WriteDesign[shellDesign, shellFileName];
CDOps.SetMutability[shellDesign, inaccessible];
}; -- to avoid GCollected objects!
StoreLayout: PUBLIC PROC [cellType: CellType] = {
name: ROPE ← CoreOps.GetCellTypeName[cellType];
layoutFileName: ROPE ← Rope.Cat[name, "Layout"];
layoutDesign: CD.Design ← CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
layout: CD.Object ← Layout[cellType];
TerminalIO.PutF["Saving the Layout for cell %g ...\n", IO.rope[name]];
layoutDesign.name ← layoutFileName;
layout ← PW.CreateCell
[LIST [CDInstances.NewInst[layout]], CD.InterestRect[layout], name.Cat[".mask"]];
[] ← CDDirectory.Include[layoutDesign, layout, name.Cat[".mask"]];
[] ← CDOps.IncludeObjectI[layoutDesign, layout];
IncludeDescribedObjects[layoutDesign, layout];
[] ← CDIO.WriteDesign[layoutDesign, layoutFileName];
CDOps.SetMutability[layoutDesign, inaccessible];
}; -- to avoid GCollected objects!
Retrieve: PUBLIC PROC [name: ROPE, withLazyExtract: BOOLTRUE] RETURNS [cellType: CellType] = {
CopyPins: PROC [fromWire, toWire: Core.Wire] = {
IF NOT CoreGeometry.HasPins[PWCore.extractMode.decoration, fromWire]
THEN SIGNAL PWCore.NoPinsOnAtomicPublic[cellType, layout, fromWire, CoreOps.GetFullWireName[cellType.public, fromWire]];
CoreGeometry.PutIndirectsLazyPins[PWCore.extractMode.decoration, toWire, LIST [fromWire]];
};
layout: CoreGeometry.Object;
public: Core.WireSeq;
TerminalIO.PutF["Retrieving %g.core\n", IO.rope[name]];
cellType ← CoreIO.RestoreCellType[name];
TerminalIO.PutF["%g.core Retrieved\n", IO.rope[name]];
SetFromPWCore[cellType];
IF NOT withLazyExtract THEN RETURN;
public ← CoreOps.CopyWire[cellType.public];
layout ← PWCore.Layout[cellType];
CoreOps.VisitAtomicPairs[cellType.public, public, CopyPins];
Sinix.DecorateObjectWithLazyExtract[public, layout, PWCore.extractMode];
};
Backdoor for clients such as PWCoreLichen
LayoutInfo: PUBLIC PROC [sourceCT: CellType] RETURNS [layout: Object, extractedCT: CellType, extractedToSource: RefTab.Ref, key: INT] = {
layout ← PWCore.Layout[sourceCT];
extractedCT ← NARROW [Sinix.Extract[layout, extractMode].result];
key ← GetPWCoreExtractedCTKey[extractedCT];
extractedToSource ← Sinix.MapExtractedToSource[sourceCT.public, extractedCT.public, layout, PWCore.extractMode];
};
Initialization and various registrations
[] ← RegisterLayoutAtom[$Get, Get, DecorateValue];
[] ← RegisterLayoutAtom[$GetAndFlatten, GetAndFlatten, DecorateValue];
[] ← RegisterLayoutAtom[$Value, Value, DecorateValue];
[] ← RegisterLayoutAtom[$ValueNoDecorate, Value];
[] ← RegisterLayoutAtom[$AbutListXNoDecorate, AbutX];
[] ← RegisterLayoutAtom[$AbutListYNoDecorate, AbutY];
[] ← RegisterLayoutAtom[$RawAbutX, AbutX, DecorateAbutX];
[] ← RegisterLayoutAtom[$RawAbutY, AbutY, DecorateAbutY];
[] ← RegisterLayoutAtom[$RawAbutFlipX, AbutFlipXAndDecorate];
[] ← RegisterLayoutAtom[$RawAbutFlipY, AbutFlipYAndDecorate];
[] ← RegisterLayoutAtom[$AbutFlipX, AbutFlipXAndDecorate, NIL, AttributeX];
[] ← RegisterLayoutAtom[$AbutFlipY, AbutFlipYAndDecorate, NIL, AttributeY];
[] ← RegisterLayoutAtom[$RawReverseAbutX, ReverseAbutX, DecorateReverseAbutX];
[] ← RegisterLayoutAtom[$RawReverseAbutY, ReverseAbutY, DecorateReverseAbutY];
[] ← RegisterLayoutAtom[$AbutX, AbutX, DecorateAbutX, AttributeX];
[] ← RegisterLayoutAtom[$AbutY, AbutY, DecorateAbutY, AttributeY];
[] ← RegisterLayoutAtom[$Abut, LayoutAbutXorY, DecorateAbutXorY, AttributeAbutXorY];
[] ← RegisterLayoutAtom[$ReverseAbutX, ReverseAbutX, DecorateReverseAbutX, AttributeX];
[] ← RegisterLayoutAtom[$ReverseAbutY, ReverseAbutY, DecorateReverseAbutY, AttributeY];
[] ← RegisterLayoutAtom[$ArrayX, ArrayX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ArrayY, ArrayY, DecorateRecasted];
[] ← RegisterLayoutAtom[$ArrayFlipX, ArrayFlipX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ArrayFlipY, ArrayFlipY, DecorateRecasted];
[] ← RegisterLayoutAtom[$ReverseArrayX, ReverseArrayX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ReverseArrayY, ReverseArrayY, DecorateRecasted];
[] ← RegisterLayoutAtom[$Recast, Recast, DecorateRecasted];
[] ← RegisterLayoutAtom[$FlipX, LayoutRotated, DecorateRotated];
[] ← RegisterLayoutAtom[$FlipY, LayoutRotated, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot90, LayoutRotated, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot90X, LayoutRotated, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot180, LayoutRotated, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot180X, LayoutRotated, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot270, LayoutRotated, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot270X, LayoutRotated, DecorateRotated];
END.