<> <> <> <> <<>> DIRECTORY CCDUtils, CD, CDCreateLabels, CDDirectory, CDInstances, CDOps, CDRects, CDSimpleRules, CDViewer, CMosB, CMosBObjects, Convert, Core, CoreBlock, CoreFrame, CoreGeometry, CoreInstCell, CoreLibrary, CoreName, CoreOps, FS, HashTable, Imager, ImagerFont, IO, PWC, PWObjects, Real, Rope, VFonts; CCDUtilsImpl: CEDAR PROGRAM IMPORTS CD, CDCreateLabels, CDDirectory, CDInstances, CDOps, CDRects, CDSimpleRules, CDViewer, CMosB, CMosBObjects, Convert, CoreBlock, CoreFrame, CoreGeometry, CoreInstCell, CoreLibrary, CoreName, CoreOps, FS, HashTable, ImagerFont, IO, PWC, PWObjects, Real, Rope, VFonts EXPORTS CCDUtils = BEGIN Signal: SIGNAL = CODE; ROPE: TYPE = Core.ROPE; GND: ROPE = CoreName.RopeNm["GND"]; VDD: ROPE = CoreName.RopeNm["VDD"]; plus: ROPE = CoreName.RopeNm["+"]; minus: ROPE = CoreName.RopeNm["-"]; NWMML: TYPE = PWC.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]]}; SizeBlankName: PROC[size: CD.Position] RETURNS[name: ROPE] ~ {RETURN[ IO.PutFR["Blank-%g-%g", IO.int[size.x], IO.int[size.y]]]}; BlankObj: PUBLIC PROC[size: CD.Position] RETURNS[cell: CD.Object] ~ { IncludeInCell: PROC[ob: CD.Object, loc: CD.Position] = {insts _ CONS[CDInstances.NewInst [ob, [off: loc]], insts]}; insts: CD.InstanceList ; minLineW: INT = 2 ; name: ROPE _ SizeBlankName[size]; IF size.x=0 OR size.y=0 THEN RETURN[NIL]; cell _ Fetch[name]; IF cell#NIL THEN RETURN[cell]; IF size.x IN (0..4*minLineW) OR size.y IN (0..4*minLineW) THEN [ ] _ IncludeInCell[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]; [ ] _ IncludeInCell[hor, [0, 0] ]; [ ] _ IncludeInCell[hor, [0, size.y-lwidth] ]; [ ] _ IncludeInCell[ver, [0, 0] ]; [ ] _ IncludeInCell[ver, [size.x-lwidth, 0] ]}; cell _ PWObjects.CreateCell[insts]; Store[name, cell]}; <<>> BlankCell: PUBLIC PROC[size: CD.Position] RETURNS[cell: CellType] ~ { obj: CD.Object _ BlankObj[size]; name: ROPE _ SizeBlankName[size]; cell _ CoreLibrary.ObjCell[obj, name, NIL, 0]; cell _ CoreFrame.NewFrameCell[0, name, [cell: cell]]}; ObjName: PUBLIC PROC[obj: CD.Object] RETURNS[name: ROPE] = { IF obj=NIL THEN RETURN[NIL]; IF obj.specific=NIL THEN RETURN[NIL]; WITH obj.specific SELECT FROM cp: CD.CellSpecific => name _ cp.name; ENDCASE => name _ CDOps.ObjectRope[obj]}; ObjSize: PUBLIC PROC[obj: CD.Object] RETURNS[size: CD.Position] = {RETURN[CD.InterestSize[obj]]}; Layout: PUBLIC PROC[ct: Core.CellType] RETURNS[obj: CD.Object] = { IF ct=NIL THEN RETURN[NIL]; SELECT ct.class FROM CoreInstCell.specificGenericCellClass => RETURN[Layout[ NARROW[ct.data]]]; CoreFrame.frameCellClass => RETURN[Layout[ CoreFrame.FCT[ct].cell ]]; ENDCASE => RETURN[PWC.Layout[ ct]]}; <<>> 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]; <> <> <> <> <> <> <> <> <> <> <> <> <> <<[ ] _ PW.IncludeInCell[picture, refObj, [0, 0]];>> <> <> <> <> <> <> <> <> <> <<[nwmmls.first.name, [400*lambda,10*lambda],CD.commentLayer, design];>> <> <> <> <> <> <> < nwmmls.first.min - org.y,>> < rSize.x - nwmmls.first.max - org.y,>> < ERROR;>> <<[ ] _ PW.IncludeInCell[sidesObj[side], textOb, pos];>> <> <> < {loc _ [-size.x, 0 ]; orient _ original};>> < {loc _ [ rSize.x, 0 ]; orient _ original};>> < {loc _ [ 0, rSize.y ]; orient _ rotate90};>> < {loc _ [ 0, -size.x ]; orient _ rotate90};>> < ERROR;>> <> <<[ ] _ CDCells.RepositionCell[sidesObj[side], NIL];>> <<[ ] _ PW.IncludeInCell[picture, sidesObj[side], loc, orient];>> <> <<[ ] _ CDCells.RepositionCell[picture, NIL]};>> <> <> <> <> <> <> <> <> <> <> SidePinList: PUBLIC PROC [cellType: CellType, side: Side] RETURNS [list: LIST OF NWMML _ NIL] = { refCell: CellType; thisSide: Side _ side; EachWirePin: CoreGeometry.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 _ PWC.AddMergeNWMMLs[[name, wire, min, max, layer], list]}; IF cellType.class=CoreInstCell.specificGenericCellClass THEN {refCell _ NARROW[cellType.data]} ELSE refCell _ cellType; [] _ PWC.InterestRect[refCell]; [] _ CoreGeometry.EnumerateWireSides [PWC.extractMode.decoration, refCell, EachWirePin]; PWC.PosSortNWMMLs[list]}; 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: 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; out.PutRope["\n******"]; 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[]}; <> <> <<_ PW.IncludeInCell[cell, CDSymbolicObjects.CreatePin[size], loc];>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<[] _ PWPins.EnumerateDeepPins[object, KeepPinOnEdge];>> <> <> <> 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] }; <> <> <> <> <> <> <> <> <> <> <> <<[] _ CDDirectory.Include[design, mainObj, name];>> <> <<[] _ CDDirectory.Include[design, decoratedObj, Rope.Cat["Ornate", name]];>> <> <> <<[ ] _ CDViewer.CreateViewer[design]};>> <<>> DrawX: PUBLIC PROC[obj0, obj1, obj2, obj3, obj4: CD.Object _ NIL] = {Draw[TRUE, obj0, obj1, obj2, obj3, obj4]}; DrawY: PUBLIC PROC[obj0, obj1, obj2, obj3, obj4: CD.Object _ NIL] = {Draw[FALSE, obj0, obj1, obj2, obj3, obj4]}; Draw: PROC[inX: BOOL, obj0, obj1, obj2, obj3, obj4: CD.Object _ NIL] = { design: CD.Design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]]; pos: CD.Position _ [0, 0]; Add: PROC[obj: CD.Object, name: ROPE] = { [] _ CDDirectory.Include[design, obj, name]; CDOps.IncludeObjectI[design, obj, pos]; IF inX THEN pos.x _ pos.x + ObjSize[obj].x ELSE pos.y _ pos.y + ObjSize[obj].y}; IF obj0#NIL THEN {Add[obj0, "0"]}; IF obj1#NIL THEN {Add[obj1, "1"]}; IF obj2#NIL THEN {Add[obj2, "2"]}; IF obj3#NIL THEN {Add[obj3, "3"]}; IF obj4#NIL THEN {Add[obj4, "4"]}; [ ] _ CDViewer.CreateViewer[design] }; <<>> <> <<[cell: CellType, name: ROPE _ NIL, design: CD.Design] = {>> <> <> <> <> <> <> <> <> <<[ ] _ CoreGlue.RouteHard[cell];>> <> <<[] _ CDDirectory.Include[design, mainObj, name];>> <> <<[] _ CDDirectory.Include[design, decoratedObj, Rope.Cat["Ornate", name]];>> <> <> <<[ ] _ CDViewer.CreateViewer[design];>> <<[ ] _ CDIO.WriteDesign[design, design.name] };>> <> <> <> <> <<[ ] _ CoreGlue.RouteHard[cell];>> <> log: IO.STREAM _ CoreFrame.GetLog[]; 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; END.