<> <> <> <> <<>> DIRECTORY Basics, BondingPads, CD, CDBasics, CDCells, CDCommandOps, CDDirectory, CDInstances, CDIO, CDLayers, CDOps, CDPanelFonts, CDProperties, CDRects, CDSatellites, CDSequencer, CDTexts, CDViewer, CMosB, Commander, CommandTool, Convert, Core, CoreClasses, CoreGeometry, CoreOps, CoreProperties, FS, IcPack, IO, PGACoordXlate, PWCore, RefTab, Rope, RopeList, Sisyph, TerminalIO, ViewerClasses, ViewerOps; IcPackImpl: CEDAR PROGRAM IMPORTS BondingPads, CD, CDBasics, CDCells, CDCommandOps, CDDirectory, CDInstances, CDIO, CDLayers, CDOps, CDPanelFonts, CDProperties, CDRects, CDSatellites, CDSequencer, CDTexts, CDViewer, CMosB, Commander, CommandTool, Convert, CoreClasses, CoreGeometry, CoreOps, CoreProperties, FS, IO, PGACoordXlate, PWCore, RefTab, Rope, RopeList, Sisyph, TerminalIO, ViewerOps EXPORTS IcPack SHARES Sisyph ~ BEGIN <> Side: TYPE = CoreGeometry.Side; Triplets: TYPE = ARRAY Side OF LIST OF Triplet _ ALL[NIL]; Triplet: TYPE = RECORD[pad, pin, text: CD.Instance _ NIL]; SignalPins: TYPE = PGACoordXlate.SignalPins; tech: CD.Technology _ CMosB.cmosB; buildIcPackDoc: IO.ROPE _ "BuildIcPack deviceCoreFile packageDaleFile -o => keep Outside pad pins (when there are dual pad rows). example: BuildIcPack MapCache PGA300DynaBus "; genEPListsDoc: IO.ROPE _ "GenExpertPinLists designName [cellName]\n"; genCPListsDoc: IO.ROPE _ "GenCoordPinList designName [cellName]\n"; genMTSPinList: IO.ROPE _ "GenMTSPinList designName [cellName]\n"; <> BuildIcPack: PUBLIC PROC[device: Core.CellType, packageNm: IO.ROPE, keepOutside: BOOL] = { cache: Core.CellType _ CacheCell[device]; BuildFromCache[cache, packageNm, keepOutside]}; BuildIcPackComm: Commander.CommandProc = { deviceNm: IO.ROPE; packageNm: IO.ROPE; overFlow: IO.ROPE; argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; keepOutside: BOOL _ FALSE; mainCell: Core.CellType _ NIL; devCacheCell: Core.CellType _ NIL; FOR ii: INT IN [1..argv.argc) DO rope: Rope.ROPE _ CommandTool.ArgN[cmd, ii]; SELECT rope.Fetch[0] FROM '- => SELECT rope.Fetch[1] FROM 'o, 'O => keepOutside _ TRUE; ENDCASE => {cmd.out.PutRope[buildIcPackDoc]; RETURN[$Failure]}; ENDCASE => {overFlow _ deviceNm; deviceNm _ packageNm; packageNm _ rope} ENDLOOP; IF deviceNm=NIL OR overFlow#NIL THEN {cmd.out.PutRope[buildIcPackDoc]; RETURN[$Failure]}; mainCell _ PWCore.Retrieve[deviceNm ! FS.Error => {mainCell _ NIL; CONTINUE}]; IF mainCell=NIL THEN {cmd.out.PutF["Device: %g not found\n", IO.rope[deviceNm]]; RETURN[$Failure]}; devCacheCell _ CacheCell[mainCell]; BuildFromCache[devCacheCell, packageNm, keepOutside]}; <> <> <> <> <> <> <> <<[]_CoreOps.SetCellTypeName[cacheCell, cacheCellNm];>> <<[]_CoreIO.ReportSaveCellType[cacheCell];>> <> <<>> BuildFromCache: PROC [cacheCell: Core.CellType, packageNm: IO.ROPE, keepOutside: BOOL] = { cacheNm: IO.ROPE _ CoreOps.GetCellTypeName[cacheCell]; deviceNm: IO.ROPE _ Root[cacheNm, "IcPack"]; newDesignNm: IO.ROPE _ deviceNm.Cat["IcPack"]; newObjNm: IO.ROPE _ deviceNm.Cat["IcPack"]; design: CD.Design _ CDIO.ReadDesign[from: packageNm, wDir: NIL]; grid: INT; package: CD.Object; device: CD.Object; packCenter: CD.Position; devCenter: CD.Position; offset: CD.Position; IF design=NIL THEN {TerminalIO.PutF["Package: %g not found\n", IO.rope[packageNm]]; RETURN}; package _ CDOps.InstList[design].first.ob; packCenter _ CDBasics.Center[CD.InterestRect[package]]; grid _ design.technology.lambda*2; CDOps.SetMutability[design]; CDOps.RemoveInstance[design, CDOps.InstList[design].first]; device _ BuildPadModel[cacheCell, keepOutside]; devCenter _ CDBasics.Center[CD.InterestRect[device]]; offset _ CDBasics.SubPoints[packCenter, devCenter]; offset.x _ ((offset.x+grid/2)/grid)*grid; offset.y _ ((offset.y+grid/2)/grid)*grid; []_CDCells.IncludeOb[design, package, device, [offset]]; []_CDCells.ToSequenceMode[package]; IF NOT CDDirectory.Rename[design, package, newObjNm].done THEN ERROR; IF NOT CDOps.RenameDesign[design, newDesignNm] THEN ERROR; []_CDOps.IncludeObject[design, package, [[0,0]]]; CDLayers.SetLayerWidth[design, CDLayers.CurrentLayer[design], tech.lambda]; []_CDViewer.CreateViewer[design]; CDSequencer.ExecuteCommand[key: $ResetScaleTop, design: design, queue: dontQueue]; IF NOT CDIO.WriteDesign[design, newDesignNm] THEN ERROR}; Root: PROC[rope, match: IO.ROPE] RETURNS[IO.ROPE] = {RETURN[rope.Substr[0, rope.Index[0, match]]]}; <> CreateIcPack: PROC [comm: CDSequencer.Command] ~ { selectedName: IO.ROPE; shortName: IO.ROPE; iconName: IO.ROPE; cellCode: IO.ROPE; scaleRope: IO.ROPE; keepOutside: BOOL; scale: INT _ 40; TerminalIO.PutRope["Create layout scaled bonding icon with atomic publics\n"]; TerminalIO.PutRope[" Uses current layer, layer width, grid and font to construct icon\n"]; IF comm.key = $CreateIcPackFromSch THEN { selected: CD.Instance _ CDOps.TheInstance[comm.design, "CreateFSMIcon\n"]; IF selected=NIL THEN RETURN; selectedName _ CDDirectory.Name[selected.ob, comm.design]; IF selectedName.IsEmpty[] THEN {TerminalIO.PutF["*** Selected schematic has no name.\n"]; RETURN}; cellCode _ IO.PutFR["Sisyph.ES[\"%g\", cx]", IO.rope[selectedName]]} ELSE {cellCode _ TerminalIO.RequestRope[" Code: "]}; cellCode _ IO.PutFR["IcPack.FlatCell[%g]", IO.rope[cellCode]]; shortName _ TerminalIO.RequestRope[" Short name: "]; IF shortName=NIL THEN shortName _ selectedName; shortName _ shortName.Substr[0, shortName.Index[0, "."]]; IF shortName=NIL THEN {TerminalIO.PutRope[" . . . aborted\n"]; RETURN}; iconName _ shortName.Concat["Bonding.icon"]; scaleRope _ TerminalIO.RequestRope[" Reduction Factor (default 40): "]; IF scaleRope#NIL THEN scale _ Convert.IntFromRope[scaleRope]; keepOutside _ TerminalIO.Confirm[" Include outside row of dual pads rows?"]; MakeAndInsertIcon[comm.design, comm.pos, iconName, cellCode, scale, keepOutside]}; MakeAndInsertIcon: PROC [design: CD.Design, pos: CD.Position, iconName, cellCode: IO.ROPE, scale: INT _ 40, keepOutside: BOOL _ FALSE]~{ icon: CD.Object; cell: Core.CellType; cx: Sisyph.Context _ Sisyph.Create[design]; grid: INT _ CDOps.GetGrid[design]; pinWidth: INT _ CDLayers.LayerWidth[design, CD.commentLayer]; font: CDTexts.CDFont _ CDPanelFonts.CurrentFont[design]; IF CDDirectory.Fetch[design, iconName]#NIL THEN {TerminalIO.PutF["*** The icon %g already exists!\n", IO.rope[iconName]]; RETURN}; cell _ NARROW[Sisyph.EvalToRef[cx, cellCode]]; icon _ BuildPadModel[cell, keepOutside, grid, pinWidth, scale, font]; CDProperties.PutObjectProp[icon, Sisyph.mode.extractProcProp, $SisyphExtractCellIcon]; CDProperties.PutObjectProp[icon, $CodeFor, cellCode]; CDCells.SetSimplificationTreshhold[cell: icon, val: 30, inPixels: TRUE]; IF NOT CDDirectory.Include[design, icon, iconName] THEN ERROR; [] _ CDOps.IncludeObjectI[design, icon, pos]; TerminalIO.PutF[" %g insterted into design.\n", IO.rope[iconName]]}; <> BuildPadModel: PUBLIC PROC[ cell: Core.CellType, keepOutside: BOOL _ FALSE, refGrid: INT _ 0, -- default 2 lambda pinWidth: INT _ 0, -- default 1/2 lambda scale: INT _ 40, refFont: CDTexts.CDFont _ NIL ] RETURNS[obj: CD.Object] ~ { ToGrid: PROC [x: CD.Number] RETURNS [v: CD.Number] ~ {v _ IF x>=0 THEN ((x+grid/2)/grid)*grid ELSE ((x-grid/2)/grid)*grid}; ScaleIR: PROC [r: CD.Rect] RETURNS [v: CD.Rect] ~ {v _ [ x1: r.x1/scale, x2: r.x2/scale, y1: r.y1/scale, y2: r.y2/scale]}; size: CD.Position _ BondingPads.GetSize[cell]; grid: INT _ IF refGrid#0 THEN refGrid ELSE tech.lambda*2; pWidth: INT _ IF pinWidth#0 THEN pinWidth ELSE tech.lambda; cellName: IO.ROPE _ Root[CoreOps.GetCellTypeName[cell], "IcPack"]; basicLayer: CD.Layer _ CD.commentLayer; sigLayer: CD.Layer _ CD.FetchLayer[tech, $blue]; vddLayer: CD.Layer _ CD.FetchLayer[tech, $red]; gndLayer: CD.Layer _ CD.FetchLayer[tech, $green]; sclSize: CD.Position _ [ToGrid[size.x/scale]+pWidth, ToGrid[size.y/scale]+pWidth]; cRect: CD.Rect _ [0, 0, sclSize.x, sclSize.y]; guard: CD.Number _ 2*pWidth; font: CDTexts.CDFont _ IF refFont#NIL THEN refFont ELSE CDTexts.MakeFont["Xerox/TiogaFonts/Helvetica7", 4]; fontCorrection: CD.Number _ -font.height/2 + font.origin.y; triplets: Triplets; iList: CD.InstanceList; nmScale: INT _ 4; nmInst: CD.Instance; eachPublic: PROC[wire: Core.Wire] = { name: IO.ROPE _ AtomicName[CoreOps.GetFullWireName[cell.public, wire]]; text: CD.Object _ CDTexts.Create[name, font, basicLayer]; instances: LIST OF CoreGeometry.Instance _ NARROW[CoreProperties.GetWireProp[wire, $BondingPads]]; padLayer: CD.Layer _ SELECT TRUE FROM name.Find["Gnd", 0, FALSE]#-1 => gndLayer, name.Find["Vdd", 0, FALSE]#-1 => vddLayer, ENDCASE => sigLayer; FOR instances _ instances, instances.rest WHILE instances#NIL DO ir: CD.Rect _ ScaleIR[CoreGeometry.BBox[instances.first]]; side: Side _ NearestSide[ir, cRect]; ave: CD.Position _ [(ir.x1+ir.x2)/2, (ir.y1+ir.y2)/2]; pinPos: CD.Position _ SELECT side FROM left => [0, ToGrid[ave.y-pWidth/2] ], right => [cRect.x2, ToGrid[ave.y-pWidth/2] ], top => [ToGrid[ave.x-pWidth/2], cRect.y2 ], ENDCASE => [ToGrid[ave.x-pWidth/2], 0 ]; pinSize: CD.Position _ SELECT side FROM left => [ave.x - cRect.x1, pWidth ], right => [cRect.x2 - ave.x, pWidth ], top => [cRect.y2 - ave.y, pWidth ], ENDCASE => [ave.y - cRect.y1, pWidth ]; pinObj: CD.Object _ CDRects.CreateRect[pinSize, basicLayer]; textPos: CD.Position _ SELECT side FROM left => [ir.x2+guard, ave.y + fontCorrection], right => [ir.x1-guard, ave.y + fontCorrection], top => [ave.x + fontCorrection, ir.y1-guard], ENDCASE => [ave.x + fontCorrection, ir.y2+guard]; orient: CD.Orientation _ SELECT side FROM left => original, right => mirrorX, top => rotate270, ENDCASE => rotate90X; padObj: CD.Object _ CDRects.CreateRect[CDBasics.SizeOfRect[ir], padLayer]; padInst: CD.Instance _ CDInstances.NewInst[padObj, [CDBasics.BaseOfRect[ir]]]; pinInst: CD.Instance _ CDInstances.NewInst[pinObj, [pinPos, orient]]; textInst: CD.Instance _ CDInstances.NewInst[text, [textPos, orient]]; CDProperties.PutInstanceProp[padInst, Sisyph.mode.extractProcProp, $ExtractNull]; CDSatellites.Associate[master: pinInst, text: textInst]; triplets[side] _ CONS[[pad: padInst, pin: pinInst, text: textInst], triplets[side]]; ENDLOOP}; DO nmFont: CDTexts.CDFont _ CDTexts.MakeFont["Xerox/TiogaFonts/Helvetica7", nmScale]; nmText: CD.Object _ CDTexts.Create[cellName, nmFont, basicLayer]; nmTextSz: CD.Position _ CD.InterestSize[nmText]; nmPos: CD.Position _ [sclSize.x/2-nmTextSz.x/2, sclSize.y/2]; nmInst _ CDInstances.NewInst[nmText, [nmPos]]; IF nmTextSz.x*3 > (cRect.x2 - cRect.x1) THEN EXIT; nmScale _ nmScale*2 ENDLOOP; obj _ CDCells.CreateEmptyCell[]; BondingPads.MarkBondingPads[cell]; []_CoreOps.VisitRootAtomics[cell.public, eachPublic]; iList _ FilterOutsidePins[triplets, keepOutside, grid]; obj _ CDCells.CreateCell[il: CONS[nmInst, iList], ir: cRect]; CDCells.ToSequenceMode[obj]}; AddIfUnique: PROC[rope: IO.ROPE, ropes: LIST OF IO.ROPE] RETURNS[LIST OF IO.ROPE] = {IF ~RopeList.Memb[ropes, rope] THEN ropes _ CONS[rope, ropes]; RETURN[ropes]}; SideNm: ARRAY Side OF IO.ROPE _ [bottom: "Bottom", top: "Top", left: "Left", right: "Right"]; Compare: PROC[side: Side, ir1, ir2: CD.Rect] RETURNS[ioSide: {in, out, equal}] = { AboutTheSame: PROC[a1, a2, b1, b2: INT] RETURNS[same: BOOL] _ { size: INT _ MAX[b2-b1, a2-a1]; overLap: INT _ MIN[a2, b2] - MAX[a1, b1]; RETURN[((overLap*100)/size) > 90]}; -- more than 90% overlap SELECT side FROM left => {IF ir1.x2ir2.x2 THEN RETURN[in]}; right => {IF ir1.x2ir2.x2 THEN RETURN[out]}; top => {IF ir1.y2ir2.y2 THEN RETURN[out]}; bottom => {IF ir1.y2ir2.y2 THEN RETURN[in]}; ENDCASE; SELECT side FROM left, right => {IF AboutTheSame[ir1.x1, ir1.x2, ir2.x1, ir2.x2] THEN RETURN[equal]}; top, bottom=> {IF AboutTheSame[ir1.y1, ir1.y2, ir2.y1, ir2.y2] THEN RETURN[equal]}; ENDCASE; ERROR}; -- pads overlap in range (0..90%) FilterOutsidePins: PROC[triplets: Triplets, keepOutside: BOOL, grid: INT] RETURNS[iList: CD.InstanceList]= { BBox: PROC[inst: CD.Instance] RETURNS[CD.Rect] = {RETURN[CDBasics.MapRect[inst.ob.bbox, inst.trans]]}; TextNm: PROC[text: CD.Instance] RETURNS[IO.ROPE] = {RETURN[NARROW[text.ob.specific, CDTexts.TextSpecific]^.text]}; FOR side: Side IN Side DO HalfPin: PROC[oldPin: CD.Object] RETURNS[newPin: CD.Object] = { oldSize: CD.Position _ CD.InterestSize[oldPin]; newPin _ CDRects.CreateRect[[oldSize.x, oldSize.y/2], oldPin.layer]}; inNms: LIST OF IO.ROPE _ NIL; outNms: LIST OF IO.ROPE _ NIL; ins: LIST OF Triplet _ NIL; outs: LIST OF Triplet _ NIL; FOR trips: LIST OF Triplet _ triplets[side], trips.rest WHILE trips#NIL DO AddTo: PROC[row: {in, out}] = {IF row=in THEN {ins _ CONS[trip, ins]; inNms _ AddIfUnique[tripNm, inNms]} ELSE {outs _ CONS[trip, outs]; outNms _ AddIfUnique[tripNm, outNms]}}; trip: Triplet _ trips.first; tripNm: IO.ROPE _ TextNm[trip.text]; tripIR: CD.Rect _ BBox[trip.pad]; IF ins=NIL THEN {AddTo[in]; LOOP}; SELECT Compare[side, tripIR, BBox[ins.first.pad]] FROM equal => {AddTo[in]; LOOP}; in => { IF outs#NIL THEN ERROR; outs _ ins; ins _ NIL; outNms _ inNms; inNms _ NIL; AddTo[in]; LOOP}; out => { IF outs#NIL AND Compare[side, tripIR, BBox[outs.first.pad]]#equal THEN ERROR; AddTo[out]; LOOP}; ENDCASE; ENDLOOP; <> <> <> <> FOR ins _ ins, ins.rest WHILE ins#NIL DO IF keepOutside AND outNms#NIL THEN ins.first.pin.ob _ HalfPin[ins.first.pin.ob]; iList _ CONS[ins.first.pin, CONS[ins.first.text, CONS[ins.first.pad, iList]]] ENDLOOP; IF keepOutside THEN { IF outNms#NIL THEN TerminalIO.PutF["%g outside pins shifted to half grid points.\n", IO.rope[SideNm[side]]]; FOR outNms _ outNms, outNms.rest WHILE outNms#NIL DO TerminalIO.PutF["Deleted %g outside %g satellites\n", IO.rope[SideNm[side]], IO.rope[outNms.first]] ENDLOOP; FOR outs _ outs, outs.rest WHILE outs#NIL DO ToHalfGrid: PROC[av, old: INT] RETURNS[new: INT] = { new _ old + (IF (av-old+newPinW/2)>0 THEN grid/2 ELSE -grid/2)}; ave: CD.Position _ CDBasics.Center[BBox[outs.first.pad]]; newPinW: INT _ CD.InterestSize[outs.first.pin.ob].y/2; oldPos: CD.Position _ outs.first.pin.trans.off; nm: IO.ROPE _ TextNm[outs.first.text]; outs.first.pin.ob _ HalfPin[outs.first.pin.ob]; CDProperties.PutInstanceProp[outs.first.pin, $SignalName, nm]; SELECT side FROM left => outs.first.pin.trans.off.y _ ToHalfGrid[ave.y, oldPos.y]; right => outs.first.pin.trans.off.y _ ToHalfGrid[ave.y, oldPos.y]; top => outs.first.pin.trans.off.x _ ToHalfGrid[ave.x, oldPos.x]; ENDCASE => outs.first.pin.trans.off.x _ ToHalfGrid[ave.x, oldPos.x]; iList _ CONS[outs.first.pin, CONS[outs.first.pad, iList]]; ENDLOOP} ELSE { FOR outNms _ outNms, outNms.rest WHILE outNms#NIL DO TerminalIO.PutF["Deleted %g outside pin(s): %g\n", IO.rope[SideNm[side]], IO.rope[outNms.first]] ENDLOOP; FOR outs _ outs, outs.rest WHILE outs#NIL DO iList _ CONS[outs.first.pad, iList] ENDLOOP} ENDLOOP}; <> AtomicName: PUBLIC PROC[strucName: IO.ROPE] RETURNS[atomicName: IO.ROPE] = { replaceBrackets:Rope.TranslatorType~{RETURN[SELECT old FROM '[=>'(,']=>'),ENDCASE=>old]}; atomicName _ Rope.Translate[base: strucName, translator: replaceBrackets]}; StructuredName: PUBLIC PROC[atomicName: IO.ROPE] RETURNS[strucName: IO.ROPE] = { replaceParens: Rope.TranslatorType~{RETURN[SELECT old FROM '(=>'[,')=>'],ENDCASE=>old]}; strucName _ Rope.Translate[base: atomicName, translator: replaceParens]}; AtomicTopWires: PROC[ref: Core.CellType] RETURNS[publics, internalOnlys: Core.Wires, actual: Core.Wire] = { eachPair: CoreOps.EachWirePairProc = { actualName: IO.ROPE _ IF publicWire.size=0 THEN AtomicName[CoreOps.GetFullWireName[ref.public, publicWire]] ELSE NIL; [] _ CoreOps.SetShortWireName[actualWire, actualName]; IF CoreOps.Member[internalOnlys, actualWire] THEN RETURN; IF CoreOps.Member[publics, actualWire] THEN RETURN; IF actualName=NIL THEN internalOnlys _ CONS[actualWire, internalOnlys] ELSE { newList: LIST OF CoreGeometry.Instance _ NIL; instances: LIST OF CoreGeometry.Instance _ NARROW[CoreProperties.GetWireProp[publicWire, $BondingPads]]; FOR instances _ instances, instances.rest WHILE instances#NIL DO newList _ CONS[instances.first, newList] ENDLOOP; CoreProperties.PutWireProp[actualWire, $BondingPads, newList]; publics _ CONS[actualWire, publics]; FOR pubs: Core.Wires _ publics, pubs.rest WHILE pubs#NIL AND pubs.rest#NIL DO TwoWires: TYPE = RECORD[w1, w2: Core.Wire]; n1: IO.ROPE _ CoreOps.GetShortWireName[pubs.first]; n2: IO.ROPE _ CoreOps.GetShortWireName[pubs.rest.first]; SELECT Rope.Compare[n1, n2, FALSE] FROM less => EXIT; greater => [pubs.rest.first, pubs.first] _ TwoWires[pubs.first, pubs.rest.first]; ENDCASE => ERROR ENDLOOP}}; actual _ CoreOps.CopyWire[ref.public]; [] _ CoreOps.VisitBinding[actual, ref.public, eachPair]}; FlatCell: PUBLIC PROC[ref: Core.CellType] RETURNS[cell: Core.CellType] = { publics: Core.Wires; internals: Core.Wires; inst: CoreClasses.CellInstance _ NEW[ CoreClasses.CellInstanceRec _ [type: ref]]; name: IO.ROPE _ CoreOps.GetCellTypeName[ref]; size: CD.Position _ BondingPads.GetSize[ref]; [publics, internals, inst.actual] _ AtomicTopWires[ref]; FOR pubs: Core.Wires _ publics, pubs.rest WHILE pubs#NIL DO internals _ CONS[pubs.first, internals] ENDLOOP; cell _ CoreClasses.CreateRecordCell[ public: CoreOps.CreateWire[publics], internal: CoreOps.CreateWire[internals], instances: LIST[inst], name: name.Cat["IcPackCell"] ]; PWCore.SetLayout[cell, $AbutX]; CoreProperties.PutCellTypeProp[cell, $BondingFrameSize, NEW[CD.Position _ size]]}; CacheCell: PUBLIC PROC[ref: Core.CellType] RETURNS[cell: Core.CellType] = { public: Core.Wire _ CoreOps.CopyWire[ref.public]; internals: Core.Wires _ NIL; eachPair: CoreOps.EachWirePairProc = { actList: LIST OF CoreGeometry.Instance _ NARROW[CoreProperties.GetWireProp[actualWire, $BondingPads]]; subPubList: LIST OF CoreGeometry.Instance _ NARROW[CoreProperties.GetWireProp[publicWire, $BondingPads]]; IF actList=NIL THEN { FOR subPubList _ subPubList, subPubList.rest WHILE subPubList#NIL DO actList _ CONS[subPubList.first, actList] ENDLOOP; CoreProperties.PutWireProp[actualWire, $BondingPads, actList]}}; name: IO.ROPE _ CoreOps.GetCellTypeName[ref]; size: REF CD.Position _ NARROW[CoreProperties.GetCellTypeProp[ref, $BondingFrameSize]]; [] _ CoreOps.VisitBinding[public, ref.public, eachPair]; FOR i: INT IN [0..public.size) DO internals _ CONS[public[i], internals] ENDLOOP; cell _ CoreClasses.CreateRecordCell[ public: public, internal: CoreOps.CreateWire[internals], instances: NIL, name: name ]; CoreProperties.PutCellTypeProp[cell, $BondingFrameSize, size]}; NearestSide: PROC[sml, lrg: CD.Rect] RETURNS[side: Side _ left] ~ { dist: INT _ ABS[lrg.x1 - sml.x1]; test: INT _ ABS[lrg.x2 - sml.x2]; IF test < dist THEN {dist _ test; side _ right}; test _ ABS[lrg.y1 - sml.y1]; IF test < dist THEN {dist _ test; side _ bottom}; test _ ABS[lrg.y2 - sml.y2]; IF test < dist THEN {dist _ test; side _ top}}; MakeTestObject: PROC[instances: LIST OF CoreGeometry.Instance] RETURNS[obj: CD.Object] = { iList: CD.InstanceList _ NIL; FOR instances _ instances, instances.rest WHILE instances#NIL DO inst: CD.Instance _ CDInstances.NewInst[instances.first.obj, instances.first.trans]; iList _ CONS[inst, iList] ENDLOOP; obj _ CDCells.CreateCell[il: iList]; CDCells.ToSequenceMode[obj]}; <> GenPinListComm: Commander.CommandProc = { argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; designNm: IO.ROPE; cellNm: IO.ROPE; cellType: Core.CellType; IF argv.argc<2 THEN {cmd.out.PutRope[genCPListsDoc]; RETURN[$Failure]}; designNm _ CommandTool.ArgN[cmd, 1]; cellNm _ CommandTool.ArgN[cmd, 2]; cellType _ GetDesignCellType[designNm, cellNm]; IF cellType=NIL THEN { cmd.out.PutF["%g.%g not found.\n", IO.rope[designNm], IO.rope[cellNm]]; RETURN[$Failure]}; cellNm _ CoreOps.GetCellTypeName[cellType]; SELECT TRUE FROM cmd.command.Find["GenExpertPinLists"]#-1 => { GenExpertPinLists[cellType]; cmd.out.PutF["%g.pinsLeft ..Right ..Top ..Bottom written.\n", IO.rope[cellNm]]}; cmd.command.Find["GenCoordPinList"]#-1 => { GenCoordPinList[cellType]; cmd.out.PutF["%g.pinCoords written.\n", IO.rope[cellNm]]}; cmd.command.Find["GenMTSPinList"]#-1 => { GenMTSPinList[cellType]; cmd.out.PutF["%g.mtsPackage written.\n", IO.rope[cellNm]]}; ENDCASE => ERROR}; GenExpertPinLists: PUBLIC PROC[cell: Core.CellType] = { WriteSideFile: PROC[sideRope: IO.ROPE, list: LIST OF IO.ROPE] = { out: IO.STREAM _ FS.StreamOpen[name.Cat[".pins", sideRope], $create]; index: INT _ 0; FOR list _ list, list.rest WHILE list#NIL DO IF (index MOD 10) = 0 THEN out.PutRope["\n"]; index _ index+1; IF list.first.Length[]=0 THEN out.PutRope["NC\n"] ELSE out.PutF["%g\n", IO.rope[list.first]] ENDLOOP; out.Close[]}; name: IO.ROPE _ CoreOps.GetCellTypeName[cell]; names: ARRAY Side OF LIST OF IO.ROPE _ GetSidePinSignals[cell]; WriteSideFile[SideNm[left], RopeList.Reverse[names[left]]]; WriteSideFile[SideNm[right], RopeList.Reverse[names[right]]]; WriteSideFile[SideNm[top], names[top]]; WriteSideFile[SideNm[bottom], names[bottom]]}; GenCoordPinList: PUBLIC PROC[cell: Core.CellType] = { name: IO.ROPE _ CoreOps.GetCellTypeName[cell]; out: IO.STREAM _ FS.StreamOpen[name.Cat[".pinCoords"], $create]; maxSize: INT _ 2; packageKey: ATOM _ GetPackageKey[cell]; sigs: LIST OF SignalPins _ GetSignalPins[cell]; FOR ss: LIST OF SignalPins _ sigs, ss.rest WHILE ss#NIL DO maxSize _ MAX[maxSize, ss.first.nm.Length[]] ENDLOOP; FOR ss: LIST OF PGACoordXlate.SignalPins _ sigs, ss.rest WHILE ss#NIL DO IF ss.first.nm.Length[]=0 THEN LOOP; out.PutRope[ss.first.nm]; THROUGH[ss.first.nm.Length[]..maxSize) DO out.PutChar[' ] ENDLOOP; FOR pins: LIST OF NAT _ ss.first.pins, pins.rest WHILE pins#NIL DO coord: PGACoordXlate.PGACoord _ PGACoordXlate.PinToPGACoord[packageKey, pins.first]; out.PutF[" %03g:%g", IO.int [pins.first], IO.rope [PGACoordXlate.PGACoordToRope[coord]] ] ENDLOOP; out.PutRope["\n"] ENDLOOP; out.Close[]}; GenMTSPinList: PUBLIC PROC[cell: Core.CellType] = { name: IO.ROPE _ CoreOps.GetCellTypeName[cell]; out: IO.STREAM _ FS.StreamOpen[name.Cat[".mtsPackage"], $create]; maxSize: INT _ 0; packageKey: ATOM _ GetPackageKey[cell]; sigs: LIST OF SignalPins _ GetSignalPins[cell]; out.PutF["Name %g;\n\n", IO.rope[name]]; out.PutF["Fixture PGA400;\n\n"]; FOR ss: LIST OF SignalPins _ sigs, ss.rest WHILE ss#NIL DO maxSize _ MAX[maxSize, ss.first.nm.Length[]] ENDLOOP; FOR ss: LIST OF PGACoordXlate.SignalPins _ sigs, ss.rest WHILE ss#NIL DO setup: IO.ROPE _ SELECT TRUE FROM ss.first.nm.Find["Vdd"]#-1 => " /5V", ss.first.nm.Find["Gnd"]#-1 => " /0V", ENDCASE => " "; pins: LIST OF NAT _ ss.first.pins; IF ss.first.nm.Length[]=0 THEN LOOP; out.PutF[" Wire %g", IO.rope[StructuredName[ss.first.nm]]]; THROUGH[ss.first.nm.Length[]..maxSize) DO out.PutChar[' ] ENDLOOP; out.PutF["%g", IO.rope[setup]]; SortPinsByCoords[pins, packageKey]; FOR pins _ pins, pins.rest WHILE pins#NIL DO coord: PGACoordXlate.PGACoord _ PGACoordXlate.PinToPGACoord[packageKey, pins.first]; out.PutF[" %g", IO.rope[PGACoordXlate.PGACoordToRope[coord]] ] ENDLOOP; out.PutRope[";\n"] ENDLOOP; out.Close[]}; GetSignalPins: PUBLIC PROC[cell: Core.CellType] RETURNS[sigs: LIST OF SignalPins] = { <> InsertList: PROC[list: LIST OF IO.ROPE] = { FOR list _ list, list.rest WHILE list#NIL DO index _ index+1; sigs _ AddSignalPin[list.first, index, sigs] ENDLOOP}; packageKey: ATOM _ GetPackageKey[cell]; index: INT _ 0; names: ARRAY Side OF LIST OF IO.ROPE _ GetSidePinSignals[cell]; sigs _ PGACoordXlate.PGAFixedPins[packageKey]; InsertList[ names[top]]; InsertList[RopeList.Reverse[ names[right]]]; InsertList[RopeList.Reverse[ names[bottom]]]; InsertList[ names[left]]}; AddSignalPin: PROC[nm: IO.ROPE, pin: NAT, sigs: LIST OF SignalPins] RETURNS[new: LIST OF SignalPins] = { TwoSignalPins: TYPE = RECORD[n1, n2: SignalPins]; new _ CONS[[nm, LIST[pin]], sigs]; FOR temp: LIST OF SignalPins _ new, temp.rest WHILE temp#NIL AND temp.rest#NIL DO SELECT Rope.Compare[temp.first.nm, temp.rest.first.nm, FALSE] FROM equal => { temp.first.pins _ AddPin[temp.first.pins.first, temp.rest.first.pins]; temp.rest _ temp.rest.rest; EXIT}; greater => [temp.first, temp.rest.first] _ TwoSignalPins[temp.rest.first, temp.first]; ENDCASE => EXIT ENDLOOP}; AddPin: PROC[pin: NAT, pins: LIST OF NAT] RETURNS[new: LIST OF NAT] = { TwoNats: TYPE = RECORD[n1, n2: NAT]; new _ CONS[pin, pins]; FOR temp: LIST OF NAT _ new, temp.rest WHILE temp#NIL AND temp.rest#NIL DO SELECT temp.first FROM = temp.rest.first => {temp.rest _ temp.rest.rest; EXIT}; > temp.rest.first => [temp.first, temp.rest.first] _ TwoNats[temp.rest.first, temp.first]; ENDCASE => EXIT ENDLOOP}; SortPinsByCoords: PROC[pins: LIST OF NAT, key: ATOM] = { CoordRope: PROC[pin: NAT] RETURNS[rope: IO.ROPE] = {RETURN [PGACoordXlate.PGACoordToRope[PGACoordXlate.PinToPGACoord[key, pin]]]}; DO TwoNats: TYPE = RECORD[n1, n2: NAT]; done: BOOL _ TRUE; FOR temp: LIST OF NAT _ pins, temp.rest WHILE temp#NIL AND temp.rest#NIL DO IF Rope.Compare[CoordRope[temp.first], CoordRope[temp.rest.first]] = greater THEN { [temp.first, temp.rest.first] _ TwoNats[temp.rest.first, temp.first]; done _ FALSE} ENDLOOP; IF done THEN EXIT ENDLOOP}; GetPackageKey: PROC[cell: Core.CellType] RETURNS[key: ATOM] = { key _ NARROW[CoreProperties.GetCellTypeProp[cell, $Package]]}; GetSidePinSignals: PUBLIC PROC[cell: Core.CellType] RETURNS[names: ARRAY Side OF LIST OF IO.ROPE _ ALL[NIL]] = { MakeList: PROC[wire: Core.Wire] RETURNS[list: LIST OF IO.ROPE] = { FOR i: INT DECREASING IN [0..wire.size) DO subPub: Core.Wire _ NARROW[RefTab.Fetch[table, wire[i]].val]; name: IO.ROPE _ IF subPub=NIL THEN "" ELSE CoreOps.GetShortWireName[subPub]; list _ CONS[name, list] ENDLOOP}; data: CoreClasses.RecordCellType _ NARROW[cell.data]; wires: ARRAY Side OF Core.Wire _ ALL[NIL]; device: CoreClasses.CellInstance; table: RefTab.Ref; FOR side: Side IN Side DO wires[side] _ CoreOps.FindWire[cell.public, SideNm[side]] ENDLOOP; FOR i: INT IN [0..data.size) DO IF ~CoreOps.GetCellTypeName[data[i].type].Substr[0, 3].Equal["Pkg"] THEN device _ data[i] ENDLOOP; table _ CoreOps.CreateBindingTable[device.actual, device.type.public]; FOR side: Side IN Side DO names[side] _ MakeList[wires[side]] ENDLOOP}; GetDesignCellType: PUBLIC PROC[designNm, cellNm: IO.ROPE _ NIL] RETURNS[cellType: Core.CellType _ NIL] = { design: CD.Design _ GetDesign[designNm]; IF design#NIL THEN { cx: Sisyph.Context _ Sisyph.Create[design]; obj: CD.Object _ CDOps.InstList[design].first.ob; objNm: IO.ROPE _ CDDirectory.Name[obj, design]; IF cellNm=NIL THEN cellNm _ objNm; cellType _ Sisyph.ES[cellNm, cx]}}; GetDesign: PUBLIC PROC [name: IO.ROPE] RETURNS [design: CD.Design] = { viewer: ViewerClasses.Viewer; design _ CDViewer.FindDesign[name]; IF design#NIL THEN RETURN[design]; IF name.Length[]=0 THEN RETURN[NIL]; design _ CDIO.ReadDesign[name]; CDOps.SetMutability[design]; viewer_CDViewer.CreateViewer[design, FALSE]; ViewerOps.CloseViewer[viewer]}; <> CDCommandOps.RegisterWithMenu[ $SpecialMenu, "Create Bonding Icon From Sch", "Create layout scaled bonding icon with atomic publics", $CreateIcPackFromSch, CreateIcPack]; CDCommandOps.RegisterWithMenu[ $SpecialMenu, "Create Bonding Icon From Code", "Create layout scaled bonding icon with atomic publics", $CreateIcPackFromCode, CreateIcPack]; Commander.Register[key:"BuildIcPack", proc: BuildIcPackComm, doc: buildIcPackDoc]; Commander.Register[key:"GenExpertPinLists", proc: GenPinListComm, doc: genEPListsDoc]; Commander.Register[key:"GenCoordPinList", proc: GenPinListComm, doc: genCPListsDoc]; Commander.Register[key:"GenMTSPinList", proc: GenPinListComm, doc: genMTSPinList]; END.