DIRECTORY CD, CDAbuts, CDCells, CDDirectory, CDExtras, CDIO, CDOps, CDPinObjects, CDProperties, CDRects USING [CreateRect], CDSequencer, CDSimpleOps, CDViewer, Convert, Commander, DragOpsCross, IFUPW, IO, PW, PWBasics, PWPins, Rope, ViewerClasses, VMStatistics, WatchStats; IFUPWUtils: CEDAR PROGRAM IMPORTS CD, CDAbuts, CDCells, CDDirectory, CDExtras, CDIO, CDOps, CDPinObjects, CDProperties, CDRects, CDSequencer, CDSimpleOps, CDViewer, Convert, IO, IFUPW, PW, PWBasics, PWPins, Rope, VMStatistics, WatchStats EXPORTS IFUPW = BEGIN OPEN IFUPW; Error: PUBLIC ERROR[msg: PW.ROPE] = CODE; GND: PUBLIC Rope.ROPE _ "GND"; VDD: PUBLIC Rope.ROPE _ "VDD"; rngByte: PUBLIC INT _ 4; rngBit: PUBLIC INT _ 8; ChangePinNames: PUBLIC PROC[obj: CD.ObPtr, oldName, newName: PW.ROPE] = { pins: CD.ApplicationList _ CDPinObjects.FindPins[obj, oldName]; FOR pins _ pins, pins.rest WHILE pins#NIL DO CDPinObjects.SetName[pins.first, newName] ENDLOOP }; ConnSpec: TYPE = REF ConnSeqRec; ConnSeqRec: TYPE = RECORD[SEQUENCE size: CARDINAL OF CnntRec]; CnntRec: TYPE = RECORD[name: Rope.ROPE, y: INT]; BuildConnSpec: PROC[in, out: List, topY, botY, refY: INT, refCell: CD.ObPtr] RETURNS[connSpec: ConnSpec] = { done: BOOL _ FALSE; size, index: CARDINAL _ ListLength[in] + ListLength[out] + 2; connSpec _ NEW[ConnSeqRec[size]]; connSpec[size-1].name _ NIL; connSpec[size-1].y _ topY; connSpec[0].name _ NIL; connSpec[0].y _ botY; index _ 1; FOR ii: INT IN [0..ListLength[in]) DO connSpec[index].name _ in.first; in _ in.rest; connSpec[index].y _ refY + CDPinObjects.FindPins[refCell, IO.PutFR["In%g", IO.int[ii]]].first.location.y; index _ index + 1 ENDLOOP; FOR ii: INT IN [0..ListLength[out]) DO connSpec[index].name _ out.first; out _ out.rest; connSpec[index].y _ refY + CDPinObjects.FindPins[refCell, IO.PutFR["Out%g", IO.int[ii]]].first.location.y; index _ index + 1 ENDLOOP; WHILE NOT done DO done _ TRUE; FOR ii: INT IN [0..size-1) DO ty: INT _ connSpec[ii].y; tname: Rope.ROPE _ connSpec[ii].name; IF connSpec[ii].y <= connSpec[ii+1].y THEN LOOP; done _ FALSE; connSpec[ii].y _ connSpec[ii+1].y; connSpec[ii].name _ connSpec[ii+1].name; connSpec[ii+1].y _ ty; connSpec[ii+1].name _ tname ENDLOOP ENDLOOP }; IOConnect: PUBLIC PROC[ design: CD.Design, cell: CD.ObPtr, top: List, in: List, out: List, bot: List, refcell: CD.ObPtr, refX: INT, refY: INT, topY: INT, botY: INT ] = { PurgeNILLsFromList: PUBLIC PROC [list: List] RETURNS[clean: List] = { IF list = NIL THEN RETURN[NIL]; clean _ PurgeNILLsFromList[list.rest]; IF list.first#NIL THEN clean _ CONS[list.first, clean]}; Same: PROC[idx1, idx2: CARDINAL] RETURNS[BOOL] = {RETURN[Rope.Equal[connSpec[idx1].name, connSpec[idx2].name]]}; connSpec: ConnSpec; tIdx, bIdx: CARDINAL _ 0; in _ PurgeNILLsFromList[in]; out _ PurgeNILLsFromList[out]; connSpec _ BuildConnSpec[in, out, topY, botY, refY, refcell]; tIdx _ connSpec.size-1; bIdx _ 0; FOR i: INT IN [0..nofVWires) DO Add: PROC[idx1, idx2: CARDINAL] RETURNS[BOOL] = { IF ~Same[idx1, idx2] THEN RETURN[FALSE]; loc.y _ connSpec[idx1].y; size.y _ connSpec[idx2].y - connSpec[idx1].y; IF size.y < 0 THEN ERROR; AddRet[cell:cell, size: size, loc: loc, level: cmosMet]; RETURN[TRUE]}; size: Size _ [metW, 0]; loc: Location _ [refX+i*metPitch+leftTail, 0]; connSpec[tIdx].name _ ListIndexItem[top, i]; connSpec[bIdx].name _ ListIndexItem[bot, i]; IF connSpec[tIdx].name#NIL THEN FOR ii: INT IN [bIdx..tIdx) DO IF Add[ ii, tIdx] THEN EXIT; REPEAT FINISHED => ERROR Error [IO.PutFR["Orphan top signal: %g", IO.rope[connSpec[tIdx].name]]] ENDLOOP; IF connSpec[bIdx].name#NIL THEN FOR ii: INT DECREASING IN (bIdx..tIdx) DO IF Add[ bIdx, ii] THEN EXIT; REPEAT FINISHED => IF ~Same[bIdx, tIdx] THEN ERROR Error[IO.PutFR["Orphan bottom signal: %g", IO.rope[connSpec[bIdx].name]]] ENDLOOP; ENDLOOP; IF ListLength[out]#0 THEN FOR i: INT IN [0..nofVWires) DO AddCnt: PROC[idx: CARDINAL] = { ctct, wire: CD.ObPtr; IF ~Same[idx, tIdx] AND ~Same[idx, bIdx] THEN RETURN; wLoc.y _ connSpec[idx].y; ctct _ MetalCntctObPtr[design, cmosPoly]; wire _ CDRects.CreateRect[[wLen, 4], cmosPoly]; [] _ PWBasics.IncludeApplication[cell, ctct, [wLoc.x-2, wLoc.y-2]]; [] _ PWBasics.IncludeApplication[cell, wire, wLoc] }; wLen: INT _ (nofVWires-1-i)*metPitch + 8; wLoc: Location _ [refX+i * metPitch +leftTail, 0]; connSpec[tIdx].name _ ListIndexItem[top, i]; connSpec[bIdx].name _ ListIndexItem[bot, i]; FOR ii: INT IN (bIdx..tIdx) DO AddCnt[ii] ENDLOOP; ENDLOOP }; AddMetalPins: PUBLIC PROC [cell: CD.ObPtr, top, bot: List, refX, topY, botY: INT, realNames: BOOL] = { length: INT _ MAX[ListLength[top], ListLength[bot]]; FOR i: INT IN [0..length) DO tName: PW.ROPE _ ListIndexItem[top, i]; bName: PW.ROPE _ ListIndexItem[bot, i]; size: Size _ [6, 6]; loc: Location _ [refX+i*metPitch+leftTail, topY-size.y]; IF tName #NIL THEN PutPin [cell, size, loc, cmosMet, (IF realNames THEN tName ELSE NIL)]; IF bName #NIL THEN PutPin [cell, size, [loc.x, botY], cmosMet, (IF realNames THEN bName ELSE NIL)]; ENDLOOP }; ProcessorRegToList: PUBLIC PROC [reg: DragOpsCross.ProcessorRegister] RETURNS[list: List] = { val: CARDINAL _ LOOPHOLE[reg]; list _ NIL; FOR bit: INT IN [0..rngBit) DO list _ CONS[(IF (val MOD 2 = 1) THEN VDD ELSE GND), list]; val _ val/2; ENDLOOP }; AddRet: PUBLIC PROC [cell: CD.ObPtr, size: Size, loc: Location, level: CD.Layer] = { IF size.x<0 OR size.y<0 THEN ERROR Error[IO.PutFR ["Strange rectangle size [%g, %g]", IO.int[size.x], IO.int[size.y]]]; IF size.x=0 OR size.y=0 THEN RETURN; [] _ PWBasics.IncludeApplication[cell, CDRects.CreateRect[size, level], loc]}; PutPin: PUBLIC PROC[cell:CD.ObPtr, size:Size, loc:Location, level:CD.Layer, name:PW.ROPE] = { pinApl: CD.ApplicationPtr _ PWBasics.IncludeApplication[cell, CDPinObjects.CreatePinOb[size], loc]; CDPinObjects.SetName[pinApl, name]; CDPinObjects.SetLayer[pinApl, level]}; SizeOf: PUBLIC PROC[design: CD.Design, cell: PW.ObjName] RETURNS[size: Size] = { RETURN[PWBasics.GetISize[PWBasics.ObjFromName[design, cell] ] ]}; Merge: PUBLIC PROC[design: CD.Design, side: Side, cell1, cell2: PW.ObjName] RETURNS[cell: PW.ObjName] = { obj: CD.ObPtr _ CDCells.CreateEmptyCell[]; obj1: CD.ObPtr _ PWBasics.ObjFromName[design, cell1]; obj2: CD.ObPtr _ PWBasics.ObjFromName[design, cell2]; size1: Size _ PWBasics.GetISize[obj1]; size2: Size _ PWBasics.GetISize[obj2]; [ ] _ PWBasics.IncludeApplication[obj, obj1, [0, 0]]; SELECT side FROM TopSide => [ ] _ PWBasics.IncludeApplication[obj, obj2, [0, size1.y-size2.y]]; BotSide => [ ] _ PWBasics.IncludeApplication[obj, obj2, [0, 0]]; RtSide => [ ] _ PWBasics.IncludeApplication[obj, obj2, [0, size1.x-size2.x]]; LtSide => [ ] _ PWBasics.IncludeApplication[obj, obj2, [0, 0]]; ENDCASE; PWBasics.RepositionCell[design, obj]; cell _ PWBasics.NameFromObj[obj]}; ProcRegToList: PUBLIC PROC [reg: ProcessorReg] RETURNS[new: List] = {val: CARDINAL _ LOOPHOLE[reg]; RETURN[CardToList8[val]]}; CardToList8: PUBLIC PROC [val: CARDINAL] RETURNS[new: List] = { new _ NIL; THROUGH [0..8) DO new _ CONS[(IF (val MOD 2)=1 THEN VDD ELSE GND), new]; val _ val/2; ENDLOOP}; FixGVInList: PUBLIC PROC [list: List] RETURNS[new: List] = {RETURN[AddGVToList[DelGVFromList[list]]]}; DelGVFromList: PUBLIC PROC [list: List] RETURNS[new: List] = { nonNilItemAdded: BOOL _ FALSE; IF list=NIL THEN RETURN[NIL]; FOR ii: INT DECREASING IN [0..ListLength[list]) DO item: PW.ROPE _ ListIndexItem[list, ii]; IF Rope.Equal[item, GND] OR Rope.Equal[item, VDD] THEN item _ NIL; IF item=NIL AND NOT nonNilItemAdded THEN LOOP; nonNilItemAdded _ TRUE; new _ CONS[item, new] ENDLOOP}; AddGVToList: PUBLIC PROC [list: List] RETURNS[new: List] = { FOR ii: INT DECREASING IN [0..MAX[nofVWires, ListLength[list]]) DO item: PW.ROPE _ ListIndexItem[list, ii]; IF ii=nofVWires-1 THEN item _ VDD; IF ii=nofVWires-2 THEN item _ GND; new _ CONS[item, new] ENDLOOP}; AddGVToLIST: PUBLIC PROC [list: LIST OF REF, indexGV: BOOL] RETURNS[new: LIST OF REF] = { FOR ii: INT DECREASING IN [0..MAX[nofVWires, LISTLength[list]]) DO item: REF _ LISTIndexItem[list, ii]; IF ii=nofVWires-1 THEN item _ IF indexGV THEN VDD.Cat["."] ELSE VDD; IF ii=nofVWires-2 THEN item _ IF indexGV THEN GND.Cat["."] ELSE GND; new _ CONS[item, new] ENDLOOP}; ListAllNil: PUBLIC PROC [list: List] RETURNS[allNIL: BOOL] = {FOR list _ list, list.rest WHILE list#NIL DO IF list.first#NIL THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]}; LISTAllNil: PUBLIC PROC [list: LIST OF REF] RETURNS[allNIL: BOOL] = {FOR list _ list, list.rest WHILE list#NIL DO IF list.first#NIL THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]}; List4: PUBLIC PROC [r0, r1, r2, r3: PW.ROPE] RETURNS[list: List] = { list _ CONS[r0, CONS[r1, CONS[r2, CONS[r3, NIL]]]]}; List8: PUBLIC PROC [r0, r1, r2, r3, r4, r5, r6, r7: PW.ROPE] RETURNS[list: List] = { list _ CONS[r0,CONS[r1,CONS[r2,CONS[r3,CONS[r4,CONS[r5,CONS[r6,CONS[r7, NIL]]]]]]]]}; LISTn: PUBLIC PROC [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15: REF _ NIL ] RETURNS[list: LIST OF REF] = { refs: ARRAY [0..16) OF REF _ [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15]; index: INT; FOR index DECREASING IN [0..16) WHILE refs[index]=NIL DO ENDLOOP; FOR index_index, index-1 WHILE index>=0 DO IF refs[index]#NIL AND ISTYPE[refs[index], REF TEXT] THEN list _ CONS[Rope.FromRefText[NARROW[refs[index]]], list ] ELSE list _ CONS[refs[index], list] ENDLOOP}; Listn: PUBLIC PROC [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15: PW.ROPE _ NIL ] RETURNS[list: List] = { refs: ARRAY [0..16) OF PW.ROPE _ [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15]; index: INT; FOR index DECREASING IN [0..16) WHILE refs[index]=NIL DO ENDLOOP; FOR index_index, index-1 WHILE index>=0 DO list _ CONS[refs[index], list] ENDLOOP}; ListLength: PUBLIC PROC [list: List] RETURNS[size: INT] = {FOR size _ 0, size+1 WHILE list#NIL DO list_list.rest ENDLOOP}; LISTLength: PUBLIC PROC [list: LIST OF REF] RETURNS[size: INT] = {FOR size _ 0, size+1 WHILE list#NIL DO list_list.rest ENDLOOP}; ListIndexItem: PUBLIC PROC [list: List, index: INT] RETURNS[item: PW.ROPE] = { FOR index _ index, index-1 WHILE index#0 AND list#NIL DO list_list.rest ENDLOOP; RETURN[IF list=NIL THEN NIL ELSE list.first]}; LISTIndexItem: PUBLIC PROC[list: LIST OF REF, index: INT] RETURNS[item: REF] = { FOR index _ index, index-1 WHILE index#0 AND list#NIL DO list_list.rest ENDLOOP; RETURN[IF list=NIL THEN NIL ELSE list.first]}; ListItemIndexMin: PUBLIC PROC [list: List, item: PW.ROPE] RETURNS[index: INT] = { IF item=NIL THEN RETURN[-1]; FOR index _ 0, index+1 WHILE list#NIL DO IF Rope.Equal[list.first, item] THEN RETURN[index]; list_list.rest ENDLOOP; RETURN[-1]}; ListNonNILIndexMin: PUBLIC PROC [list: List] RETURNS[index: INT] = { FOR index _ 0, index+1 WHILE list#NIL DO IF list.first#NIL THEN RETURN[index]; list_list.rest ENDLOOP; RETURN[-1]}; ListItemIndexMax: PUBLIC PROC [list: List, item: PW.ROPE] RETURNS[index: INT] = { count: INT _ -1; index _ -1; IF item=NIL THEN RETURN[-1]; FOR list _ list, list.rest WHILE list#NIL DO count _ count+1; IF Rope.Equal[list.first, item] THEN index _ count ENDLOOP}; ListNonNILIndexMax: PUBLIC PROC [list: List] RETURNS[index: INT] = { count: INT _ -1; index _ -1; FOR list _ list, list.rest WHILE list#NIL DO count _ count+1; IF list.first#NIL THEN index _ count ENDLOOP}; ReverseList: PUBLIC PROC [list: List] RETURNS [new: List] = {FOR list _ list, list.rest WHILE list#NIL DO new _ CONS[list.first, new] ENDLOOP}; ReverseLIST: PUBLIC PROC [list: LIST OF REF] RETURNS [new: LIST OF REF] = {FOR list _ list, list.rest WHILE list#NIL DO new _ CONS[list.first, new] ENDLOOP}; AppendIndexToRope: PUBLIC PROC[index: INT, item: PW.ROPE] -- If last char is '. RETURNS[PW.ROPE] = { IF Rope.Find[item, ".", 0]=-1 THEN RETURN[item]; RETURN[Rope.Cat[item, Convert.RopeFromInt[index, 36, FALSE] ] ] }; ExpandList: PUBLIC PROC[index1, index2: INT, list: LIST OF REF] RETURNS[new: List] ={ item1, item2, item3: PW.ROPE _ NIL; IF list = NIL THEN RETURN[NIL]; new _ ExpandList[index1, index2, list.rest]; IF list.first = NIL THEN RETURN[CONS[NIL, new]]; WITH list.first SELECT FROM first: Rope.ROPE => item1 _ first; first: REF TEXT => item1 _ Rope.FromRefText[first]; first: LIST OF REF => { WITH LISTIndexItem[first, index1] SELECT FROM second: Rope.ROPE => item2 _ second; second: REF TEXT => item2 _ Rope.FromRefText[second]; second: LIST OF REF => { WITH LISTIndexItem[second, index2] SELECT FROM third: Rope.ROPE => item3 _ third; third: REF TEXT => item3 _ Rope.FromRefText[third]; third: REF => IF third#NIL THEN ERROR; ENDCASE => ERROR }; second: List => item3 _ ListIndexItem[second, index2]; second: REF => IF second#NIL THEN ERROR; ENDCASE => ERROR }; first: LIST OF List => TRUSTED { second: List _ LOOPHOLE[LISTIndexItem[LOOPHOLE[first], index1]]; item3 _ ListIndexItem[second, index2]}; first: List => item2 _ ListIndexItem[first, index1]; first: REF => IF first#NIL THEN ERROR; ENDCASE => ERROR; IF item1#NIL THEN item2 _ AppendIndexToRope[index1, item1]; IF item2#NIL THEN item3 _ AppendIndexToRope[index2, item2]; RETURN[CONS[item3, new] ]}; OldGetMDS: PUBLIC PROC RETURNS[newMDS: INT] = TRUSTED { pagesAllocated, pagesFreed, pagesInPartition: INT; [pagesAllocated, pagesFreed, pagesInPartition]_ VMStatistics.VirtualAllocation[mds]; newMDS _ MAX[0, pagesInPartition - pagesAllocated + pagesFreed]}; AbutListX: PUBLIC PROC[design: CD.Design, list: LIST OF PW.ObjName] RETURNS[new: PW.ObjName] = { objList: LIST OF CD.ObPtr _ ListObjFromObjNames[design, list]; newAbut: CD.ObPtr _ CDAbuts.CreateNewAbutX[objList]; PWBasics.Include[design, newAbut]; new _ PWBasics.NameFromObj[newAbut]}; AbutListY: PUBLIC PROC[design: CD.Design, list: LIST OF PW.ObjName] RETURNS[new: PW.ObjName] = { objList: LIST OF CD.ObPtr _ ListObjFromObjNames[design, list]; newAbut: CD.ObPtr _ CDAbuts.CreateNewAbutY[objList]; PWBasics.Include[design, newAbut]; new _ PWBasics.NameFromObj[newAbut]}; AbutX: PUBLIC PROC[design: CD.Design, cell1, cell2: PW.ObjName] RETURNS[new: PW.ObjName] = {RETURN[ IF cell1=NIL THEN cell2 ELSE IF cell2=NIL THEN cell1 ELSE AbutListX[design, LIST[cell1, cell2]]]}; AbutY: PUBLIC PROC[design: CD.Design, cell1, cell2: PW.ObjName] RETURNS[new: PW.ObjName] = {RETURN[ IF cell1=NIL THEN cell2 ELSE IF cell2=NIL THEN cell1 ELSE AbutListY[design, LIST[cell1, cell2]]]}; ListObjFromObjNames: PROC [design: CD.Design, names: LIST OF PW.ObjName] RETURNS [LIST OF CD.ObPtr] = { revList, list: LIST OF CD.ObPtr _ NIL; WHILE names#NIL DO revList _ CONS[PWBasics.ObjFromName[design, names.first], revList]; names _ names.rest; ENDLOOP; WHILE revList#NIL DO list _ CONS[revList.first, list]; revList _ revList.rest; ENDLOOP; RETURN[list] }; UniqueIndex: INT _ 0; UniqueCellName: PUBLIC PROC[type: PW.ROPE, top, bot, ins, outs: List] RETURNS[name: PW.ROPE] = { Index: PROC[rope: PW.ROPE] RETURNS[index: INT] = { IF Rope.Equal[rope, "GND"] THEN RETURN[6]; IF Rope.Equal[rope, "VDD"] THEN RETURN[7]; index _ ListItemIndexMax[top, rope]; IF index IN [6..8) THEN ERROR Error["Impossible"]; IF index IN [0..12) THEN RETURN[index]; IF index # -1 THEN ERROR Error["Impossible"]; index _ ListItemIndexMax[bot, rope]; IF index IN [6..8) THEN ERROR Error["Impossible"]; IF index IN [0..12) THEN RETURN[index+12]; IF index = -1 THEN RETURN[31]; ERROR Error["Impossible"]}; topSig, botSig, tbEq, val: INT _ 0; IF MAX[ListLength[top], ListLength[bot]] > 12 THEN { UniqueIndex _ UniqueIndex+1; RETURN[IO.PutFR["%g-Lrg-%g", IO.rope[type], IO.int[UniqueIndex]]]}; FOR ii: INT IN [0..12) DO topN: PW.ROPE _ ListIndexItem[top, ii]; botN: PW.ROPE _ ListIndexItem[bot, ii]; IF ii IN [6..7] THEN LOOP; topSig _ (topSig*2) +(IF topN#NIL THEN 1 ELSE 0); botSig _ (botSig*2) +(IF botN#NIL THEN 1 ELSE 0); tbEq _ (tbEq*2) +(IF Rope.Equal[topN, botN] THEN 1 ELSE 0); ENDLOOP; val _ (topSig*1024+botSig)*1024+tbEq; name _ type.Cat["-"]; name _ name.Cat[Convert.RopeFromInt[from: val, base: 32, showRadix: FALSE]]; FOR ins _ ins, ins.rest WHILE ins#NIL DO val _ Index[ins.first]; name _ name.Cat[Convert.RopeFromInt[from: val, base: 32, showRadix: FALSE]] ENDLOOP; name _ name.Cat["-"]; FOR outs _ outs, outs.rest WHILE outs#NIL DO val _ Index[outs.first]; name _ name.Cat[Convert.RopeFromInt[from: val, base: 32, showRadix: FALSE]] ENDLOOP }; RegisterDesignWithPW: PUBLIC PROC[design: CD.Design] = { command: CDSequencer.Command _ NEW[CDSequencer.CommandRec _ [a: $FlushCaches]]; command _ NEW[CDSequencer.CommandRec _ [design: design, a: $FlushCaches]]; CDSequencer.ExecuteCommand[comm: command, queue: dontQueue] }; WriteOutNewDesign: PUBLIC PROC[design: CD.Design, newName: PW.ROPE] = { CDSimpleOps.RenameDesign[design, newName]; [ ] _ CDIO.WriteDesign[design, newName] }; AssembleList: PUBLIC PROC[ ref: REF, rowProc: LIST OF IFUPW.UserProc, newDesignName: PW.ROPE _ NIL, cmd: Commander.Handle _ NIL] RETURNS[cellName: PW.ObjName] = { design: CD.Design; length: INT _ 0; size: Size; viewer: ViewerClasses.Viewer; vmold, vmnew: WatchStats.WatchStatsRecord; cellList: LIST OF PW.ROPE _ NIL; WITH ref SELECT FROM designFile: Rope.ROPE => design _ CDIO.ReadDesign[designFile]; designRef: CD.Design => design _ designRef; ENDCASE => ERROR; RegisterDesignWithPW[design]; viewer _ CDViewer.CreateViewer[design]; PWBasics.Output[ IO.PutFR["\n\n%g\n", IO.time[]]]; vmold _ WatchStats.GetWatchStats[]; FOR rowProc _ rowProc, rowProc.rest WHILE rowProc#NIL DO cellN: PW.ROPE; obj: CD.ObPtr; IF rowProc.first=NIL THEN LOOP; cellN _ rowProc.first[design]; obj _ CDDirectory.Fetch[design, cellN].object; size _ PWBasics.GetISize[obj]; length _ length + size.y; cellList _ CONS[cellN, cellList]; vmnew _ WatchStats.GetWatchStats[]; PWBasics.Output[IO.PutFR["\n %5g %5g %5g %g", IO.int[length/2], IO.int[size.y/2], IO.int[vmold.vmFree - vmnew.vmFree], IO.rope[cellN] ] ]; vmold _ vmnew; ENDLOOP; cellName _ AbutListY[design, cellList ]; PWBasics.Output[ IO.PutFR["\n%g\n", IO.time[]]]; IF newDesignName # NIL THEN { -- Called from Command Tool write: BOOL _ IF cmd=NIL OR cmd.commandLine=NIL THEN FALSE ELSE IF Rope.Find[cmd.commandLine,"-w",0,FALSE]=-1 THEN FALSE ELSE TRUE; print: BOOL _ IF cmd.commandLine=NIL THEN FALSE ELSE IF Rope.Find[cmd.commandLine,"-p",0,FALSE]=-1 THEN FALSE ELSE TRUE; newCellName: PW.ROPE _ newDesignName.Cat["Cell"]; obPtr: CD.ObPtr _ CDDirectory.Fetch[design, cellName].object; IF obPtr= NIL THEN ERROR; IF CDDirectory.Rename[design, obPtr, newCellName, TRUE].done THEN cellName _ newCellName ELSE cellName _ PW.ReName[cellName, newCellName]; obPtr _ CDDirectory.Fetch[design, cellName].object; size _ PWBasics.GetISize[obPtr]; CDOps.SetAppList[design, NIL]; CDOps.AddAnObject[design, obPtr, [0, 0]]; RepositionDesignViewer[design, viewer]; PWBasics.Output[cellName]; PWBasics.Output[" included in design\n\n" ]; IF write THEN WriteOutNewDesign[design, newDesignName]; IF print THEN PlotDesign[design, size]}; RETURN[cellName]}; Register: PUBLIC PROC [userProc: UserProc, name: ROPE] = {PW.Register[userProc, name]}; ByteBitFromIndex: PUBLIC PROC[index: INT, seq: BOOL] RETURNS[byte, bit: INT] = { byte _ IF seq THEN index / rngBit ELSE index MOD rngByte; bit _ IF seq THEN index MOD rngBit ELSE index / rngByte }; ByteBitToIndex: PUBLIC PROC[byte, bit: INT, seq: BOOL] RETURNS[index: INT] = { RETURN[IF seq THEN byte * rngBit + bit ELSE bit * rngByte + byte]}; RepositionDesignViewer: PUBLIC PROC[design: CD.Design, viewer: ViewerClasses.Viewer] = {CDViewer.ShowAndScale[viewer, CDExtras.BoundingBox[design]]}; PlotDesign: PUBLIC PROC[design: CD.Design, pos, sPos: Location _ [0, 0]] = { command: CDSequencer.Command _ NEW[CDSequencer.CommandRec _ [design: design, pos: pos, sPos: sPos, a: $VersatecAutoPlot]]; CDSequencer.ExecuteCommand[command, design, $VersatecAutoPlot]}; AssignRowPinsAndRename: PUBLIC PROC[ design: CD.Design, rowName: PW.ObjName, newName: PW.ObjName, identity: BOOL _ TRUE, top: LIST OF REF _ NIL, bot: LIST OF REF _ NIL, ctl: List _ NIL, seq: BOOL _ FALSE ] RETURNS[cellName: PW.ObjName] = { AssignNames: PinNameProc = { oldPinName: PW.ROPE _ CDPinObjects.GetName[pin]; IF identity THEN RETURN[oldPinName]; SELECT side FROM LtSide, RtSide => { IF oldPinName.Find[VDD]>=0 THEN RETURN[oldPinName]; IF oldPinName.Find[GND]>=0 THEN RETURN[oldPinName]; name _ ListIndexItem[ctl, Convert.IntFromRope[oldPinName]]}; TopSide, BotSide => { list: List; byte, bit: INT; column: INT _ ((pin.location.x MOD cellWidth)-leftTail)/metPitch; [byte, bit] _ ByteBitFromIndex[pin.location.x/cellWidth, seq]; list _ ExpandList[byte, bit, IF side=TopSide THEN top ELSE bot]; list _ FixGVInList[list]; name _ ListIndexItem[list, column]; IF name=NIL THEN ERROR}; ENDCASE => ERROR}; cellName _ RenamePins[design, rowName, newName, AssignNames]}; PinNameProc: TYPE = PROC[pin: CD.ApplicationPtr, side: Side] RETURNS[name: PW.ObjName]; RenamePins: PUBLIC PROC[ design: CD.Design, refObjName: PW.ObjName, newObjName: PW.ObjName, pinNameProc: PinNameProc] RETURNS [cellName: PW.ObjName] = { KeepPinOnEdge: CDPinObjects.AppEnumerator = { newRope: PW.ROPE; newApp: CD.ApplicationPtr; side: Side; isOnBorder: BOOL; [isOnBorder, side] _ PWPins.GetSide[refObj, app]; IF ~isOnBorder THEN RETURN; newRope _ pinNameProc[app, side]; IF Rope.IsEmpty[newRope] THEN RETURN; newApp _ NEW[CD.Application _ [ ob: CDPinObjects.CreatePinOb[app.ob.size], location: app.location, orientation: app.orientation, properties: CDProperties.CopyProps[app.properties]]]; CDPinObjects.SetName[newApp, newRope]; newCellPtr.contents _ CONS[newApp, newCellPtr.contents]; }; refObj: CD.ObPtr _ CDDirectory.Fetch[design, refObjName].object; newObj: CD.ObPtr _ NIL; newCellPtr: CD.CellPtr; app: CD.ApplicationPtr _ NEW[CD.Application _ [ob: refObj]]; CDProperties.PutPropOnApplication[app, $StopEnumerateDeepPins, $StopEnumerateDeepPins]; newObj _ CDCells.CreateEmptyCell[]; newCellPtr _ NARROW[newObj.specificRef]; [] _ PWPins.EnumerateDeepPins[refObj, KeepPinOnEdge]; newCellPtr.contents _ CONS[app, newCellPtr.contents]; CDCells.SetInterestRect[newObj, CD.InterestRect[refObj]]; [] _ PWBasics.RepositionCell[design, newObj, newObjName]; cellName _ CDDirectory.Name[newObj]; RETURN[cellName] }; FillerCell: PUBLIC PROC [design: CD.Design, obj: CD.ObPtr, objSide: Side, width: INT, copyPins: BOOL _ FALSE] RETURNS [cell: CD.ObPtr] = { KeepPinOnEdge: PWPins.AppEnumerator = { isOnIt: BOOL; side: Side; layer: CD.Layer _ CDPinObjects.GetLayer[app]; name: PW.ROPE _ CDPinObjects.GetName[app]; [isOnIt, side] _ PWPins.GetSide[obj, app]; IF ~isOnIt OR side#objSide THEN RETURN[FALSE]; SELECT side FROM TopSide, BotSide => { locX: INT _ app.location.x-rRect.x1; AddRet[cell, [app.ob.size.x, width], [locX, 0], layer]; IF copyPins THEN { PutPin[cell, [app.ob.size.x, pinDim], [locX, 0], layer, name]; PutPin[cell, [app.ob.size.x, pinDim], [locX, width-pinDim], layer, name]}}; ENDCASE => { locY: INT _ app.location.y-rRect.y1; AddRet[cell, [width, app.ob.size.y], [0, locY], layer]; IF copyPins THEN { PutPin[cell, [pinDim, app.ob.size.y], [0, locY], layer, name]; PutPin[cell, [pinDim, app.ob.size.y], [width-pinDim, locY], layer, name]}}}; rRect, fRect: CD.Rect; pinDim: INT _ MIN[8, width/2]; IF copyPins AND pinDim = 0 THEN ERROR; cell _ CDCells.CreateEmptyCell[]; rRect _ CD.InterestRect[obj]; fRect _ SELECT objSide FROM TopSide, BotSide => [0, 0, rRect.x2-rRect.x1, width], LtSide, RtSide => [0, 0, width, rRect.y2-rRect.y1], ENDCASE => ERROR; CDCells.SetInterestRect[cell, fRect]; [] _ PWPins.EnumerateDeepPins[obj, KeepPinOnEdge]; [] _ PWBasics.RepositionCell[design, cell, "Filler"] }; END. `IFUPWUtils.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last Edited by Curry, June 22, 1985 3:30:39 pm PDT GVTypeList: PUBLIC List _ LIST["latch", "triDr", "buf", "inv", "nor", "nand", "xor"]; Horizontal connections IF (size.x MOD 2)=1 OR (size.y MOD 2)=1 OR size.x<0 OR size.y<0 ViewerOps.ChangeColumn[viewer, color]; Ê"˜šœ™Jšœ<™Jš œ œœ œœ˜1J˜šž œœ"œ œ˜LJšœ˜Jšœœœ˜Jšœ œ(˜=Jšœ œ˜!Jšœœ˜7Jšœœ˜/Jšœ ˜ šœœœ˜%Jšœ.˜.šœ˜Jšœœœ˜N—Jšœœ˜—šœœœ˜&Jšœ1˜1šœ˜Jšœœœ˜O—Jšœœ˜—šœœ˜Jšœœ˜ šœœœ ˜Jšœœ˜Jšœ œ˜%Jšœ$œœ˜0Jšœ œ˜Jšœ$˜$Jšœ)˜)Jšœ˜Jšœœœ˜.———J˜J˜šž œœœ˜Jšœœ˜Jšœœ˜Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ œ˜Jšœœ˜ Jšœœ˜ Jšœœ˜ Jšœœ˜šžœœœœ˜EJš œœœœœ˜Jšœ&˜&Jšœ œœ œ˜8—š žœœ œœœ˜0Jšœœ8˜?—Jšœ˜Jšœ œ˜Jšœ˜Jšœ˜Jšœ=˜=Jšœ˜Jšœ ˜ šœœœ˜š žœœ œœœ˜1Jšœœœœ˜(Jšœ˜Jšœ.˜.Jšœ œœ˜Jšœ8˜8Jšœœ˜—Jšœ˜Jšœ.˜.Jšœ-˜-Jšœ.˜.š œœœœœœ˜>š œœœœœœ˜;Jšœœ œœ˜J——šœœœœœ œœ˜Išœœœœœœœ˜OJšœœ#œœ˜R——Jšœ˜—Jšœ™š œœœœœ˜9šžœœœ˜Jšœ œ˜Jšœœœœ˜5Jšœ˜Jšœ)˜)Jšœ/˜/JšœD˜DJšœ5˜5—Jšœœ ˜)Jšœ2˜2Jšœ-˜-Jšœ.˜.Jš œœœœ œ˜2Jšœ˜ —J˜—šž œœ˜Jšœœ*œ œ˜LJšœœœ#˜4šœœœ ˜Jšœœœ˜'Jšœœœ˜'Jšœ˜Jšœ8˜8šœœœ$˜6Jš œœ œœœ˜$—šœœœ,˜>Jš œœ œœœ˜$—Jšœ˜ ——J˜šžœœœ'œ˜]Jšœœœ˜Jšœœ˜ šœœœ ˜Jšœœœœœœœœ ˜:J˜ Jšœ˜ ——š žœœœœ*œ ˜TJš œ œœ œœ œ ™?šœ œ ˜šœœœ˜Jšœ$œœ˜E——Jšœ œ œœ˜$JšœN˜N—šžœœœœ'œ œœ˜^šœœ˜JšœI˜I—Jšœ#˜#Jšœ&˜&—š žœœœ œœ œ˜PJšœ;˜A—š žœœœ œ#œ ˜KJšœœ ˜Jšœœ#˜*Jšœœ-˜5Jšœœ-˜5Jšœ&˜&Jšœ&˜&Jšœ5˜5šœ˜JšœO˜OJšœ@˜@JšœN˜NJšœ@˜@Jšœ˜—Jšœ%˜%Jšœ"˜"—J˜šž œœœœ˜DJšœœœœ˜:—š ž œœœœœ˜?Jšœœ˜ šœ˜Jšœœœœœœœœ˜6Jšœ ˜ Jšœ˜ ——šž œœœœ ˜:Jšœœ$˜+—šž œœœœ˜>Jšœœœ˜Jš œœœœœ˜š œœ œœ˜2Jšœœœ˜(Jš œœœœœœ˜BJš œœœœœœ˜.Jšœœ˜Jšœœ œ˜——šž œœœœ˜<š œœ œœœ˜BJšœœœ˜(Jšœœœ˜"Jšœœœ˜"Jšœœ œ˜——šž œœœœœœ œ˜;Jšœœœœ˜š œœ œœœ˜BJšœœ˜$Jšœœœ œœ œœ˜DJšœœœ œœ œœ˜DJšœœ œ˜——š ž œœœœ œ˜<šœœœœ˜-Jšœ œœœœœœœ˜=——šž œœœœœœœ œ˜Cšœœœœ˜-Jšœ œœœœœœœ˜=——š žœœœœœœ˜DJš œœœœœœ˜4—š žœœœ"œœœ˜TJšœœœœœœœœœœ ˜U—š žœœœHœœ˜eJšœœœœ˜Jšœœ œœJ˜dJšœœ˜ Jšœ œœ œ œœœ˜Ašœœ ˜*š œ œœœœœ˜4Jšœœœ˜>Jšœœœ˜-———šžœœ˜JšœGœœœ˜VJšœ˜š œœ œœœ˜ JšœG˜G—Jšœœ˜ Jšœ œœ œ œœœ˜AJš œœ œœœ˜S—š ž œœœœœ˜9Jš œœœœœœ˜@—šž œœœœœœœœ˜@Jš œœœœœœ˜@—šž œœœœœœœ˜NJš œœ œœœœ˜PJš œœœœœœ˜.—šž œœœœœœ œœœ˜QJš œœ œœœœ˜PJš œœœœœœ˜.—šžœœœœœœœ˜QJšœœœœ˜šœœœ˜(Jšœœœ˜3Jšœœ˜—Jšœ˜ —š žœœœœœ˜Dšœœœ˜(Jšœ œœœ˜%Jšœœ˜—Jšœ˜ —šžœœœœœœœ˜QJšœœ˜Jšœ ˜ Jšœœœœ˜šœœœ˜,Jšœ˜Jšœœœ˜<——š žœœœœœ˜DJšœœ˜Jšœ ˜ šœœœ˜,Jšœ˜Jšœ œœœ˜.——šž œœœœ˜Jšœ˜—Jšœ%˜%Jšœ˜JšœDœ˜Lšœœœ˜)Jšœ˜JšœDœœ˜T—Jšœ˜šœœœ˜,Jšœ˜JšœDœœ˜V——J˜šžœœœ œ ˜8Jšœœ-˜OJšœ œ=˜JJšœ>˜>J˜—š žœœœ œœœ˜GJšœ*˜*Jšœœ ˜*—J˜šž œœœ˜Jšœœ˜ Jšœ œœœ ˜ Jšœœœœ˜Jšœœ˜Jšœ œ ˜!Jšœœ˜Jšœœ˜Jšœ ˜ Jšœ˜Jšœ*˜*Jš œ œœœœœ˜ šœœ˜Jšœœ œ˜>Jšœ œ˜+Jšœ œ˜—Jšœ˜Jšœ'˜'Jšœ&™&Jšœœœ ˜2Jšœ#˜#šœ!œ œ˜8Jšœœœ˜Jšœœ˜Jšœœœœ˜Jšœ˜Jšœ/˜/Jšœ˜Jšœ˜Jšœ œ˜!Jšœ#˜#šœœ˜0Jšœ˜Jšœ˜Jšœ"˜$Jšœ˜—Jšœ˜Jšœ˜——šœ)˜)Jšœœœ ˜0šœœœŸ˜9š œœœœœ˜/š œœœœ"œ˜=Jšœœœœ˜——šœœœ˜$š œœœœ"œ˜=Jšœœœœ˜——Jšœ œœ˜1Jšœœ4˜=Jšœœœœ˜šœ0œ˜˜>J˜—šž œœœ œ*˜Lšœœ˜;Jšœ>˜>—Jšœ@˜@—J˜šžœœœ˜$Jšœ œ˜Jšœ œ ˜Jšœ œ ˜Jšœ œœ˜Jš œœœœœ˜Jš œœœœœ˜Jšœœ˜šœœœ˜Jšœ œ ˜!—šœ˜Jšœ œœ˜0Jšœ œœ ˜$šœ˜šœ˜Jšœœœœ ˜3Jšœœœœ ˜3Jšœ<˜<—šœ˜Jšœ ˜ Jšœ œ˜Jšœœœ˜AJšœ?˜?Jšœ œœœ˜CJšœ˜Jšœ&˜&Jšœœœœ˜—Jšœœ˜——Jšœ>˜>—J˜šž œœœœ˜JšœW˜WJšœ$˜$Jšœ œ˜(Jšœ5˜5Jšœœ˜5Jšœ œ˜9Jšœ9˜9Jšœ$˜$Jšœ ˜—J˜šž œœ˜Jš œ œœœ œœ˜UJšœœ ˜šœ'˜'Jšœœ˜ Jšœ ˜ Jšœœ$˜.Jšœœœ˜+Jšœ*˜*Jš œ œœœœ˜.šœ˜šœ˜Jšœœ˜$Jšœ7˜7šœ œ˜JšœB˜BJšœK˜K——šœ˜ Jšœœ˜$Jšœ7˜7šœ œ˜JšœA˜AJšœL˜L————Jšœœ˜Jš œœœœ œ œœ˜EJšœ!˜!Jšœœ˜šœœ ˜Jšœ5˜5Jšœ3˜3Jšœœ˜—Jšœ&˜&Jšœ2˜2Jšœ7˜7—J˜Jšœ˜—J™J™—…—\Ž€‹