<> <> <> <<>> DIRECTORY Basics, CD, CDCells USING [CreateEmptyCell, SetInterestRect], CDDirectory, CDRects USING [CreateRect], Convert, IFUPW, IO, PW, Rope; IFUPWMux: CEDAR PROGRAM IMPORTS CD, CDCells, CDDirectory, CDRects, Convert, IO, IFUPW, PW, Rope EXPORTS IFUPW = BEGIN OPEN IFUPW; gnd: INT _ 6; vdd: INT _ 7; -- vdd assumed to be gnd+1 below <<>> IFUMuxRow: PUBLIC PROC [ design: CD.Design, name: PW.ROPE, leftCtl: List _ NIL, rightCtl: List _ NIL, top: LIST OF REF, in: LIST OF REF, out: LIST OF REF, bot: LIST OF REF, rp: RowParams _ IFUDataColNSeq ] RETURNS [cell: CD.Object] = { cells: PW.ListOb; ctl: List _ IFUPW.ListConcat[leftCtl, rightCtl]; FOR ii: INT DECREASING IN [0..rp.rngByte*rp.rngBit) DO byte, index: INT; [byte, index] _ IFUPW.ByteBitFromIndex[ii, rp]; cells _ CONS[ Mux[ design: design, ctl: ctl, in: ExpandList[byte, index, in], top: ExpandList[byte, index, top], out: ExpandList[byte, index, out], bot: ExpandList[byte, index, bot] ], cells]; ENDLOOP; cell _ PW.AbutListX[design, cells]; cell _ IFUPW.RenameObjAndAssignRowPins [design, cell, name, FALSE, top, bot, leftCtl, rightCtl, rp]; RETURN[cell]}; Mux: PROC [ design: CD.Design, top: List, ctl: List, in: List, out: List, bot: List] RETURNS [cell: CD.Object] = { cellName: PW.ROPE; xstrLgth: INT _ 8*lambda; xstrWth: INT _ (4+4)*lambda; tranBiasx: INT _ (xstrWth-metW)/2; xstrHt: INT _ xstrLgth + 2*difW; pFrng: INT _ (pwrW-metW)/2; topExtra: INT _ cnctSize/2 + topTail; botExtra: INT _ cnctSize/2 + botTail; pitch: Size = [metPitch, met2Pitch]; found: BOOL _ TRUE; muxEvenDn: BOOL = TRUE; range: Size; outN: PW.ROPE _ IF out=NIL THEN NIL ELSE out.first; iRect: CD.Rect; outIndex, outIndexBot: INT; top _ FixGVInList[top]; bot _ FixGVInList[bot]; range _ [MAX[ListLength[top],ListLength[bot]], ListLength[ctl]]; outIndex _ ListItemIndexMin[top, outN]; outIndexBot _ ListItemIndexMin[bot, outN]; IF outIndex # ListItemIndexMax[top, outN] OR outIndexBot # ListItemIndexMax[bot, outN] OR (outIndex#-1 AND outIndexBot#-1 AND outIndex#outIndexBot) THEN ERROR Error[IO.PutFR["Multiple column output %g- ABORT", IO.rope[outN]]]; IF outIndex = -1 THEN outIndex _ outIndexBot; cellName _ UniqueCellName["Mux", top, bot, in, out]; [found, cell] _ CDDirectory.Fetch[design, cellName]; IF found THEN RETURN[cell]; log.PutRope["."]; <> cell _ CDCells.CreateEmptyCell[]; IF outN#NIL AND ListItemIndexMax[top, outN]=-1 AND ListItemIndexMax[bot, outN]=-1 THEN ERROR Error[IO.PutFR ["Output signal (%g) is not in either top or bot lists - ABORT", IO.rope[outN]]]; IF outN#NIL AND ListItemIndexMax[in, outN]#-1 THEN ERROR Error[IO.PutFR ["Output signal (%g) is also used as input - ABORT", IO.rope[outN]]]; FOR i: INT IN [0..range.x) DO loc: Location _ [i*pitch.x, 0]; tIO: PW.ROPE _ ListIndexItem[top, i]; bIO: PW.ROPE _ ListIndexItem[bot, i]; topOut: BOOL _ Rope.Equal[tIO,outN]; botOut: BOOL _ Rope.Equal[bIO,outN]; tY: INT _ IF topOut THEN ListNonNILIndexMin[in] ELSE ListItemIndexMin[in,tIO]; bY: INT _ IF botOut THEN ListNonNILIndexMax[in] ELSE ListItemIndexMax[in,bIO]; tY _ tY + ((tY + (IF topOut=muxEvenDn THEN 1 ELSE 2)) MOD 2); bY _ bY + ((bY + (IF botOut=muxEvenDn THEN 1 ELSE 2)) MOD 2); IF tY=-1 AND bY=-1 THEN tY_bY_0; IF ~Rope.Equal[tIO, bIO] AND tY<=bY AND tIO#NIL AND bIO#NIL THEN ERROR Error[IO.PutFR ["2 signals (%g, %g) in same channel - ABORT", IO.rope[tIO], IO.rope[bIO]]]; IF tIO#NIL THEN AddRet[cell:cell, level: cmosMet, size: [metW, (range.y-tY) * pitch.y + topExtra ], loc: [i*pitch.x, tY * pitch.y ]]; IF bIO#NIL THEN AddRet[cell:cell, level: cmosMet, size: [metW, bY * pitch.y + botExtra ], loc: [i*pitch.x, 0 * pitch.y - botExtra ]]; ENDLOOP; FOR vgIndex: INT IN [gnd..vdd] DO AddRet[cell: cell, level: cmosMet, size: [pwrW, range.y * pitch.y + topExtra + botExtra ], loc: [vgIndex*pitch.x-pFrng, - botExtra ]] ENDLOOP; AddMetalPins [cell, top, bot, -leftTail, range.y*pitch.y+ topExtra, - botExtra, FALSE]; BEGIN xstr: CD.Object _ TransistorObject[size: [xstrWth, xstrLgth], difLayer: cmosNDif]; dcon: CD.Object _ IFUPW.Contact[cmosNDif]; pcon: CD.Object _ IFUPW.Contact[cmosPoly]; vcon: CD.Object _ IFUPW.Contact[cmosMet2]; scon: CD.Object _ IFUPW.Contact[cmosPWCont]; lstIONotGnd: BOOL _ TRUE; lstGndClear: BOOL _ TRUE; thsIONotGnd: BOOL _ TRUE; thsGndClear: BOOL _ TRUE; FOR ctlIndex: INT IN [0..range.y) DO cnctBiasx: INT _ (cnctSize-metW)/2; Include: PROC[object: CD.Object, location: Location] = {[] _ PW.IncludeInCell[cell, object, location]}; AddGndContact: PROC[updn: {up, dn}] = {IF updn=up THEN Include[scon, [gnd*pitch.x-cnctBiasx, (ctlIndex+1)*pitch.y - cnctSize/2 ]] ELSE Include[scon, [gnd*pitch.x-cnctBiasx, (ctlIndex+0)*pitch.y - cnctSize/2 ]]}; AddMux: PROC [index: Location] = { <> dWL: INT _ (ABS[outIndex-index.x])*pitch.x+cnctSize; pWL: INT _ (range.x-index.x)*pitch.x; minX: INT _ MIN[outIndex, index.x]; polX: INT _ MIN[outIndex, index.x]; pol: CD.Object _ CDRects.CreateRect[[pWL, polW], cmosPoly]; dif: CD.Object _ CDRects.CreateRect[[dWL, difW], cmosNDif]; <> dir: INT _ IF ((index.y MOD 2)=0)=muxEvenDn THEN 1 ELSE -1; yloc: INT _ index.y*pitch.y + pitch.y/2; Include[pcon, [range.x *pitch.x -cnctBiasx, yloc -cnctSize/2 ]]; Include[vcon, [range.x *pitch.x +cnctSize, yloc -cnctSize/2 ]]; Include[pol, [index.x *pitch.x -cnctBiasx, yloc -polW/2 ]]; Include[dif, [minX *pitch.x -cnctBiasx, yloc +dir*pitch.y/2 -difW/2 ]]; <> Include[dcon, [outIndex *pitch.x -cnctBiasx, yloc +dir*pitch.y/2 -cnctSize/2 ]]; Include[dcon, [index.x *pitch.x -cnctBiasx, yloc -dir*pitch.y/2 -cnctSize/2 ]]; Include[xstr, [index.x *pitch.x-tranBiasx, yloc -xstrLgth/2 ]]}; cName: PW.ROPE _ Convert.RopeFromInt[ctlIndex]; size: Size _ [cellWidth, met2W]; loc: Location _ [-leftTail, ctlIndex*pitch.y+pitch.y/2-met2W/2]; ioIndex: INT _ -1; AddRet[cell:cell, size:size, loc:loc, level:cmosMet2]; PutPin [cell, [met2W, met2W], loc, cmosMet2, cName]; PutPin [cell, [met2W, met2W], [cellWidth-leftTail-met2W, loc.y], cmosMet2, cName]; IF outN#NIL THEN { ioItem: PW.ROPE _ ListIndexItem[in, ctlIndex]; IF ioItem # NIL THEN { IF ioIndex < 0 THEN ioIndex _ ListItemIndexMax[top, ioItem]; IF ioIndex < 0 THEN ioIndex _ ListItemIndexMax[bot, ioItem]; IF ioIndex >=0 THEN AddMux[index: [ioIndex, ctlIndex]]}; thsIONotGnd _ ioIndex # gnd; thsGndClear _ thsIONotGnd AND ((ioIndex> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <<["2 signals (%g, %g) in same channel - ABORT", IO.rope[tIO], IO.rope[bIO]]];>> <> <> <> <> <> <> <> <> <<[cell, top, bot, -leftTail, rangeY*pitch.y+polW/2+met2W/2+topTail, -botTail, TRUE];>> <> <> <> <<{[] _ PW.IncludeInCell[cell, obj, location]};>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <= 0 THEN {>> <> <> <> <<>> <> <> <> <> <<0 => VDD,>> < GND,>> < ListIndexItem[ctl, ctlIndex-1];>> <> <> <> <> <> <> <> <> <> <= 0 THEN Put[viaCtct, [ioIndex*pitch.x-2, loc.y-1]];>> <<>> <