DIRECTORY CD, CDCells, CDExtras, CDFrame, CDIO, CDOps, CDOrient, CDPinObjects, CDProperties, CDRects USING [CreateRect], CDSequencer, CDSil, CDSimpleOps, CDViewer, Convert, Commander, DragOpsCross, IFUPW, IO, PW, PWPins, Rope, ViewerClasses; IFUPWImpl: CEDAR PROGRAM IMPORTS CD, CDCells, CDExtras, CDFrame, CDIO, CDOps, CDPinObjects, CDProperties, CDRects, CDSequencer, CDSil, CDSimpleOps, CDViewer, Convert, IO, IFUPW, PW, PWPins, Rope EXPORTS IFUPW = BEGIN OPEN IFUPW; Error: PUBLIC ERROR[msg: ROPE] = CODE; log: PUBLIC IO.STREAM _ CDFrame.GetLog[]; GND: PUBLIC Rope.ROPE _ "GND"; VDD: PUBLIC Rope.ROPE _ "VDD"; IFUDataColSeq: PUBLIC RowParams _ NEW[RowParamsRec _ [seq: TRUE] ]; IFUDataColNSeq: PUBLIC RowParams _ NEW[RowParamsRec _ [seq: FALSE] ]; ChangePinName: PUBLIC PROC[obj: CD.Object, oldName, newName: ROPE] = { pins: CD.InstanceList _ 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.Object] 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.Object, top: List, in: List, out: List, bot: List, refcell: CD.Object, 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.Object; IF ~Same[idx, tIdx] AND ~Same[idx, bIdx] THEN RETURN; wLoc.y _ connSpec[idx].y; ctct _ Contact[cmosPoly]; wire _ CDRects.CreateRect[[wLen, polW], cmosPoly]; [] _ PW.IncludeInCell[cell, ctct, [wLoc.x-(cnctSize-metW)/2, wLoc.y-(cnctSize-polW)/2]]; [] _ PW.IncludeInCell[cell, wire, wLoc] }; wLen: INT _ (nofVWires-1-i)*metPitch + cnctSize; 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.Object, top, bot: List, refX, topY, botY: INT, realNames: BOOL] = { length: INT _ MAX[ListLength[top], ListLength[bot]]; FOR i: INT IN [0..length) DO tName: ROPE _ ListIndexItem[top, i]; bName: ROPE _ ListIndexItem[bot, i]; size: Size _ [metW, metW]; 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 }; AddRet: PUBLIC PROC [cell: CD.Object, 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; [] _ PW.IncludeInCell[cell, CDRects.CreateRect[size, level], loc]}; PutPin: PUBLIC PROC[cell:CD.Object, size:Size, loc:Location, level:CD.Layer, name:ROPE] = { pinApl: CD.Instance _ PW.IncludeInCell[cell, CDPinObjects.CreatePinOb[size], loc]; CDPinObjects.SetName[pinApl, name]; CDPinObjects.SetLayer[pinApl, level]}; 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: 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: 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: 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: 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: ROPE _ NIL ] RETURNS[list: List] = { refs: ARRAY [0..16) OF 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}; ListConcat: PUBLIC PROC [list1, list2: List] RETURNS[new: List] = { FOR i: INT DECREASING IN [0..ListLength[list2]) DO new _ CONS[ ListIndexItem[list2, i], new] ENDLOOP; FOR i: INT DECREASING IN [0..ListLength[list1]) DO new _ CONS[ ListIndexItem[list1, i], new] 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: 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: 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: 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: ROPE] -- If last char is '. RETURNS[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: 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] ]}; UniqueIndex: INT _ 0; UniqueCellName: PUBLIC PROC[type: ROPE, top, bot, ins, outs: List] RETURNS[name: ROPE] = { Index: PROC[rope: 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: ROPE _ ListIndexItem[top, ii]; botN: 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 }; WriteOutNewDesign: PUBLIC PROC[design: CD.Design, newName: ROPE] = { CDSimpleOps.RenameDesign[design, newName]; [ ] _ CDIO.WriteDesign[design, newName] }; GetDesign: PUBLIC PROC[ref: REF] RETURNS[design: CD.Design] = { WITH ref SELECT FROM text: REF TEXT => design _ CDIO.ReadDesign[Rope.FromRefText[text]]; designFile: Rope.ROPE => design _ CDIO.ReadDesign[designFile]; designRef: CD.Design => design _ designRef; ENDCASE => ERROR}; NFS, NewFrameSeq: PUBLIC PROC[ module: ROPE, xory: XorY, listTopLt: LIST OF Frame, orient: CD.Orientation _ CD.original ] RETURNS[frame: Frame] = { count: INT _ 0; FOR list: LIST OF Frame _ listTopLt, list.rest WHILE list # NIL DO IF list.first=NIL THEN LOOP; count _ count+1 ENDLOOP; frame _ NEW[CDFrame.FrameSeq[count]]; frame.xory _ xory; frame.orient _ orient; frame.shell _ NEW[CDFrame.ShellRec _ [name: module]]; count _ (IF xory=x THEN 0 ELSE count-1); FOR list: LIST OF Frame _ listTopLt, list.rest WHILE list # NIL DO IF list.first=NIL THEN LOOP; frame[count] _ list.first; count _ count + (IF xory=x THEN 1 ELSE -1) ENDLOOP}; NFSFUP, NewFrameSeqFromListUserProc: PUBLIC PROC[ module: ROPE, xory: XorY, listTopLt: LIST OF UserProc, orient: CD.Orientation _ CD.original ] RETURNS[frame: Frame] = { count: INT _ 0; FOR list: LIST OF UserProc _ listTopLt, list.rest WHILE list # NIL DO count _ count+1 ENDLOOP; frame _ NEW[CDFrame.FrameSeq[count]]; frame.xory _ xory; frame.orient _ orient; frame.shell _ NEW[CDFrame.ShellRec _ [name: module]]; count _ (IF xory=x THEN 0 ELSE count-1); FOR list: LIST OF UserProc _ listTopLt, list.rest WHILE list # NIL DO refProc: REF UserProc _ NEW[UserProc _ list.first]; IF list.first=NIL THEN LOOP; frame[count] _ NEW[CDFrame.FrameSeq[0]]; frame[count].data _ refProc; count _ count + (IF xory=x THEN 1 ELSE -1) ENDLOOP}; ShowObject: PUBLIC PROC[cell: CD.Object] = { design: CD.Design _ CDOps.CreateDesign[IFUPW.cmos]; viewer: ViewerClasses.Viewer _ CDViewer.CreateViewer[design]; CDOps.AddAnObject[design, cell, [0, 0]]; CDViewer.ShowAndScale[viewer, CDExtras.BoundingBox[design]]}; Show5Objects: PUBLIC PROC [bottom, right, top, left, middle: CD.Object] = { design: CD.Design _ CDOps.CreateDesign[IFUPW.cmos]; viewer: ViewerClasses.Viewer _ CDViewer.CreateViewer[design]; maxX: INT _ MAX[ IF top=NIL THEN 0 ELSE CD.InterestSize[top].x, IF bottom=NIL THEN 0 ELSE CD.InterestSize[bottom].x]; maxY: INT _ MAX[ IF left=NIL THEN 0 ELSE CD.InterestSize[left].y, IF right=NIL THEN 0 ELSE CD.InterestSize[right].y]; CDOps.SetInstList[design, NIL]; CDOps.AddAnObject[design, left, [-CD.InterestSize[left].x, 0]]; CDOps.AddAnObject[design, bottom, [0, -CD.InterestSize[bottom].y]]; CDOps.AddAnObject[design, top, [0, maxY]]; CDOps.AddAnObject[design, right, [maxX, 0]]; CDOps.AddAnObject[design, middle, [0, 0]]; CDViewer.ShowAndScale[viewer, CDExtras.BoundingBox[design]]}; ShowFrameBlock: PUBLIC PROC[frame: Frame] ~ { designB: CD.Design _ CDOps.CreateDesign[CDSil.cdsil]; viewerB: ViewerClasses.Viewer _ CDViewer.CreateViewer[designB]; cellB: CD.Object _ CDFrame.FrameToObject[frame, designB, FALSE]; CDSimpleOps.RenameDesign[designB, "ShowFrameBlock"]; CDOps.AddAnObject[designB, cellB, [0, 0]]; RepositionDesignViewer[designB, viewerB]}; AssembleFrame: PUBLIC PROC[ ref: REF, frame: REF CDFrame.FrameSeq, cmd: Commander.Handle, name: ROPE _ NIL ] = { design, designB: CD.Design; cell, cellB: CD.Object; done: BOOL _ FALSE; impl: BOOL _ TRUE; block: BOOL _ TRUE; write: BOOL _ FALSE; plot: BOOL _ FALSE; IF name=NIL AND frame.shell#NIL THEN name _ frame.shell.name; IF frame.shell=NIL OR NOT Rope.Equal[frame.shell.name, name] THEN { FOR index: INT IN [0..frame.seqSize) DO AssembleFrame[ref, frame[index], cmd, name] ENDLOOP; RETURN}; design _ GetDesign[ref]; IF cmd#NIL AND cmd.commandLine#NIL THEN { IF Rope.Find[cmd.commandLine,"-i", 0,FALSE]#-1 THEN impl _ NOT impl; IF Rope.Find[cmd.commandLine,"-b", 0,FALSE]#-1 THEN block _ NOT block; IF Rope.Find[cmd.commandLine,"-w", 0,FALSE]#-1 THEN write _ NOT write; IF Rope.Find[cmd.commandLine,"-p", 0,FALSE]#-1 THEN plot _ NOT plot }; IF impl THEN { viewer: ViewerClasses.Viewer _ CDViewer.CreateViewer[design]; CDSimpleOps.RenameDesign[design, name]; CDOps.SetInstList[design, NIL]; cell _ CDFrame.FrameToObject[frame, design]; CDOps.AddAnObject[design, cell, [0, 0]]; RepositionDesignViewer[design, viewer]}; IF block THEN { designB: CD.Design _ CDOps.CreateDesign[CDSil.cdsil]; viewerB: ViewerClasses.Viewer _ CDViewer.CreateViewer[designB]; CDSimpleOps.RenameDesign[designB, name.Cat["Block"]]; cellB _ CDFrame.FrameToObject[frame, designB]; CDOps.AddAnObject[designB, cellB, [0, 0]]; RepositionDesignViewer[designB, viewerB]}; IF cell=NIL THEN {cell _ cellB; design _ designB}; IF write THEN WriteOutNewDesign[design, name]; IF plot THEN PlotDesign[design, [0,0], CD.InterestSize[cell]] }; Register: PUBLIC PROC [userProc: PWUserProc, name: ROPE] = {PW.Register[userProc, name]}; ByteBitFromIndex: PUBLIC PROC[index: INT, rp: RowParams] RETURNS[byte, bit: INT] = { byte _ IF rp.seq THEN index / rp.rngBit ELSE index MOD rp.rngByte; bit _ IF rp.seq THEN index MOD rp.rngBit ELSE index / rp.rngByte }; ByteBitToIndex: PUBLIC PROC[byte, bit: INT, rp: RowParams] RETURNS[index: INT] = { RETURN[IF rp.seq THEN byte * rp.rngBit + bit ELSE bit * rp.rngByte + byte]}; RepositionDesignViewer: PUBLIC PROC[design: CD.Design, viewer: ViewerClasses.Viewer] = {CDViewer.ShowAndScale[viewer, CDExtras.BoundingBox[design]]}; PlotDesign: PUBLIC PROC[design: CD.Design, pos: Location, sPos: Size _ [0, 0]] = { command: CDSequencer.Command _ NEW[CDSequencer.CommandRec _ [design: design, pos: pos, sPos: sPos, a: $VersatecAutoPlot]]; CDSequencer.ExecuteCommand[command, design, $VersatecAutoPlot]}; RenameObjAndAssignRowPins: PUBLIC PROC[ design: CD.Design, row: CD.Object, newObjName: ROPE, identity: BOOL _ TRUE, top: LIST OF REF _ NIL, bot: LIST OF REF _ NIL, leftCtl: List _ NIL, rightCtl: List _ NIL, rp: RowParams _ IFUDataColNSeq ] RETURNS[newObject: CD.Object] = { AssignNames: PinNameProc = { oldPinName: ROPE _ CDPinObjects.GetName[pin]; IF identity THEN RETURN[oldPinName]; SELECT side FROM left => { index: INT _ Rope.SkipTo[oldPinName, 0, "0123456789"]; IF oldPinName.Find[VDD]>=0 THEN RETURN[oldPinName]; IF oldPinName.Find[GND]>=0 THEN RETURN[oldPinName]; index _ Convert.IntFromRope[Rope.Substr[oldPinName, index]]; name _ ListIndexItem[leftCtl, index]}; right => { index: INT _ Rope.SkipTo[oldPinName, 0, "0123456789"]; IF oldPinName.Find[VDD]>=0 THEN RETURN[oldPinName]; IF oldPinName.Find[GND]>=0 THEN RETURN[oldPinName]; index _ Convert.IntFromRope[Rope.Substr[oldPinName, index]] - ListLength[leftCtl]; name _ ListIndexItem[rightCtl, index]}; top, bottom => { list: List; byte, bit: INT; column: INT _ ((pin.location.x MOD cellWidth)-leftTail)/metPitch; [byte, bit] _ ByteBitFromIndex[pin.location.x/cellWidth, rp]; list _ ExpandList[byte, bit, IF side=top THEN top ELSE bot]; list _ FixGVInList[list]; name _ ListIndexItem[list, column]; IF name=NIL THEN ERROR}; ENDCASE => ERROR}; newObject _ RenameObjAndPins[design, row, newObjName, AssignNames]}; RenameObjAndPins: PUBLIC PROC[ design: CD.Design, object: CD.Object, newObjName: ROPE, pinNameProc: PinNameProc] RETURNS[newObject: CD.Object] = { KeepPinOnEdge: CDPinObjects.InstanceEnumerator = { newRope: ROPE; newInst: CD.Instance; side: CDFrame.Side5; 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: CDPinObjects.CreatePinOb[inst.ob.size], location: inst.location, orientation: inst.orientation ]]; CDProperties.CopyProps[inst.properties, newInst]; CDPinObjects.SetName[newInst, newRope]; newCellPtr.contents _ CONS[newInst, newCellPtr.contents]; }; newCellPtr: CD.CellPtr; inst: CD.Instance _ NEW[CD.InstanceRep _ [ob: object]]; CDProperties.PutPropOnInstance[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]]; PW.IncludeInDirectory[design, newObject, newObjName]; RETURN[newObject] }; FillerCell: PUBLIC PROC [design: CD.Design, obj: CD.Object, objSide: Side, width: INT, copyPins: BOOL _ FALSE] RETURNS [cell: CD.Object] = { KeepPinOnEdge: PWPins.InstanceEnumerator = { side: Side; layer: CD.Layer _ CDPinObjects.GetLayer[inst]; name: ROPE _ CDPinObjects.GetName[inst]; side _ PWPins.GetSide[obj, inst]; IF side#objSide THEN RETURN[FALSE]; SELECT side FROM top, bottom => { locX: INT _ inst.location.x-rRect.x1; AddRet[cell, [inst.ob.size.x, width], [locX, 0], layer]; IF copyPins THEN { PutPin[cell, [inst.ob.size.x, pinDim], [locX, 0], layer, name]; PutPin[cell, [inst.ob.size.x, pinDim], [locX, width-pinDim], layer, name]}}; ENDCASE => { locY: INT _ inst.location.y-rRect.y1; AddRet[cell, [width, inst.ob.size.y], [0, locY], layer]; IF copyPins THEN { PutPin[cell, [pinDim, inst.ob.size.y], [0, locY], layer, name]; PutPin[cell, [pinDim, inst.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 top, bottom => [0, 0, rRect.x2-rRect.x1, width], left, right => [0, 0, width, rRect.y2-rRect.y1], ENDCASE => ERROR; CDCells.SetInterestRect[cell, fRect]; [] _ PWPins.EnumerateDeepPins[obj, KeepPinOnEdge]; [] _ PW.IncludeInDirectory[design, cell, "Filler"] }; END. :IFUPWImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last Edited by Curry, January 27, 1986 9:42:58 am PST Horizontal connections IF (size.x MOD 2)=1 OR (size.y MOD 2)=1 OR size.x<0 OR size.y<0 SizeOf: PUBLIC PROC[design: CD.Design, cell: CD.Object] RETURNS[size: Size] = { RETURN[CD.InterestSize[cell ] ]}; Merge: PUBLIC PROC[design: CD.Design, side: Side, cell1, cell2: PW.ObjName] RETURNS[cell: PW.ObjName] = { obj: CD.Object _ CDCells.CreateEmptyCell[]; obj1: CD.Object _ PWBasics.ObjFromName[design, cell1]; obj2: CD.Object _ PWBasics.ObjFromName[design, cell2]; size1: Size _ CD.InterestSize[obj1]; size2: Size _ CD.InterestSize[obj2]; [ ] _ PW.IncludeInCell[obj, obj1, [0, 0]]; SELECT side FROM top => [ ] _ PW.IncludeInCell[obj, obj2, [0, size1.y-size2.y]]; bottom => [ ] _ PW.IncludeInCell[obj, obj2, [0, 0]]; right => [ ] _ PW.IncludeInCell[obj, obj2, [0, size1.x-size2.x]]; left => [ ] _ PW.IncludeInCell[obj, obj2, [0, 0]]; ENDCASE; PW.IncludeInDirectory[design, obj]; cell _ PWBasics.NameFromObj[obj]}; IF list.first=NIL THEN LOOP; Ê"¾˜šœ™Jšœ<™Jš œ œœ œœ˜1J˜šž œœ"œ œ˜MJšœ˜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šœ2˜2šœœ˜!Jšœ6˜6—Jšœœ#˜*—Jšœœ'˜0Jšœ2˜2Jšœ-˜-Jšœ.˜.Jš œœœœ œ˜2Jšœ˜ —J˜—šž œœ˜Jšœœ+œ œ˜MJšœœœ#˜4šœœœ ˜Jšœœ˜$Jšœœ˜$Jšœ˜Jšœ8˜8šœœœ$˜6Jš œœ œœœ˜$—šœœœ,˜>Jš œœ œœœ˜$—Jšœ˜ ——J˜š žœœœœ+œ ˜UJš œ œœ œœ œ ™?šœ œ ˜šœœœ˜Jšœ$œœ˜E——Jšœ œ œœ˜$Jšœœ<˜C—š žœœœœ(œ œ˜\šœœ ˜Jšœœ:˜>—Jšœ#˜#Jšœ&˜&—š žœœœ œœ œ™OJšœœ ™!—š žœœœ œ#œ ™KJšœœ ™Jšœ œ™+Jšœ œ'™6Jšœ œ'™6Jšœ$™$Jšœ$™$Jšœ*™*šœ™Jšœ@™@Jšœ4™4JšœB™BJšœ3™3Jšœ™—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šœ œœœœœœœ˜=——š žœœœœœ˜AJš œœœœœœ˜4—š žœœœ"œœ˜QJšœœœœœœœœœœ ˜U—š žœœœHœœ˜eJšœœœœ˜Jšœœ œœJ˜dJšœœ˜ Jšœ œœ œ œœœ˜Ašœœ ˜*š œ œœœœœ˜4Jšœœœ˜>Jšœœœ˜-———šžœœ˜JšœGœœ˜SJšœ˜šœœ œœ˜JšœG˜G—Jšœœ˜ Jšœ œœ œ œœœ˜AJš œœ œœœ˜S—šž œœœœ˜Cš œœ œœ˜2Jšœœ œ˜2—š œœ œœ˜2Jšœœ œ˜3——š ž œœœœœ˜9Jš œœœœœœ˜@—šž œœœœœœœœ˜@Jš œœœœœœ˜@—š ž œœœœœœ˜KJš œœ œœœœ˜PJš œœœœœœ˜.—šž œœœœœœ œœœ˜QJš œœ œœœœ˜PJš œœœœœœ˜.—š žœœœœœœ˜NJšœœœœ˜šœœœ˜(Jšœœœ˜3Jšœœ˜—Jšœ˜ —š žœœœœœ˜Dšœœœ˜(Jšœ œœœ˜%Jšœœ˜—Jšœ˜ —š žœœœœœœ˜NJšœœ˜Jšœ ˜ Jšœœœœ˜šœœœ˜,Jšœ˜Jšœœœ˜<——š žœœœœœ˜DJšœœ˜Jšœ ˜ šœœœ˜,Jšœ˜Jšœ œœœ˜.——šž œœœœ˜Jšœ˜—Jšœ%˜%Jšœ˜JšœDœ˜Lšœœœ˜)Jšœ˜JšœDœœ˜T—Jšœ˜šœœœ˜,Jšœ˜JšœDœœ˜V——J˜š žœœœ œœ˜DJšœ*˜*Jšœœ ˜*—J˜š ž œœœœœ œ ˜?šœœ˜Jšœœœ œ$˜EJšœœ œ˜>Jšœ œ˜+Jšœ œ˜——J˜šžœœœ˜Jšœ œ˜Jšœ ˜ Jšœ œœ˜šœ'˜'Jšœ˜—Jšœœ˜š œœœœœ˜BJšœ œœœ˜Jšœœ˜—Jšœœ˜%Jšœ˜Jšœ˜Jšœœ$˜5Jšœ œœœ ˜(š œœœœœ˜BJšœ œœœ˜Jšœ˜Jš œœœœœ˜4——šž#œœœ˜1Jšœ œ˜Jšœ ˜ Jšœ œœ ˜šœ'˜'Jšœ˜—Jšœœ˜š œœœ!œœ˜EJšœ œœœ™Jšœœ˜—Jšœœ˜%Jšœ˜Jšœ˜Jšœœ$˜5Jšœ œœœ ˜(š œœœ!œœ˜EJšœ œ œ˜3Jšœ œœœ˜Jšœ(˜(Jšœ˜Jš œœœœœ˜4——J˜šž œœœœ ˜,Jšœœœ˜3Jšœ=˜=Jšœ(˜(Jšœ=˜=—J˜šž œ œ$œ ˜KJšœœœ˜3Jšœ=˜=šœœœ˜Jš œœœœœ˜/Jš œœœœœ ˜5—šœœœ˜Jš œœœœœ ˜0Jš œœœœœ ˜3—Jšœœ˜Jšœ#œ˜@Jšœ'œ ˜CJšœ+˜+Jšœ-˜-Jšœ*˜*Jšœ=˜=—J˜šžœ œ˜-Jšœ œ-˜8Jšœ?˜?Jšœ=œ˜DJšœ#žœ˜4Jšœ*˜*Jšœ*˜*—J˜šž œœœ˜Jšœœ˜ Jšœœ˜Jšœ˜Jšœ œ˜Jšœœ œ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jš œœœ œœ˜=š œ œœœ$œ˜Cšœœœ˜'JšÏb œœ˜4—JšÐbkœ˜—Jšœ˜š œœœœœ˜)Jšœ$œœœ˜EJšœ$œœœ˜GJšœ#œœœ˜FJšœ$œœœ˜H—šœœ˜Jšœ>˜>Jšœ'˜'Jšœœ˜Jšœ,˜,Jšœ(˜(Jšœ*˜*—šœœ˜Jšœ œ-˜8Jšœ?˜?Jšœ5˜5Jšœ.˜.Jšœ*˜*Jšœ*˜*—Jšœœœ"˜2Jšœœ!˜.šœœœ ˜@J˜——Jš žœœœœœ˜Yšžœœœœ˜8Jšœ œ˜Jš œœœœœ ˜CJš œœœœ œ˜D—J˜šžœœœ œ˜:Jšœœ˜šœœ˜Jšœ˜Jšœ˜ ——J˜šžœœœ œ)˜WJšœ>˜>J˜—šž œœœ œ0˜Ršœœ˜;Jšœ>˜>—Jšœ@˜@—J˜šžœœœ˜'Jšœ œ˜Jšœœ˜Jšœ œ˜Jšœ œœ˜Jš œœœœœ˜Jš œœœœœ˜Jšœœ˜Jšœœ˜šœ$˜$Jšœ œ ˜!—šœ˜Jšœ œ˜-Jšœ œœ ˜$šœ˜šœ ˜ Jšœœ,˜6Jšœœœœ ˜3Jšœœœœ ˜3Jšœ<˜˜>Jšœ œ œœ˜?Jšœ˜Jšœ&˜&Jšœœœœ˜—Jšœœ˜——JšœD˜D—J˜šžœœœ˜Jšœ œ˜Jšœ œ˜Jšœ œ˜šœ˜Jšœ œ ˜!—•StartOfExpansion= -- [app: CD.ApplicationPtr] RETURNS [quit: BOOL _ FALSE] -- šœ2˜2Jšœ œ˜Jšœ œ ˜Jšœ˜Jšœ$˜$Jšœ œœ˜Jšœ"˜"Jšœœœ˜%šœ œœ˜ Jšœ.˜.Jšœ˜Jšœ!˜!—Jšœ1˜1Jšœ'˜'Jšœœ˜9Jšœ˜—Jšœ œ ˜Jšœœ œœ˜9JšœU˜UJšœ'˜'Jšœ œ˜+Jšœ5˜5Jšœœ˜6Jšœ#œ˜