PWCoreImpl.mesa
Copyright Ó 1985, 1987 by Xerox Corporation. All rights reserved.
Louis Monier May 17, 1986 1:35:25 pm PDT
Bertrand Serlet April 28, 1988 1:48:55 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, InstanceTable, IO,
PW, PWCore,
RefTab, Rope,
Sinix, SinixOps, Sisyph, TerminalIO;
PWCoreImpl:
CEDAR
PROGRAM
IMPORTS Atom, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties, CoreClasses, CoreIO, CoreOps, CoreProperties, CoreGeometry, GList, RefTab, InstanceTable, IO, PW, PWCore, Rope, Sinix, SinixOps, Sisyph, TerminalIO
EXPORTS PWCore
SHARES CDCells, CDDirectory =
BEGIN OPEN PWCore;
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: ROPE ← NIL] = 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:
ATOM ←
NIL] = {
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.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.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: INT ← LOOPHOLE [cellType];
IF CDProperties.GetObjectProp[obj, fromPWCoreProp]#NIL THEN Signal[cellType]; -- same object is stuffed on two different cells! That breaks the invariants, and Lichen will not work!
CDProperties.PutObjectProp[obj, fromPWCoreProp, NEW [FromPWCoreRecord ← [int]]];
};
Layout:
PUBLIC
PROC [cellType: CellType]
RETURNS [obj: Object] = {
layoutAtom: ATOM;
layoutAtomData: LayoutAtomData;
obj ← CoreGeometry.GetObject[extractMode.decoration, cellType];
IF obj#NIL THEN RETURN;
layoutAtom ← NARROW [CoreProperties.GetCellTypeProp[cellType, layoutAtomProp]];
IF layoutAtom=
NIL
THEN
layoutAtom ← NARROW [CoreProperties.GetCellClassProp[cellType.class, layoutAtomProp]];
IF layoutAtom=
NIL
AND cellType.class.recast=
NIL
THEN
ERROR Error[$NoLayoutAtom, "Impossible to find a layoutAtom for this cellType", cellType];
layoutAtomData ← GetLayoutAtomData[IF layoutAtom=NIL THEN $Recast ELSE layoutAtom];
IF layoutAtomData=
NIL
THEN
ERROR Error[$NoRegistration, IO.PutFR["LayoutAtom %g has not been registered", IO.atom[layoutAtom]], cellType];
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:
INT ←
CD.FetchTechnology[$cmosB].lambda/2;
-- Not very clean here!
AttributeAbutXorY: AttributesProc = {
ambiguous, inX: BOOL;
[ambiguous, inX] ← InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge];
IF ambiguous THEN ERROR Error[$CallerBug, "*** Ambiguity for deciding between AbutX and AbutY.\n", cellType];
SortInstances[Sisyph.mode.decoration, cellType, IF inX THEN SortInX ELSE SortInY];
};
LayoutAbutXorY: LayoutProc = {
obj ← (IF InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge].inX THEN AbutX ELSE AbutY)[cellType];
};
DecorateAbutXorY: DecorateProc = {
(IF InstancesInXOrY[Sisyph.mode.decoration, cellType, sisyphFudge].inX THEN DecorateAbutX ELSE DecorateAbutY)[cellType, obj];
};
AttributeX: AttributesProc = {SortInstances[Sisyph.mode.decoration, cellType, SortInX]};
AttributeY: AttributesProc = {SortInstances[Sisyph.mode.decoration, cellType, SortInY]};
AbutX: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i:
NAT
DECREASING
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListX[subObjects];
};
AbutY: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i:
NAT
DECREASING
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListY[subObjects];
};
AbutFlipXAndDecorate: LayoutProc = {obj ← AbutFlipAndDecorate[cellType,
TRUE]};
AbutFlipYAndDecorate: LayoutProc = {obj ← AbutFlipAndDecorate[cellType,
FALSE]};
AbutFlipAndDecorate:
PROC [cellType: CellType, inX:
BOOL]
RETURNS [obj: Object] = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
flip: BOOL ← FALSE; -- indicates polarity of the coming flip
instances: CD.InstanceList ← NIL; -- instances for constructing the cell
layout0: CD.Object ← Layout[data[0].type];
isize0: CD.Position ← CD.InterestSize[layout0];
pos: CD.Position ← [0, 0]; -- position (in ir coordonnates) of the coming cell
FOR i:
NAT
IN [0 .. data.size)
DO
orientation: CD.Orientation ← IF flip THEN IF inX THEN mirrorX ELSE rotate180X ELSE original;
layout: CD.Object ← Layout[data[i].type];
ir: CD.Rect = CDBasics.MapRect[CD.InterestRect[layout], [[0, 0], orientation]];
isize: CD.Position ← CDBasics.SizeOfRect[ir];
trans: CD.Transformation = [CDBasics.SubPoints[pos, CDBasics.BaseOfRect[ir]], orientation]; -- translation, in the CD coordonnate system
IF NOT (IF inX THEN isize.y=isize0.y ELSE isize.x=isize0.x) THEN ERROR; -- incompatible y dimension for an abutX
instances ← CONS [CDInstances.NewInst[layout, trans], instances];
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;
};
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};
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: BOOL ← FALSE;
FOR i:
NAT
IN [0 .. data.size-1)
DO
rect1:
CD.Rect ← CDBasics.MapRect[
CD.InterestRect[CoreGeometry.GetObject[decoration, data[i].type]],
CoreGeometry.GetTrans[decoration, data[i]]
];
FOR j:
NAT
IN (i .. data.size)
DO
rect2:
CD.Rect ← CDBasics.MapRect[
CD.InterestRect[CoreGeometry.GetObject[decoration, data[j].type]],
CoreGeometry.GetTrans[decoration, data[j]]
];
IF rect1.x1+fudge<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:
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];
};
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:
BOOL ←
FALSE] = {
name: ROPE ← CoreOps.GetCellTypeName[cellType];
TerminalIO.PutF["Saving the Core for cell %g ...\n", IO.rope[name]];
[] ← CoreIO.ReportSaveCellType[cellType];
StoreShell[cellType, withCuteFonts];
StoreLayout[cellType];
TerminalIO.PutF["\nLayout checkpoint:\n %g.core\n %gLayout.dale\n %gShell.dale\n",
IO.rope[name], IO.rope[name], IO.rope[name]]};
StoreShell:
PUBLIC
PROC [cellType: CellType, withCuteFonts:
BOOL ←
FALSE] = {
name: ROPE ← CoreOps.GetCellTypeName[cellType];
shellFileName: ROPE ← Rope.Cat[name, "Shell"];
shellDesign: CD.Design ← CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
shell: CD.Object;
TerminalIO.PutF["Saving the Shell for cell %g ...\n", IO.rope[name]];
shell ← CoreGeometry.CreateShell[extractMode.decoration, cellType, withCuteFonts];
shellDesign.name ← shellFileName;
[] ← CDDirectory.Include[shellDesign, shell, name];
[] ← CDOps.IncludeObjectI[shellDesign, shell];
[] ← CDIO.WriteDesign[shellDesign, shellFileName];
CDOps.SetMutability[shellDesign, inaccessible]}; -- to avoid GCollected objects!
StoreLayout:
PUBLIC
PROC [cellType: CellType] = {
name: ROPE ← CoreOps.GetCellTypeName[cellType];
layoutFileName: ROPE ← Rope.Cat[name, "Layout"];
layoutDesign: CD.Design ← CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
layout: CD.Object ← Layout[cellType];
TerminalIO.PutF["Saving the Layout for cell %g ...\n", IO.rope[name]];
layoutDesign.name ← layoutFileName;
layout ←
PW.CreateCell
[LIST [CDInstances.NewInst[layout]], CD.InterestRect[layout], name.Cat[".mask"]];
[] ← CDDirectory.Include[layoutDesign, layout, name.Cat[".mask"]];
[] ← CDOps.IncludeObjectI[layoutDesign, layout];
IncludeDescribedObjects[layoutDesign, layout];
[] ← CDIO.WriteDesign[layoutDesign, layoutFileName];
CDOps.SetMutability[layoutDesign, inaccessible]}; -- to avoid GCollected objects!
Retrieve:
PUBLIC
PROC [name:
ROPE]
RETURNS [cellType: CellType] = {
obj: CD.Object;
TerminalIO.PutF["Retrieving %g.core\n", IO.rope[name]];
cellType ← CoreIO.RestoreCellType[name];
obj ← CoreGeometry.GetObject[extractMode.decoration, cellType];
SetFromPWCore[cellType];
TerminalIO.PutF["%g.core Retrieved\n", IO.rope[name]]};
Backdoor for clients such as PWCoreLichen
LayoutInfo:
PUBLIC
PROC [sourceCT: CellType]
RETURNS [layout: Object, extractedCT: CellType, extractedToSource: RefTab.Ref, key:
INT] = {
FillTable:
PROC [sourcePublic: Wire] = {
EachSourcePin: CoreGeometry.EachInstanceProc = {
Action:
PROC [extractedInstance: CoreGeometry.Instance, value: InstanceTable.Value] = {
extractedWire: Wire = NARROW [value];
prevSource: Wire ← NARROW [RefTab.Fetch[extractedToSource, extractedWire].val];
IF prevSource=sourcePublic THEN RETURN; -- already considered
IF
NOT extractMode.touchProc[extractMode.touchProc, instance, extractedInstance]
THEN RETURN;
IF prevSource#NIL THEN SIGNAL PinsCorrespondingToSeveralPublics[sourceCT, layout, LIST [prevSource, sourcePublic], LIST [instance, extractedInstance]];
[] ← RefTab.Store[extractedToSource, extractedWire, sourcePublic];
};
InstanceTable.Enumerate[extractedInstances, Action, CoreGeometry.BBox[instance]];
};
[] ← CoreGeometry.EnumeratePins[extractMode.decoration, sourcePublic, EachSourcePin];
};
extractedInstances: InstanceTable.Table; -- table instance -> extractedPublic
layout ← PWCore.Layout[sourceCT];
extractedCT ← NARROW [Sinix.Extract[layout, extractMode].result];
extractedToSource ← RefTab.Create[]; -- maps extractedWire to source
extractedInstances ← InstanceTableFromPublic[extractMode.decoration, layout.bbox, extractedCT.public];
key ← GetPWCoreExtractedCTKey[extractedCT];
CoreOps.VisitRootAtomics[sourceCT.public, FillTable];
};
Creates a table instance -> public
InstanceTableFromPublic:
PROC [decoration: CoreGeometry.Decoration, bbox:
CD.Rect, public: WireSeq]
RETURNS [table: InstanceTable.Table] = {
FillInstanceTable:
PROC [wire: Wire] = {
AddPinInTable: CoreGeometry.EachInstanceProc = {
InstanceTable.Insert[table, instance, wire];
};
[] ← CoreGeometry.EnumeratePins[decoration, wire, AddPinInTable];
};
table ← InstanceTable.Create[bbox];
CoreOps.VisitRootAtomics[public, FillInstanceTable];
};
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, FlipX, DecorateRotated];
[] ← RegisterLayoutAtom[$FlipY, FlipY, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot90, Rot90, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot180, Rot180, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot270, Rot270, DecorateRotated];
END.