PW.mesa 
Copyright Ó 1984, 1985, 1986, 1987 by Xerox Corporation. All rights reserved.
Louis Monier August 22, 1985 12:23:42 pm PDT
Bertrand Serlet July 7, 1987 1:29:49 pm PDT
DIRECTORY CD, CDDirectory, CDGenerate, Rope;
PW: CEDAR DEFINITIONS = BEGIN
Abuts: Primitives
Abuts differ from cells by the fact they contain an ordered list of subObjects abutted one next to the other, and not a set of instances. There is more information in an AbutX (resp. Y): the order of subObjects is important and the leftmost (resp. bottommost) is the first one. Not all cells can be described with Abuts: for example the ones which have overlapping instances. Abutted cells are checked for compatible sizes. Origin for the abutted objects is the InterestRect. For abuts, the InterestBase is [0, 0].
abutXClass: CD.ObjectClass;
abutYClass: CD.ObjectClass;
CreateAbutProc: TYPE = PROC [subObjects: LIST OF CD.Object ← NIL, name: Rope.ROPENIL, props: CD.PropList ← NIL] RETURNS [newAbut: CD.Object];
CreateNewAbutX: CreateAbutProc;
CreateNewAbutY: CreateAbutProc;
EachSubObjectProc: TYPE = PROC [subObject: CD.Object, pos: CD.Position] RETURNS [quit: BOOLFALSE];
pos is relative to the [0, 0] of the abut
EnumerateSubObjects: PROC [abut: CD.Object, eachSubObject: EachSubObjectProc] RETURNS [BOOL];
abut is assumed to be of class abutXClass or abutYClass.
returns position of a would-be after-last sub-object, relative to the [0, 0] of the abut
CountSubObjects: PROC [abut: CD.Object] RETURNS [size: NAT];
Abuts: Sugared
For the following functions, NIL acts as neutral element.
AbutX: PROC [t1, t2, t3, t4, t5, t6: CD.Object ← NIL] RETURNS [obj: CD.Object];
builds from left to right.
AbutY: PROC [t1, t2, t3, t4, t5, t6: CD.Object ← NIL] RETURNS [obj: CD.Object];
builds from bottom to top.
AbutListX: PROC [objects: LIST OF CD.Object, name: Rope.ROPENIL, props: CD.PropList ← NIL] RETURNS [obj: CD.Object];
builds from left to right.
AbutListY: PROC [objects: LIST OF CD.Object, name: Rope.ROPENIL, props: CD.PropList ← NIL] RETURNS [obj: CD.Object];
builds from bottom to top.
MapFunction: PROC [function: PROC [INT, INT] RETURNS [CD.Object], lx: INT ← 0, ux: INT, ly: INT ← 0, uy: INT] RETURNS [CD.Object];
evaluates function over the domain [lx..ux)*[ly..uy) and abuts the resulting tiles in an array.
ArrayX: PROC [obj: CD.Object, nx: INT ← 1] RETURNS [CD.Object];
Aligns nx tiles in the X direction.
ArrayY: PROC [obj: CD.Object, ny: INT ← 1] RETURNS [CD.Object];
Aligns ny tiles in the Y direction.
Array: PROC [obj: CD.Object, nx, ny: INT ← 1] RETURNS [CD.Object];
Aligns nx tiles in the X direction and ny tiles in the Y direction.
Rotations
Rotations allow a far more memory efficient representation of rotated (or mirrored) objects than cells.
rotationClass: CD.ObjectClass;
RotationSpecific: TYPE = REF RotationSpecificRec;
RotationSpecificRec: TYPE = RECORD [
ir: CD.Rect,   -- for algorithmic efficiency
obj: CD.Object,
orientation: CD.Orientation
];
CreateRotation: PROC [obj: CD.Object, orientation: CD.Orientation, name: Rope.ROPENIL, props: CD.PropList ← NIL] RETURNS [rotation: CD.Object];
Creates a new rotation. Returns NIL if obj is NIL.
FlipX: PROC [obj: CD.Object] RETURNS [CD.Object] =
INLINE {RETURN [CreateRotation[obj, mirrorX]]};
Symetry that changes X (so/Y)
FlipY: PROC [obj: CD.Object] RETURNS [CD.Object] =
INLINE {RETURN [CreateRotation[obj, rotate180X]]};
Symmetry that changes Y (so/X)
Rot90: PROC [obj: CD.Object] RETURNS [CD.Object] =
INLINE {RETURN [CreateRotation[obj, rotate90]]};
Counter-clockwise
Rot180: PROC [obj: CD.Object] RETURNS [CD.Object] =
INLINE {RETURN [CreateRotation[obj, rotate180]]};
Rot270: PROC [obj: CD.Object] RETURNS [CD.Object] =
INLINE {RETURN [CreateRotation[obj, rotate270]]};
Indirect
Indirect objects introduce one level of indirection, so that users can store properties both on indirect objects and their source. No new code is necessary for Indirects since they use the expand mechanism. The result of the expansion is never included in the directory, for the expanded cell might be already in another directory. They are used to implement low weight imports in PW.
indirectClass: CD.ObjectClass;
CreateIndirect: PROC [sourceObject: CD.Object, name: Rope.ROPENIL, props: CD.PropList ← NIL] RETURNS [indirectObject: CD.Object];
Creates a new IndirectObject. Returns NIL if sourceObject is NIL.
Lazy
Lazy objects are basically a way of avoiding the static creation of huge cells, by expanding them on demand. All the data structure contained in a Lazy object is a CreateProc returning an CD.Object, and the necessary parameters to apply to this proc, when it is really needed to expand this fake object into an ordinary CD object.
Lazy objects will permit the construction of huge circuits, if they are used so to generate basic bricks. They open the space/time compromise when generating geometry.
It is assumed that the info field contains no CD object, so that changing a cell has no consequence on the Lazy object.
It is also supposed that the createProc computing the geometry of the object is fast enough, so that there is no need to cache it. If it is not the case, the client can use a cache inside the createProc.
lazyClass: CD.ObjectClass;
CreateProc: TYPE = PROC [info: REF] RETURNS [obj: CD.Object];
CreateLazy: PROC [info: REF, createProc: CreateProc, bbox, ir: CD.Rect, name: Rope.ROPENIL, props: CD.PropList ← NIL] RETURNS [newLazy: CD.Object];
Creates a new Lazy object.
It is assumed that: CreateProc[info].bbox=bbox AND CD.InterestRect[CreateProc[info]]=ir
Tilings
Tilings are two dimensional abuts. Having a special class allows fast extraction.
tilingClass: CD.ObjectClass;
CreateTiling: PROC [sizeX, sizeY: NAT, tiles: PROC [x, y: NAT] RETURNS [CD.Object], name: Rope.ROPENIL, props: CD.PropList ← NIL] RETURNS [tiling: CD.Object];
x varies in [0 .. sizeX); y varies in [0 .. sizeY).
All tiles in a row should have same height and all tiles in a column should have same width.
EachTileProc: TYPE = PROC [x, y: NAT, tile: CD.Object, pos: CD.Position] RETURNS [quit: BOOLFALSE];
pos is relative to the [0, 0] of the tiling.
EnumerateTiles: PROC [tiling: CD.Object, eachTile: EachTileProc] RETURNS [BOOL];
tiling is assumed to be of class tilingClass.
GetTilingSize: PROC [tiling: CD.Object] RETURNS [sizeX, sizeY: NAT];
Accesses size of the tiling.
GetTile: PROC [tiling: CD.Object, x, y: NAT] RETURNS [tile: CD.Object];
Accesses individual tiles.
Implementors goodies
CreateCell: PROC [instances: CD.InstanceList, ir: CD.Rect ← [0, 0, -1, -1], name: Rope.ROPENIL, props: CD.PropList ← NIL] RETURNS [CD.Object];
This is the right way to create cells (it should be in CDCells!).
SetName: PROC [obj: CD.Object, name: Rope.ROPENIL];
Sets or removes a hint name.
Name: PROC [obj: CD.Object] RETURNS [name: Rope.ROPE];
Retrieves a hint name.
If none, searches the accessible designs.
Get: PROC [design: CD.Design, name: Rope.ROPE] RETURNS [obj: CD.Object];
Fetches the object named name in design, makes a copy of it (if not previously done), and returns a read-only object.
Provokes an ERROR if name is not found in design.
Flatten: PROC [cell: CD.Object] RETURNS [new: CD.Object];
Flattens the content of a cell.
Works all the way (not just the top level), and even on Abuts.
Does not flatten cell marked with a non-nil $DontFlatten property.
GeneratorProc: TYPE = CDGenerate.GeneratorProc;
RegisterGenerator: PROC [generator: GeneratorProc, name: Rope.ROPE];
Registration of a new generator.
RegisterProp: PROC [prop: ATOM, copy: BOOLFALSE, flushOnEdit: BOOLFALSE] RETURNS [sameAtom: ATOM];
This goodie is to register a property which is an ATOM (instead of a REF), when you do not care about registering it many times, and so that it is easy to specify the copy proc. If the argument flushOnEdit is set to TRUE, all edits of a cell will provoke the dismiss of the property for that cell and all the cells that depends on it.
RegisterClass: PROC [objectType: ATOM, expand: CDDirectory.ExpandProc, enumerateChildObjects: CDDirectory.EnumerateChildObjectsProc ← NIL, replaceDirectChilds: CDDirectory.ReplaceDChildsProc ← NIL, interestRect: CD.RectProc ← NIL, drawMe, quickDrawMe, showMeSelected: CD.DrawProc ← NIL] RETURNS [objectClass: CD.ObjectClass];
Yes, it is perfectly legal to run this proc twice!
All the defaults are the one you dream
Utilities for debug
OpenDesign: PROC [fileName: Rope.ROPE] RETURNS [design: CD.Design];
Convenience for using the interpreter.
Draw: PROC [obj: CD.Object, technologyName: ATOMNIL] RETURNS [design: CD.Design];
Creates a new CD viewer and displays the object. Default is $cmosB technology. The object and its depencies are NOT included in the design.
END.