<> <> <> <> <<-- PatchWork (PW) is a Silicon Assembler.>> <<>> DIRECTORY CD USING [Design, Instance, InstanceList, Object, original, Position], CDCells USING [CreateEmptyCell, RepositionCell, SetInterestRect], CDGenerate USING [GeneratorProc], CDOrient USING [mirrorX, mirrorY, Orientation, rotate90, rotate180, rotate270], IO USING [Value], PWPins USING [Side], Rope USING [ROPE], TerminalIO; PW: CEDAR DEFINITIONS IMPORTS CDCells, TerminalIO = BEGIN <> ROPE: TYPE = Rope.ROPE; -- Unavoidable <<>> <<-- The new hot types, identical to CD types>> Object: TYPE = CD.Object; -- an object, i.e. a definition ListOb: TYPE = LIST OF Object; Instance: TYPE = CD.Instance; -- an instance InstanceList: TYPE = CD.InstanceList; Design: TYPE = CD.Design; UserProc: TYPE = CDGenerate.GeneratorProc; -- PROC [design: Design, key: ROPE, table: CDGenerate.Table, data: REF] RETURNS [ob: Object_NIL] <> AbutProblem: SIGNAL [what: ROPE, isX: BOOL, ob1, ob2: Object]; <<-- This signal might be raised by an incorrect abut>> <> Reverse: PUBLIC PROC [listObj: ListOb] RETURNS [result: ListOb _ NIL]; <> ForEachInstProc: TYPE = PROC [inst: Instance, data: REF] RETURNS [newInst: Instance _ NIL]; <<-- Used in enumeration procs, for example by conditional objects>> <> <<-- The use of this subset is safe in the following sense: if a novice user (i.e. not Christian Jacobi or Don Curry) creates interactively cells with ChipNDale, and assembles them using only Abuts, MapFunction, and the like, then the resulting design is not going to give him any trouble: it should display, plot and turn into CIF with no complication.>> <<>> <<-- Abuts: the following procs create an Abut, which is not a cell, but a new class of CD object. >> <<-- All these proc can raise the signal AbutProblem>> <<-- The simple abutment uses the interestrect; it stops and complains if size mismatch; NIL is the neutral element. AbutX builds from left to right, and AbutY from bottom to top.>> AbutX: PROC [t1, t2, t3, t4, t5, t6: Object _ NIL] RETURNS [obj: Object]; AbutY: PROC [t1, t2, t3, t4, t5, t6: Object _ NIL] RETURNS [obj: Object]; AbutListX: PROC [listOb: ListOb] RETURNS [obj: Object]; AbutListY: PROC [listOb: ListOb] RETURNS [obj: Object]; <<>> <<-- AbutCheck: parse the pins and check if they match; stop and complain if pin mismatch>> <<-- pins match if: same width (depth does not matter), same position, same layer, names checked by a special proc.>> AbutCheckX: PROC [t1, t2, t3, t4, t5, t6: Object _ NIL] RETURNS [obj: Object]; AbutCheckY: PROC [t1, t2, t3, t4, t5, t6: Object _ NIL] RETURNS [obj: Object]; AbutCheckListX: PROC [listOb: ListOb] RETURNS [obj: Object]; AbutCheckListY: PROC [listOb: ListOb] RETURNS [obj: Object]; <<-- Arrays and other repetitions>> <<-- MapFunction evaluates the function over the domain [lx..ux)*[ly..uy) and abuts the resulting tiles in an array. Creates empty cell when lx>=ux or ly>=uy.>> XYFunction: TYPE = PROC [x, y: INT] RETURNS [resultingOb: Object]; MapFunctionX: PROC [function: XYFunction, lx: INT _ 0, ux: INT] RETURNS [new: Object]; MapFunctionY: PROC [function: XYFunction, ly: INT _ 0, uy: INT] RETURNS [new: Object]; MapFunction: PROC [function: XYFunction, lx: INT _ 0, ux: INT, ly: INT _ 0, uy: INT] RETURNS [new: Object]; <<>> MapFunctionIndexPins: PROC [function: XYFunction, lx: INT _ 0, ux: INT, ly: INT _ 0, uy: INT, indexedPins: ARRAY PWPins.Side OF LIST OF ROPE _ ALL [NIL]] RETURNS [new: Object]; <> <<>> <<-- Aligns nx tiles in the X (--) direction. If nx<=0 an empty cell is created>> ArrayX: PROC [ob: Object, nx: INT _ 1] RETURNS [Object]; <<-- Aligns ny tiles in the Y (|) direction. If nx<=0 an empty cell is created>> ArrayY: PROC [ob: Object, ny: INT _ 1] RETURNS [Object]; <<-- Equivalent to ArrayY[ArrayX[ob, nx], ny]: no flat 2D array>> Array: PROC [ob: Object, nx, ny: INT _ 1] RETURNS [new: Object]; <<>> <<-- Planar tranformations and instance names: these properties are usually associated to instances, not objects, so we have to add an extra level of hierarchy>> ChangeOrientation: PUBLIC PROC [obj: Object, orientation: CDOrient.Orientation] RETURNS [cell: Object]; <<-- Symmetry that changes X (so/Y)>> FlipX: PROC [ob: Object] RETURNS [Object] = INLINE {RETURN [ChangeOrientation[ob, CDOrient.mirrorX]]}; <> FlipY: PROC [ob: Object] RETURNS [Object] = INLINE {RETURN [ChangeOrientation[ob, CDOrient.mirrorY]]}; <> Identity: PROC [ob: Object] RETURNS [Object] = INLINE {RETURN [ob]}; <> Rot90: PROC [ob: Object] RETURNS [Object] = INLINE {RETURN [ChangeOrientation[ob, CDOrient.rotate90]]}; Rot180: PROC [ob: Object] RETURNS [Object] = INLINE {RETURN [ChangeOrientation[ob, CDOrient.rotate180]]}; Rot270: PROC [ob: Object] RETURNS [Object] = INLINE {RETURN [ChangeOrientation[ob, CDOrient.rotate270]]}; InstanceName: PROC [obj: Object, instanceName: ROPE] RETURNS [cell: Object]; <<>> <<-- Copy and conditional objects>> <<-- Copy: first level only, i.e. any subcell is just referenced, not duplicated>> Copy: PROC [ob: Object] RETURNS [new: Object]; <<-- Parametrized cells (conditional objects only for now) >> Inst: PROC [ob: Object, conds: LIST OF ROPE, removeNamed: BOOL _ TRUE] RETURNS [new: 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.>> Flatten: PROC [cell: Object] RETURNS [new: Object]; <<>> <<-- Designs, directories, . . .>> <> Get: PROC [design: Design, name: ROPE] RETURNS [ob: Object]; <<-- Open a design, given a file name>> OpenDesign: PROC [fileName: ROPE] RETURNS [design: Design]; <<-- Registration of a new UserProc>> Register: PROC [userProc: UserProc, name: ROPE]; <> <> SharedAbutX: PROC [t1, t2: Object _ NIL] RETURNS [obj: Object]; SharedAbutY: PROC [t1, t2: Object _ NIL] RETURNS [obj: Object]; SharedAbutListX: PROC [listOb: ListOb] RETURNS [obj: Object]; SharedAbutListY: PROC [listOb: ListOb] RETURNS [obj: Object]; FlushSharedCache: PROC; <> <> RegisterProp: PROC [prop: ATOM, copy: BOOL _ FALSE, flushOnEdit: BOOL _ FALSE] RETURNS [sameAtom: ATOM]; <<-- Empty cell: must be repositionned and included in a directory when filled>> CreateEmptyCell: PROC RETURNS [cell: Object] = INLINE {cell _ CDCells.CreateEmptyCell[]}; <<>> <<-- Include an object in a cell; position is relative to the InterestRect>> IncludeInCell: PROC [cell: Object, obj: Object, position: CD.Position _ [0, 0], orientation: CDOrient.Orientation _ CD.original] RETURNS [newInst: Instance]; <<>> <<-- Adds the properties of obj which are copiable to the ones of newObj>> AppendProps: PROC [newObj, obj: Object]; <<>> <> SetInterestRect: PROC [obj: Object, size: CD.Position] = INLINE {[] _ CDCells.SetInterestRect[obj, [0, 0, size.x, size.y]]}; <<-- Reposition the object. Should be called for every cell created by CreateEmptyCell, once filled and once interestRect positionned>> RepositionCell: PROC [obj: Object] = INLINE {[] _ CDCells.RepositionCell[obj, NIL]}; <<>> <<-- The following primitive allows the use of the InterestRect coordinates only: location is the position of the InterestRect of inst in the InterestRect coordinate system of obj>> GetLocation: PROC [inst: Instance, obj: Object] RETURNS [location: CD.Position]; <<-- Tries to find the property on the object, if it fails on the class, and if it fails expands (a failure in expansion provokes the return of NIL) and starts all over again.>> Send: PROC [obj: Object, prop: ATOM] RETURNS [value: REF _ NIL, expandedObj: Object]; <> ForEachPinProc: TYPE = PROC [inst: Instance] RETURNS [obj: Object]; SelectNamesProc: TYPE = PROC [name: ROPE] RETURNS [keepIt: BOOL]; KeepAll: SelectNamesProc; <<>> <<-- Transfer cell is a very Xerographic constructor: it first creates an empty cell: one dimension is the specified width, the other is the same as the side of the template; then it parses the side of the template, and for every pin it calls the objProc and sticks the resulting object in the cell so that it faces the pin; the object is rotated according to the side in use, and the right side corresponds to the original orientation>> TransferCell: PUBLIC PROC [template: Object, objSide: PWPins.Side, width: INT, objProc: ForEachPinProc, selectNameProc: SelectNamesProc _ KeepAll] RETURNS [cell: Object]; <<>> <<-- put pins, make by rotation!!!>> TopFillerCell: PROC [template: Object, height: INT, selectNameProc: SelectNamesProc _ KeepAll] RETURNS [cell: Object]; BottomFillerCell: PUBLIC PROC [template: Object, height: INT, selectNameProc: SelectNamesProc _ KeepAll] RETURNS [cell: Object]; LeftFillerCell: PROC [template: Object, width: INT, selectNameProc: SelectNamesProc _ KeepAll] RETURNS [cell: Object]; RightFillerCell: PUBLIC PROC [template: Object, width: INT, selectNameProc: SelectNamesProc _ KeepAll] RETURNS [cell: Object]; <> Draw: PROC [obj: CD.Object, technologyName: ATOM _ NIL] RETURNS [design: CD.Design]; <> <> <<-- Input and output from the terminal>> WriteF: PROC [format: ROPE _ NIL, v1, v2, v3, v4, v5: IO.Value _ [null[]]] = INLINE {TerminalIO.WriteF[format, v1, v2, v3, v4, v5]}; RequestRope: PROC [text: ROPE _ NIL] RETURNS [ROPE] = INLINE {RETURN[TerminalIO.RequestRope[text]]}; RequestInt: PROC [text: ROPE _ NIL] RETURNS [INT] = INLINE {RETURN[TerminalIO.RequestInt[text]]}; <<>> <<-- Predicates>> ODD: PROC [i: INT] RETURNS [BOOL]; EVEN: PROC [i: INT] RETURNS [BOOL]; <<>> <<-- Dealing with Log2 of numbers>> Log2: PROC [n: INT] RETURNS [INT]; TwoToThe: PROC [x: INT] RETURNS [INT]; TwoToTheLog2: PROC [n: INT] RETURNS [INT]; <<>> <<-- Extract the xth bit in the interger N>> <<-- Warning: bit 0 is the LOW order bit (lsb). That is NOT the mesa convention!>> XthBitOfN: PROC [x, n: INT] RETURNS [BOOL]; END.