DIRECTORY Basics, CCDUtils, CD, CDCells, CDCleanUp, CDCreateLabels, CDDirectory, CDOps, CDOrient, CDProperties, CDRects, CDSimpleOps, CDSimpleRules, CDSymbolicObjects, CDViewer, CMosB, CMosBObjects, Convert, Core, CoreBlock, CoreClasses, CoreFrame, CoreInstCell, CoreName, CoreOps, FS, HashTable, Imager, ImagerFont, IO, PW, PWCore, PWPins, Real, Rope, Sinix, SinixCMos, VFonts; CCDUtilsImpl: CEDAR PROGRAM IMPORTS Basics, CD, CDCells, CDCleanUp, CDCreateLabels, CDDirectory, CDOps, CDProperties, CDRects, CDSimpleOps, CDSimpleRules, CDSymbolicObjects, CDViewer, CMosB, CMosBObjects, Convert, CoreBlock, CoreClasses, CoreFrame, CoreInstCell, CoreName, CoreOps, FS, HashTable, ImagerFont, IO, PW, PWCore, PWPins, Real, Rope, Sinix, SinixCMos, VFonts EXPORTS CCDUtils = BEGIN Signal: SIGNAL = CODE; ROPE: TYPE = CCDUtils.ROPE; GND: ROPE = CoreName.RopeNm["GND"]; VDD: ROPE = CoreName.RopeNm["VDD"]; plus: ROPE = CoreName.RopeNm["+"]; minus: ROPE = CoreName.RopeNm["-"]; NWMML: TYPE = CCDUtils.NWMML; CellType: TYPE = Core.CellType; Side: TYPE = CoreFrame.Side; cache: HashTable.Table _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; Store: PROC[name: ROPE, obj: CD.Object] = {[]_HashTable.Store[cache, name, obj]}; Fetch: PROC[name: ROPE] RETURNS[obj: CD.Object] = {RETURN[NARROW[HashTable.Fetch[cache, name].value, CD.Object]]}; BlankObj: PUBLIC PROC[size: CD.Position] RETURNS[cell: CD.Object] ~ { name: ROPE _ IO.PutFR["Dummy-%g-%g", IO.int[size.x], IO.int[size.y]]; minLineW: INT = 2 ; IF size.x=0 OR size.y=0 THEN RETURN[NIL]; cell _ Fetch[name]; IF cell#NIL THEN RETURN[cell]; cell _ CDCells.CreateEmptyCell[]; IF size.x IN (0..4*minLineW) OR size.y IN (0..4*minLineW) THEN [ ] _ PW.IncludeInCell[cell, CDRects.CreateRect[size, CD.commentLayer], [0, 0] ] ELSE { lwidth: INT _ MAX[minLineW, MIN[size.x/100, size.y/100]]; hor: CD.Object _ CDRects.CreateRect[[size.x, lwidth], CD.commentLayer]; ver: CD.Object _ CDRects.CreateRect[[lwidth, size.y], CD.commentLayer]; [ ] _ PW.IncludeInCell[cell, hor, [0, 0] ]; [ ] _ PW.IncludeInCell[cell, hor, [0, size.y-lwidth] ]; [ ] _ PW.IncludeInCell[cell, ver, [0, 0] ]; [ ] _ PW.IncludeInCell[cell, ver, [size.x-lwidth, 0] ]}; PW.RepositionCell[cell]; Store[name, cell]}; BlankCell: PUBLIC PROC[size: CD.Position] RETURNS[cell: CellType] ~ { obj: CD.Object _ BlankObj[size]; CDProperties.PutProp [obj, SinixCMos.extractBMode.extractProcProp, $CCDUtilsBlankCell]; cell _ PWCore.FromLayoutWithoutPublic[obj]; CoreBlock.PutCellSide[cell, all]; cell _ CoreFrame.NewFrameCell[0, ObjName[obj], [cell: cell]]}; NewBlankCellType: PUBLIC PROC RETURNS[cell: CellType] ~ { rec: CoreClasses.RecordCellType _ NEW [CoreClasses.RecordCellTypeRec[0]]; rec.internal _ CoreOps.CreateWires[0]; cell _ NEW[Core.CellTypeRec _ [ class: CoreClasses.recordCellClass, public: CoreOps.CreateWires[0], data: rec, properties: NIL]]}; BlankExtractProc: Sinix.ExtractProc ~ { name: ROPE _ ObjName[obj]; cellType: Core.CellType _ NewBlankCellType[]; result _ CoreOps.SetCellTypeName[cellType, name]}; ObjName: PUBLIC PROC[obj: CD.Object] RETURNS[name: ROPE] = { IF obj=NIL THEN RETURN[NIL]; IF obj.specificRef=NIL THEN RETURN[NIL]; IF NOT ISTYPE[obj.specificRef, CD.CellPtr] THEN RETURN[NIL]; RETURN[NARROW[obj.specificRef, CD.CellPtr].name]}; ObjSize: PUBLIC PROC[obj: CD.Object] RETURNS[size: CD.Position] = {RETURN[CD.InterestSize[obj]]}; font1: Imager.Font _ VFonts.EstablishFont [family:"Helvetica", size: 7, bold: TRUE, italic: FALSE, defaultOnFailure: FALSE]; font2: Imager.Font _ VFonts.EstablishFont [family:"Helvetica", size: 14, bold: TRUE, italic: FALSE, defaultOnFailure: FALSE]; OrnateFrame: PUBLIC PROC [cell: CellType, design: CD.Design_NIL] RETURNS[picture: CD.Object] = { recCell: CellType _ cell; rSize: CD.Position; loc: CD.Position; sidesObj: ARRAY Side OF CD.Object; refObj: CD.Object; IF cell.class = CoreFrame.frameCellClass THEN recCell _ CoreFrame.FCT[cell].cell ELSE recCell _ cell; refObj _ CoreFrame.Layout[recCell]; picture _ CDCells.CreateEmptyCell[]; rSize _ CD.InterestSize[refObj]; [ ] _ PW.IncludeInCell[picture, refObj, [0, 0]]; FOR side: Side IN Side DO nwmmls: LIST OF NWMML _ SidePinList[recCell, side]; bias: INT = lambda; orient: CD.Orientation; size: CD.Position _ [0, 0]; IF nwmmls=NIL THEN LOOP; sidesObj[side] _ CDCells.CreateEmptyCell[]; FOR nwmmls _ nwmmls, nwmmls.rest WHILE nwmmls#NIL DO textOb: CD.Object _ ScaledText [nwmmls.first.name, [400*lambda,10*lambda],CD.commentLayer, design]; pos: CD.Position ; size.x _ MAX[size.x, ((textOb.size.x+2*bias+lambda-1)/lambda)*lambda]; pos.x _ bias; pos.y _ SELECT side FROM left, right => nwmmls.first.min, bottom, top => rSize.x - nwmmls.first.max, ENDCASE => ERROR; [ ] _ PW.IncludeInCell[sidesObj[side], textOb, pos]; ENDLOOP; SELECT side FROM left, right => {size.y _ rSize.y}; top, bottom => {size.y _ rSize.x}; ENDCASE => ERROR; SELECT side FROM left => {loc _ [-size.x, 0 ]; orient _ CDOrient.original}; right => {loc _ [ rSize.x, 0 ]; orient _ CDOrient.original}; top => {loc _ [ 0, rSize.y ]; orient _ CDOrient.rotate90}; bottom => {loc _ [ 0, -size.x ]; orient _ CDOrient.rotate90}; ENDCASE => ERROR; CDCells.SetInterestRect[sidesObj[side], [0, 0, size.x, size.y]]; [ ] _ CDCells.RepositionCell[sidesObj[side], NIL]; [ ] _ PW.IncludeInCell[picture, sidesObj[side], loc, orient]; ENDLOOP; [ ] _ CDCells.RepositionCell[picture, NIL]}; AddRet: PUBLIC PROC [cell: CD.Object, size: CD.Position, loc: CD.Position, level: CD.Layer] = { IF size.x<0 OR size.y<0 THEN { PW.WriteF["Strange rectangle size [%g, %g]", IO.int[size.x], IO.int[size.y] ]; Signal[]}; IF size.x=0 OR size.y=0 THEN RETURN; [] _ PW.IncludeInCell[cell, CDRects.CreateRect[size, level], loc]}; SidePinList: PUBLIC PROC [cellType: CellType, side: PWPins.Side] RETURNS [list: LIST OF NWMML _ NIL] = { refCell: CellType; thisSide: Side _ side; EachWirePin: PWCore.EachWirePinProc = { SubstituteWireName: CoreOps.EachWirePairProc ~ { IF actualWire#wire THEN RETURN; wire_publicWire; name_CoreName.WireNm[wire].n; RETURN[FALSE, TRUE]}; name: ROPE _ CoreName.WireNm[wire].n; IF side#thisSide THEN RETURN; IF NOT CoreBlock.OnSide[CoreFrame.SideSides[side], CoreBlock.GetWireSide[wire]] THEN RETURN; IF layer#cmosMet AND layer#cmosMet2 THEN SELECT name FROM GND, VDD, plus, minus => RETURN ENDCASE; IF cellType.class=CoreInstCell.specificGenericCellClass THEN [ ] _ CoreOps.VisitBinding[refCell.public, cellType.public, SubstituteWireName]; IF name=NIL THEN RETURN; list _ AddMergeNWMMLs[[name, wire, min, max, layer], list]}; IF cellType.class=CoreInstCell.specificGenericCellClass THEN {refCell _ NARROW[cellType.data]} ELSE refCell _ cellType; [] _ PWCore.EnumerateWirePins[refCell, EachWirePin]; PosSortNWMMLs[list]}; AddMergeNWMMLs: PUBLIC PROC[item: NWMML, lst: LIST OF NWMML] RETURNS[LIST OF NWMML] = { IV: PROC[w: Core.Wire] RETURNS[int: INT] = {int _ LOOPHOLE[w]}; IF lst=NIL THEN RETURN[CONS[item, NIL]]; FOR l: LIST OF NWMML _ lst, l.rest DO nameCompare: Basics.Comparison _ IF l.first.name=NIL AND item.name = NIL THEN Basics.CompareINT[IV[l.first.wire], IV[item.wire]] ELSE Rope.Compare[l.first.name, item.name]; IF nameCompare = equal AND l.first.layer = item.layer AND l.first.max >= item.min AND l.first.min <= item.max THEN { l.first.max _ MAX[ l.first.max, item.max]; l.first.min _ MIN[ l.first.min, item.min]; RETURN[lst]}; IF nameCompare = greater OR nameCompare = equal AND ( l.first.layer > item.layer OR l.first.layer = item.layer AND l.first.min > item.min) THEN { temp: NWMML _ l.first; l.rest _ CONS[item, l.rest]; l.first _ l.rest.first; l.rest.first _ temp; RETURN[lst]}; IF l.rest = NIL THEN {l.rest _ CONS[item, l.rest]; RETURN[lst]}; ENDLOOP}; PosSortNWMMLs: PUBLIC PROC[lst: LIST OF NWMML] = { DO ok: BOOL _ TRUE; FOR l: LIST OF NWMML _ lst, l.rest WHILE l#NIL AND l.rest#NIL DO IF l.first.min > l.rest.first.min OR l.first.min = l.rest.first.min AND l.first.max > l.rest.first.max THEN {temp: NWMML _ l.first; l.first _ l.rest.first; l.rest.first _ temp; ok _ FALSE} ENDLOOP; IF ok THEN EXIT; ENDLOOP}; ListNWMMLs: PUBLIC PROC[lst: LIST OF NWMML, log: IO.STREAM] = { list: LIST OF NWMML; list _ lst; lst _ NIL; FOR list _ list, list.rest WHILE list#NIL DO lst _ CONS[list.first, lst] ENDLOOP; list _ lst; FOR list _ list, list.rest WHILE list#NIL DO ListNWMML[list.first, log] ENDLOOP; log.PutChar[IO.CR] }; ListNWMML: PUBLIC PROC[nwmml: NWMML, log: IO.STREAM] = { layerCard: CARDINAL _ LOOPHOLE[nwmml.layer]; log.PutF["\n%g\tpos: %5g\tsize: %5g\tlayer: %g", IO.rope[nwmml.name], IO.int[nwmml.min], IO.int[nwmml.max-nwmml.min], IO.rope[ SELECT nwmml.layer FROM cmosMet2 => "metal2", cmosMet => "metal", cmosPoly => "poly", ENDCASE => Convert.RopeFromCard[layerCard] ] ]}; ListUniqueSignals: PUBLIC PROC[first: PWPins.Side, cell0, cell1: CellType, log: REF _ NIL] = { Incrment: PROC[table: HashTable.Table, id: REF] = { val: REF INT _ NARROW[HashTable.Fetch[table, id].value]; IF val=NIL THEN {val _ NEW[INT _ 0]; [] _ HashTable.Store[table, id, val]}; val^ _ val^ + 1}; nwmmls0: LIST OF NWMML _ SidePinList[cell0, CoreFrame.OppSide[first]]; nwmmls1: LIST OF NWMML _ SidePinList[cell1, first]; side0Nm: ROPE _ CoreFrame.SideRope[CoreFrame.OppSide[first]]; side1Nm: ROPE _ CoreFrame.SideRope[first]; out: IO.STREAM; count: INT _ 0; mark: REF _ NEW[INT _ 0]; table0: HashTable.Table _ HashTable.Create[ ]; table1: HashTable.Table _ HashTable.Create[ ]; IF log=NIL THEN out _ FS.StreamOpen["UniqueSignals.txt", $create] ELSE WITH log SELECT FROM rope: ROPE => {out _ FS.StreamOpen[rope, $create]}; text: REF TEXT => {out _ FS.StreamOpen[Rope.FromRefText[text], $create]}; stm: IO.STREAM => {out _ stm}; ENDCASE => {Signal[]}; FOR temp: LIST OF NWMML _ nwmmls0, temp.rest WHILE temp#NIL DO Incrment[table0, temp.first.name] ENDLOOP; FOR temp: LIST OF NWMML _ nwmmls1, temp.rest WHILE temp#NIL DO Incrment[table1, temp.first.name] ENDLOOP; out.PutF["\nUnique signal log %g\n%10g side of %g\n%10g side of %g\n", IO.time[], IO.rope[side0Nm], IO.rope[CoreName.CellNm[cell0].n], IO.rope[side1Nm], IO.rope[CoreName.CellNm[cell1].n] ]; FOR temp: LIST OF NWMML _ nwmmls0, temp.rest WHILE temp#NIL DO val: REF INT _ NARROW[HashTable.Fetch[table0, temp.first.name].value]; IF val^<2 AND NOT HashTable.Fetch[table1, temp.first.name].found THEN out.PutF["\n%g\tpos: %5g", IO.rope[temp.first.name], IO.int[temp.first.min]] ENDLOOP; FOR temp: LIST OF NWMML _ nwmmls1, temp.rest WHILE temp#NIL DO val: REF INT _ NARROW[HashTable.Fetch[table1, temp.first.name].value]; IF val^<2 AND NOT HashTable.Fetch[table0, temp.first.name].found THEN out.PutF["\n%g\tpos: %5g", IO.rope[temp.first.name], IO.int[temp.first.min]] ENDLOOP; out.PutRope["\n"]; out.Close[]}; PutPin: PUBLIC PROC[cell: CD.Object, size, loc: CD.Position, level: CD.Layer, name: ROPE] = { pinApl: CD.Instance _ PW.IncludeInCell[cell, CDSymbolicObjects.CreatePin[size], loc]; CDSymbolicObjects.SetName[pinApl, name]; CDSymbolicObjects.SetLayer[pinApl, level]}; RenamePins: PUBLIC PROC[ object: CD.Object, pinNameProc: CCDUtils.PinNameProc] RETURNS[newObject: CD.Object] = { KeepPinOnEdge: CDSymbolicObjects.InstEnumerator ~ { newRope: ROPE; newInst: CD.Instance; side: PWPins.Side; side _ PWPins.GetSide[object, inst]; IF side=none THEN RETURN; newRope _ pinNameProc[inst, side]; IF Rope.IsEmpty[newRope] THEN RETURN; newInst _ NEW[CD.InstanceRep _ [ ob: CDSymbolicObjects.CreatePin[inst.ob.size], location: inst.location, orientation: inst.orientation ]]; CDProperties.CopyProps[inst.properties, newInst]; CDSymbolicObjects.SetName[newInst, newRope]; newCellPtr.contents _ CONS[newInst, newCellPtr.contents] }; newCellPtr: CD.CellPtr; inst: CD.Instance _ NEW[CD.InstanceRep _ [ob: object]]; CDProperties.PutInstanceProp[inst, $StopEnumerateDeepPins, $StopEnumerateDeepPins]; newObject _ CDCells.CreateEmptyCell[]; newCellPtr _ NARROW[newObject.specificRef]; [] _ PWPins.EnumerateDeepPins[object, KeepPinOnEdge]; newCellPtr.contents _ CONS[inst, newCellPtr.contents]; CDCells.SetInterestRect[newObject, CD.InterestRect[object]]; RETURN[newObject] }; cmos: PUBLIC CD.Technology = CMosB.cmosB; cmosNDif: PUBLIC CD.Layer _ CMosB.ndif; cmosPDif: PUBLIC CD.Layer _ CMosB.pdif; cmosWPDif: PUBLIC CD.Layer _ CMosB.wpdif; cmosWNDif: PUBLIC CD.Layer _ CMosB.wndif; cmosPoly: PUBLIC CD.Layer _ CMosB.pol; cmosMet: PUBLIC CD.Layer _ CMosB.met; cmosMet2: PUBLIC CD.Layer _ CMosB.met2; cmosPWCont: PUBLIC CD.Layer _ CMosB.pwellCont; cmosNWCont: PUBLIC CD.Layer _ CMosB.nwellCont; cmosNWell: PUBLIC CD.Layer _ CMosB.nwell; lambda: PUBLIC INT _ CMosB.lambda; pwrW: PUBLIC INT _ 5*lambda; metW: PUBLIC INT _ 3*lambda; met2W: PUBLIC INT _ 4*lambda; polW: PUBLIC INT _ 2*lambda; difW: PUBLIC INT _ 2*lambda; topTail: PUBLIC INT _ 2*lambda; leftTail: PUBLIC INT _ 6*lambda; -- to center of 0th channel rightTail: PUBLIC INT _ 2*lambda; -- metPitch-leftTail botTail: PUBLIC INT _ 1*lambda; cnctSize: PUBLIC INT _ 4*lambda; metPitch: PUBLIC INT _ 8*lambda; met2Pitch: PUBLIC INT _ 8*lambda; polMuxPitch: PUBLIC INT _ 8*lambda; polPitch: PUBLIC INT _ 6*lambda; -- without adjacent contacts Contact: PUBLIC PROC[layer: CD.Layer] RETURNS[cntc: CD.Object] = { RETURN[SELECT layer FROM cmosMet2, cmosPoly, cmosNDif, cmosPDif, cmosWPDif, cmosWNDif => CDSimpleRules.Contact[cmosMet, layer], cmosPWCont, cmosNWCont => CMosBObjects.CreateDifCon[layer], ENDCASE => ERROR]}; TransistorObject: PUBLIC PROC[size: CD.Position, difLayer: CD.Layer] RETURNS[trans: CD.Object]= {trans _ CMosBObjects.CreateTransistor[size: size, difLayer: difLayer]}; textCache: CD.Design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]]; ScaledText: PUBLIC PROC[text: ROPE, box: CD.Position, layer: CD.Layer, design: CD.Design_NIL] RETURNS[cell: CD.Object _ NIL] = { MakeName: PROC[fontIndex: INT] RETURNS[name: ROPE] = { name _ IO.PutFR["Label%g-%g[%g]", IO.int[fontIndex], IO.int[scaleFactor], IO.rope[text]]}; Scale: PROC[font: Imager.Font] RETURNS[scale: INT] = { extents: ImagerFont.Extents _ ImagerFont.RopeBoundingBox[font, text]; strSize: CD.Position; IF box.x<4 OR box.y<4 THEN RETURN[0]; strSize.x _ Real.RoundI[extents.rightExtent+extents.leftExtent]; strSize.y _ Real.RoundI[extents.ascent+extents.descent]; scale _ MIN[box.x/strSize.x, box.y/strSize.y]}; scaleFactor: INT; IF design=NIL THEN design _ textCache; IF text.Length[]=0 THEN text _ ""; scaleFactor _ Scale[font2]; IF scaleFactor>0 THEN { cell _ CDDirectory.Fetch[design, MakeName[2]].object; IF cell=NIL THEN { cell _ CDCreateLabels.CreateTextCell[design, text, font2, scaleFactor, layer]; [] _ CDDirectory.Include[design, cell, MakeName[2]]; RETURN[cell]} }; scaleFactor _ Scale[font1]; IF scaleFactor>0 THEN { cell _ CDDirectory.Fetch[design, MakeName[1]].object; IF cell=NIL THEN { cell _ CDCreateLabels.CreateTextCell[design, text, font1, scaleFactor, layer]; [] _ CDDirectory.Include[design, cell, MakeName[2]]; RETURN[cell]} }; RETURN[NIL] }; ShowModule: PUBLIC PROC[name: ROPE, design: CD.Design _ NIL] = { frameCT: CellType; new: BOOL _ design=NIL; mainObj, decoratedObj: CD.Object; IF new THEN { design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]]; CDSimpleOps.RenameDesign[design, name]}; frameCT _ CoreFrame.ReadFrameCache[name]; IF frameCT=NIL THEN Signal[]; IF frameCT=NIL THEN RETURN; mainObj _ CoreFrame.Layout[frameCT]; [] _ CDDirectory.Include[design, mainObj, name]; decoratedObj _ OrnateFrame[frameCT, design]; [] _ CDDirectory.Include[design, decoratedObj, Rope.Cat["Ornate", name]]; IF new THEN CDOps.IncludeObjectI[design, decoratedObj, [0, 0]]; CDCleanUp.CleanUp[ design, NIL]; [ ] _ CDViewer.CreateViewer[design]}; IF metW # CDSimpleRules.MinWidth[cmosMet] THEN ERROR; IF met2W # CDSimpleRules.MinWidth[cmosMet2] THEN ERROR; IF polW # CDSimpleRules.MinWidth[cmosPoly] THEN ERROR; IF difW # CDSimpleRules.MinWidth[cmosNDif] THEN ERROR; Sinix.RegisterExtractProc[$CCDUtilsBlankCell, BlankExtractProc]; END. „CCDUtilsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last Edited by Curry, June 11, 1986 11:28:30 pm PDT Side: TYPE = PWPins.Side; BlankObj: PUBLIC PROC[size: CD.Position] RETURNS[cell: CD.Object] ~ { cellPtr: CD.CellPtr; found: BOOL _ FALSE; name: ROPE _ IO.PutFR["Dummy-%g-%g", IO.int[size.x], IO.int[size.y]]; IF size.x=0 OR size.y=0 THEN RETURN[NIL]; cell _ Fetch[name]; IF cell#NIL THEN RETURN[cell]; cell _ CDCells.CreateEmptyCell[]; cellPtr _ NARROW[cell.specificRef]; cellPtr.contents _ CONS[NEW[CD.InstanceRep _ [ob: CDRects.CreateRect[size, CD.backgroundLayer]] ], cellPtr.contents]; Store[name, cell]}; textOb _ CDTexts.CreateText[pins[i].name, font, layer]; IF (size.x MOD 2)=1 OR (size.y MOD 2)=1 OR size.x<0 OR size.y<0 Only metal2 left/right or metal1 top/bottom power is included Add sorted by name, wire, layer, min, max - - - merge overlaps InsertModule: PUBLIC PROC [cell: CellType, name: ROPE _ NIL, design: CD.Design] = { new: BOOL _ design=NIL; mainObj, decoratedObj: CD.Object; name _ CoreName.CellNm[cell, name].n; IF new THEN { design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]]; CDSimpleOps.RenameDesign[design, name]}; CoreFrame.Expand[hard, cell]; CoreFrame.NameFrame[cell, name]; [ ] _ CoreGlue.RouteHard[cell]; mainObj _ CoreFrame.Layout[cell]; [] _ CDDirectory.Include[design, mainObj, name]; decoratedObj _ OrnateFrame[cell, design]; [] _ CDDirectory.Include[design, decoratedObj, Rope.Cat["Ornate", name]]; IF new THEN CDOps.IncludeObjectI[design, decoratedObj, [0, 0]]; CDCleanUp.CleanUp[ design, NIL]; [ ] _ CDViewer.CreateViewer[design]; [ ] _ CDIO.WriteDesign[design, design.name] }; InsertModule: PUBLIC PROC[cell:CellType, name: ROPE _ NIL, design: CD.Design _NIL]={ name _ CoreName.CellNm[cell, name].n; CoreFrame.Expand[hard, cell]; CoreFrame.NameFrame[cell, name]; [ ] _ CoreGlue.RouteHard[cell]; CoreFrame.WriteFrameCheckPoint[cell]}; Ê)˜šœ™Jšœ<™˜>—J˜šžœ œœ˜9Jšœ"œ$˜IJšœ'˜'šœ œ˜"Jšœ$˜$Jšœ˜Jšœ ˜ Jšœ œ˜——J˜šžœ˜'Jšœœ˜Jšœ-˜-Jšœ2˜2—J˜š žœœœœ œœ˜˜>Jšœœ˜—Jšœ@˜@Jšœ2˜2Jšœœ5˜=Jšœ˜—Jšœ,˜,—J˜J˜šžœœœœœœœ ˜_Jš œ œœ œœ œ ™?šœ œ ˜šœ˜Jšœ+œœ˜NJšœ ˜ ——Jšœ œ œœ˜$Jšœœ<˜C—J˜J™=šž œœœ(˜@Jš œœœœœ˜'Jšœ˜Jšœ˜šž œ˜'šžœ˜0Jšœœœ˜Jšœ/œœœ˜D—Jšœœ˜&Jšœœœ˜šœœI˜OJšœœ˜ —šœœ˜(Jš œœœœœ˜9—šœ5œ˜=JšœP˜P—Jšœœœœ˜Jšœ<˜<—šœ5˜7Jšœ œœ˜?—Jšœ4˜4Jšž œ˜—J˜Jšœ>™>šžœœœœœœœ˜œ˜PJšœ˜———Jšœœœ˜Jšœ˜ ——J˜šž œœœœœœœœ˜?Jšœœœœ˜Jšœœ˜šœœœ˜,Jšœœœ˜$—Jšœ ˜ Jš œœœœœ˜PJšœ œœ˜—J˜š ž œœœ œœœ˜8Jšœ œœ˜,šœ0˜0Jšœ˜Jšœ˜Jšœ˜šœœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ)˜0———J™šžœ œ2œœ˜^šžœœœ˜3Jšœœœœ#˜8Jš œœœœœ-˜KJšœ˜—Jšœ œœœ0˜FJšœ œœœ˜3Jšœ œ0˜>Jšœ œ˜+Jšœœœ˜Jšœ œ˜Jšœœœœ˜Jšœ/˜/Jšœ/˜/šœ˜ Jšœœ)˜6šœœœ˜Jšœœ œ˜5Jšœœœ œ.˜IJšœœœ˜Jšœ˜——š œœœœœœ˜>Jšœ"œ˜*—š œœœœœœ˜>Jšœ"œ˜*—šœG˜GJšœ˜ Jšœœ ˜4Jšœœ!˜6—š œœœœœœ˜>Jšœœœœ1˜Fšœœœ0˜EJšœœœœ˜U——š œœœœœœ˜>Jšœœœœ1˜Fšœœœ0˜EJšœœœ˜U——Jšœœ˜ J˜—šžœœœœœœœ˜^šœœ ˜Jšœœ=˜A—Jšœ(˜(Jšœ+˜+—J˜šž œœœ˜Jšœ œ˜šœ"˜"Jšœ œ ˜!—•StartOfExpansion= -- [app: CD.ApplicationPtr] RETURNS [quit: BOOL _ FALSE] -- šž œ&˜3Jšœ œ˜Jšœ œ ˜Jšœ˜Jšœ$˜$Jšœ œœ˜Jšœ"˜"Jšœœœ˜%šœ œœ˜ Jšœ1˜1Jšœ˜Jšœ!˜!—Jšœ1˜1Jšœ,˜,Jšœœ!˜;—Jšœ œ ˜Jšœœ œœ˜9JšœS˜SJšœ&˜&Jšœ œ˜+Jšœ5˜5Jšœœ˜6Jšœ#œ˜Jšœ œœ Ÿ˜8Jšœ œœ ˜!J˜Jšœ œœ ˜$Jšœ œœ ˜#Jšœ œœ ˜$Jšœœœ ˜%Jšœ œœŸ˜AJ˜š žœœœœœœ ˜Bšœœ˜šœ?˜?Jšœ&˜&—šœ˜Jšœ!˜!—Jšœœ˜J˜——š žœœœœœ˜Dšœœ ˜JšœH˜H——J˜Jšœ œ9˜FJ˜š ž œœœœœœ˜]Jšœœ˜"š žœœ œœœ˜6Jš œœœœœ˜Z—šžœœœ œ˜7JšœE˜EJšœ œ ˜Jšœ œ œœ˜%Jšœ@˜@Jšœ8˜8Jšœ œ$˜0—Jšœ œ˜Jšœœœ˜&Jšœ+˜+Jšœ˜šœœ˜Jšœ5˜5šœœ˜JšœN˜NJšœžœ˜4Jšœ ˜——Jšœ˜šœœ˜Jšœ5˜5šœœ˜JšœN˜NJšœžœ˜4Jšœ ˜——Jšœœ˜J˜—š ž œœœœ œ œ˜@Jšœ˜Jšœœ œ˜Jšœœ˜!šœœ˜ Jšœœ˜8Jšœ(˜(—Jšœ)˜)Jšœ œœ ˜Jšœ œœœ˜Jšœ$˜$Jšœ0˜0Jšœ,˜,JšœI˜IJšœœ4˜?Jšœœ˜ Jšœ%˜%—J™šž œœ™Jšœœœ œ ™9Jšœœ œ™Jšœœ™!Jšœ%™%šœœ™ Jšœœ™8Jšœ(™(—Jšœ™Jšœ ™ Jšœ™Jšœ!™!Jšœ0™0Jšœ)™)JšœI™IJšœœ4™?Jšœœ™ Jšœ$™$Jšœœ$™.—J˜šž œœœœœ œ œ™TJšœ%™%Jšœ™Jšœ ™ Jšœ™Jšœ&™&—J˜Jšœ(œœ˜5Jšœ*œœ˜7Jšœ)œœ˜6Jšœ)œœ˜6J˜Jšœ@˜@J˜Jšœ˜—J˜J˜J˜J˜—…—>¾\k