DIRECTORY CD, CDBasics, CDCells, CDDirectory, CDInstances, CDOps, CDProperties, CDSymbolicObjects, CDViewer, Core, CoreBlock, CoreClasses, CoreGeometry, CoreLibrary, CoreName, CoreProperties, HashTable, IO, PW, PWC, Rope, RopeList, Rosemary, TerminalIO, ViewerClasses, WriteCapa; CoreLibraryImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDDirectory, CDInstances, CDProperties, CDSymbolicObjects, CoreBlock, CoreClasses, CoreGeometry, CoreName, CoreProperties, HashTable, IO, PW, PWC, Rope, RopeList, Rosemary, TerminalIO, WriteCapa EXPORTS CoreLibrary = BEGIN Signal: SIGNAL = CODE; ROPE: TYPE = Core.ROPE; CellType: TYPE = Core.CellType; Library: TYPE = CoreLibrary.Library; LibraryRec: TYPE = CoreLibrary.LibraryRec; RenamePinsProc: TYPE = CoreLibrary.RenamePinsProc; designArchive: LIST OF CD.Design _ NIL; -- prevent garbage collection OpenLibrary: PUBLIC PROC[name: ROPE] RETURNS[lib: Library] = { lib _ NEW[LibraryRec _ [ design: PW.OpenDesign[name], table: HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope] ] ]; IF lib.design=NIL THEN Signal[]; designArchive _ CONS[lib.design, designArchive]}; Set: PUBLIC PROC[ lib: Library, name: ROPE, cell: Core.CellType ] = { old: Core.CellType; name _ CoreName.CellNm[cell, name].n; IF name.Length[]=0 THEN Signal[]; old _ NARROW[HashTable.Fetch[lib.table, name].value]; IF old#NIL AND old#cell THEN Signal[]; [ ] _ HashTable.Store[lib.table, name, cell]}; ObjCell: PUBLIC PROC[ obj: CD.Object, name: ROPE, rename: RenamePinsProc _ NIL, flatten: INT _ -1] RETURNS[cell: Core.CellType] = { TerminalIO.PutF["Define Core Cell: %g\n", IO.rope[name]]; IF flatten=-1 THEN obj _ Flatten[obj, rename] -- New independent object ELSE THROUGH [0..flatten) DO obj _ FlattenOneLevel[obj, rename].new ENDLOOP; IF name.Length[]=0 THEN Signal[]; IF CDDirectory.Name[obj]=NIL THEN PWC.SetObjName[obj, name]; cell _ PWC.Extract[obj]; IF CoreProperties.GetCellTypeProp[cell, $CoreIOGlobal]#NIL THEN RETURN[cell]; [] _ CoreProperties.PutCellTypeProp[cell, $CoreIOGlobal, $CoreIOGlobal]; [] _ CoreName.CellNm[cell, name]; CoreBlock.MarkSides[cell]; CoreBlock.DeletePseudoPublics[cell]; WriteCapa.WriteWireCapa[cell]; -- put capacitance on all leaf cells MarkWeakTransistors[cell]; }; Flatten: PUBLIC PROC [cell: CD.Object, rename: RenamePinsProc_NIL] RETURNS [new: CD.Object] = { flat: BOOL _ FALSE; new _ Crystallize[cell]; TerminalIO.PutF["Flatten cell: %g ", IO.rope[NARROW[new.specificRef, CD.CellPtr].name]]; FOR pass: INT IN [0..10) WHILE NOT flat DO TerminalIO.PutF["."]; [new, flat] _ FlattenOneLevel[new, rename] ENDLOOP; TerminalIO.PutF[" done\n"]}; FlattenOneLevel: PUBLIC PROC [cell: CD.Object, rename: RenamePinsProc_NIL] RETURNS [new: CD.Object, flat: BOOL _ TRUE] = { IncludeInNew: PROC[child: CD.Instance] = { baby: CD.Instance; IF CDSymbolicObjects.IsPin[child.ob] AND rename#NIL THEN { name: ROPE _ CDSymbolicObjects.GetName[child]; sides: CoreGeometry.Sides _ CoreGeometry.GetSides[iRect, child]; SELECT TRUE FROM sides[left] => name _ rename[name, left, child.location.y-iBase.y]; sides[right] => name _ rename[name, right, child.location.y-iBase.y]; sides[top] => name _ rename[name, top, child.location.x-iBase.x]; sides[bottom] => name _ rename[name, bottom, child.location.x-iBase.x]; ENDCASE => RETURN; IF name=NIL THEN RETURN; CDSymbolicObjects.SetName[child, name]}; baby _ CDCells.IncludeOb[ design: NIL, cell: new, ob: child.ob, position: child.location, -- iBase, orientation: child.orientation, cellCSystem: cdCoords, -- interrestCoords, obCSystem: cdCoords, -- interrestCoords, mode: dontPropagate ].newInst; CDProperties.CopyProps[child.properties, baby] }; list0, list1: CD.InstanceList; iRect: CD.Rect _ CD.InterestRect[cell]; iBase: CD.Position _ CDBasics.BaseOfRect[iRect]; IF NOT CDCells.IsCell[cell] THEN ERROR; new _ CDCells.CreateEmptyCell[]; CDCells.SetInterestRect[new, CD.InterestRect[cell]]; list0 _ NARROW [cell.specificRef, CD.CellPtr].contents; FOR list0 _ list0, list0.rest WHILE list0 # NIL DO inst: CD.Instance _ NEW[CD.InstanceRep _ list0.first^]; inst.ob _ Crystallize[inst.ob]; IF CDCells.IsCell[inst.ob] THEN { list1 _ NARROW [inst.ob.specificRef, CD.CellPtr].contents; list1 _ CDInstances.ComposedList[list1, inst.location, inst.ob.size, inst.orientation]; FOR list1 _ list1, list1.rest WHILE list1 # NIL DO flat _ flat AND NOT inst.ob.class.inDirectory; IncludeInNew[list1.first] ENDLOOP } ELSE IncludeInNew[inst]; ENDLOOP; [ ] _ CDCells.RepositionCell[new, NIL] }; Crystallize: PUBLIC PROC [cell: CD.Object] RETURNS [new: CD.Object] = { new _ cell; WHILE cell.class.inDirectory AND NOT CDCells.IsCell[new] DO new _ CDDirectory.Expand[new, NIL, NIL].new; IF new=NIL THEN Signal[]; ENDLOOP}; FlattenAll: PROC [cell: CD.Object] RETURNS [new: CD.Object] = { cell _ Crystallize[cell]; TerminalIO.PutF["Flatten cell: %g \n", IO.rope[NARROW[cell.specificRef, CD.CellPtr].name]]; new _ FlattenAllLevels[cell]}; FlattenAllLevels: PROC [cell: CD.Object] RETURNS [new: CD.Object] = { IncludeInNew: PROC[child: CD.Instance] = { baby: CD.Instance; baby _ CDCells.IncludeOb[ design: NIL, cell: new, ob: child.ob, position: child.location, -- iBase, orientation: child.orientation, cellCSystem: cdCoords, -- interrestCoords, obCSystem: cdCoords, -- interrestCoords, mode: dontPropagate ].newInst; CDProperties.CopyProps[child.properties, baby] }; list0, list1: CD.InstanceList; iBase: CD.Position _ CDBasics.BaseOfRect[CD.InterestRect[cell]]; IF NOT cell.class.inDirectory THEN RETURN[cell]; cell _ Crystallize[cell]; new _ CDCells.CreateEmptyCell[]; CDCells.SetInterestRect[new, CD.InterestRect[cell]]; list0 _ NARROW [cell.specificRef, CD.CellPtr].contents; FOR list0 _ list0, list0.rest WHILE list0 # NIL DO inst: CD.Instance _ NEW[CD.InstanceRep _ list0.first^]; inst.ob _ FlattenAllLevels[inst.ob]; IF NOT CDCells.IsCell[inst.ob] THEN IncludeInNew[inst] ELSE { list1 _ NARROW [inst.ob.specificRef, CD.CellPtr].contents; list1 _ CDInstances.ComposedList[list1, inst.location, inst.ob.size, inst.orientation]; FOR list1 _ list1, list1.rest WHILE list1 # NIL DO IncludeInNew[list1.first] ENDLOOP }; ENDLOOP; [ ] _ CDCells.RepositionCell[new, NIL] }; MarkWeakTransistors: PROC [cell: CellType] = { SELECT cell.class FROM CoreClasses.transistorCellClass => ERROR; CoreClasses.recordCellClass => { data: CoreClasses.RecordCellType _ NARROW[cell.data]; FOR child: NAT IN [0..data.size) DO IF data.instances[child].type.class # CoreClasses.transistorCellClass THEN MarkWeakTransistors[ data.instances[child].type] ELSE { name: ROPE _ NARROW [CoreProperties.GetCellInstanceProp[data.instances[child], $CoreName]]; IF Rope.Equal[name, "driveWeak"] THEN [] _ Rosemary.SetTransistorInstanceSize[data.instances[child], driveWeak]}; ENDLOOP }; ENDCASE => ERROR}; END. 2CoreLibraryImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Curry October 18, 1986 5:36:16 pm PDT Don Curry October 27, 1986 12:46:49 pm PST Last Edited by: Louis Monier February 10, 1987 9:37:52 pm PST Get: PUBLIC PROC[ lib: Library, name: ROPE, removeNamed: BOOL _ TRUE, conds: LIST OF ROPE _ NIL, flatten: INT _ -1, merge: BOOL _ FALSE] RETURNS[cell: Core.CellType] = { obj: CD.Object; refName: ROPE _ name; IF name.Length[]=0 THEN Signal[]; IF conds#NIL THEN { conds _ RopeList.Sort[conds, RopeList.Compare]; refName _ refName.Cat[IF removeNamed THEN "-Remove" ELSE "-Keep"]; FOR list: LIST OF ROPE _ conds, list.rest WHILE list#NIL DO refName _ refName.Cat["-", (IF list.first=NIL THEN "NONE" ELSE list.first)] ENDLOOP }; name _ CoreName.RopeNm[name]; refName _ CoreName.RopeNm[refName]; cell _ NARROW[HashTable.Fetch[lib.table, refName].value]; IF cell#NIL THEN RETURN[cell]; obj _ CDDirectory.Fetch[lib.design, name].object; IF obj=NIL THEN RETURN[NIL]; IF conds#NIL THEN obj _PW.Inst[obj, conds, removeNamed]; cell _ ObjCell[obj, refName, NIL, flatten]; IF merge THEN CoreBlock.MergeCell[cell]; Set[lib, refName, cell]}; cell _ PWC.Extract[obj ! Sinix.FusionPropMismatch => {IF CheckMismatch[name, prop, value1, value2].ok THEN RESUME}]; Sos.CheckDesignRules [cell, NIL, NIL, TRUE, $PWCLayout, $SinixCMosBInstance, $SinixCMosBWireGeometry]; CheckMismatch: PROC[name: ROPE, prop: ATOM, value1, value2: REF] RETURNS[ok: BOOL] = { log: IO.STREAM _ CoreFrame.GetLog[]; nv, ng, rv, rg: BOOL _ FALSE; r1, r2: ROPE; cnt: INT _ 0; IF prop#$CoreName THEN RETURN[FALSE]; r1 _ NARROW[value1]; r2 _ NARROW[value2]; IF Rope.Find[name, "VDD", 0, FALSE]>0 THEN nv _ TRUE; IF Rope.Find[name, "GND", 0, FALSE]>0 THEN ng _ TRUE; IF Rope.Equal[r1, "VDD", FALSE] THEN {rv _ TRUE; cnt _ cnt+1}; IF Rope.Equal[r1, "GND", FALSE] THEN {rg _ TRUE; cnt _ cnt+1}; IF Rope.Equal[r2, "VDD", FALSE] THEN {rv _ TRUE; cnt _ cnt+1}; IF Rope.Equal[r2, "GND", FALSE] THEN {rg _ TRUE; cnt _ cnt+1}; ok _ cnt=1 AND ((rv AND nv) OR (rg AND ng)); IF ok THEN log.PutF["%g and %g fused in %g\n", IO.rope[r1], IO.rope[r2], IO.rope[name] ]}; MergeUnnamedWellPublic: PROC [cell: Core.CellType] = { publics: Core.Wires _ NIL; vddPins: LIST OF CD.Instance _ NIL; vdd: Core.Wire _ CoreOps.FindWire[cell.public, "VDD"]; IF vdd=NIL THEN vdd _ CoreOps.FindWire[cell.public, "+"]; IF vdd#NIL THEN vddPins _ CoreGeometry.GetPins[PWC.extractMode.decoration, vdd]; FOR i: INT DECREASING IN [0..cell.public.size) DO list: LIST OF CD.Instance; IF CoreName.WireNm[cell.public[i]].n.Length[]#0 THEN {publics _ CONS[cell.public[i], publics]; LOOP}; list _ CoreGeometry.GetPins[PWC.extractMode.decoration, cell.public[i]]; FOR list _ list, list.rest WHILE list#NIL DO IF list.first.ob.layer#CMosB.nwell THEN Signal[] ELSE vddPins_CONS[list.first, vddPins]; ENDLOOP; IF vdd=NIL THEN { [] _ CoreName.WireNm[cell.public[i], "VDD"]; TerminalIO.PutF["Unnamed NWell public renamed to VDD\n"]; vdd _ cell.public[i]; publics _ CONS[cell.public[i], publics]} ELSE TerminalIO.PutF["Removing Unnamed NWell public\n"]; ENDLOOP; cell.public _ CoreOps.CreateWire[publics]; CoreGeometry.PutPins[PWC.extractMode.decoration, vdd, vddPins]}; MarkWeakTransistors: PROC [cell: CellType, lengthToWidthMin: REAL _ .5] = { SELECT cell.class FROM CoreClasses.transistorCellClass => ERROR; CoreClasses.recordCellClass => { data: CoreClasses.RecordCellType _ NARROW[cell.data]; FOR child: NAT IN [0..data.size) DO IF data.instances[child].type.class # CoreClasses.transistorCellClass THEN MarkWeakTransistors[ data.instances[child].type, lengthToWidthMin ] ELSE { trans: CoreClasses.Transistor _ NARROW[data.instances[child].type.data]; name: ROPE _ NARROW [CoreProperties.GetCellInstanceProp[data.instances[child], $CoreName]]; length: REAL _ trans.length; width: REAL _ trans.width; IF length/width > lengthToWidthMin OR Rope.Equal[name, "driveWeak"] THEN [] _ Rosemary.SetTransistorInstanceSize[data.instances[child], driveWeak]; ENDLOOP }; ENDCASE => MarkWeakTransistors[ CoreOps.Recast[cell], lengthToWidthMin ]}; ENDCASE => ERROR}; Test: PROC[design, name: ROPE] = { lib: Library _ OpenLibrary[design]; cell: Core.CellType _ Get[lib, name]; ref: CD.Object _ PW.Get[lib.design, name]; obj: CD.Object _ PWC.Layout[cell]; iRect: CD.Rect _ CD.InterestRect[obj]; viewer: ViewerClasses.Viewer; CoreOps.PrintCellType[cell]; IF ref=NIL OR obj=NIL THEN Signal[]; CDOps.IncludeObjectI[lib.design, obj, [0, 0]]; CDCleanUp.CleanUp[lib.design]; viewer _ CDViewer.CreateViewer[lib.design]; CDViewer.ShowAndScale[viewer, iRect]; Signal[]}; Test["IFUCore", "Junk"]; Κ »– "cedar" style˜šœ™Jšœ<™šœœ˜Jšœœ˜JšœS˜S—Jšœ œœ ˜ Jšœœ˜1—J•StartOfExpansion[]˜šžœœœ™Jšœ™Jšœ œ™Jšœ œœ™Jšœ œœœ™Jšœ œ ™šœ œœ™Jšœ™ —Jšœœ™Jšœ œ™Jšœœ ™!šœœœ™Jšœ/™/Jšœœ œ œ ™Bš œœœœœœ™;Jš œœ œœœœ™V——Jšœ™Jšœ#™#Jšœœ,™9Jšœœœœ™Jšœ1™1Jš œœœœœ™Jšœœœœ™8Jšœœ ™+Jšœœ™(Jšœ™—J˜šžœœœ˜Jšœ ˜ Jšœœ˜ šœ˜Jšœ˜Jšœ%˜%Jšœœ ˜!Jšœœ)˜5Jšœœœ œ ˜&Jšœ.˜.——J˜šžœœœ˜Jšœœ˜Jšœ œ˜Jšœ˜šœ œ ˜Jšœ˜ —Jšœ*œ ˜9šœ ˜ JšœŸ˜9Jšœœœ(œ˜L—Jšœœ ˜!Jšœœœœ˜