<> <> <> <> <<>> <<>> DIRECTORY Basics, CD, CDCells USING [CreateEmptyCell, SetInterestRect], CDDirectory, CDRects USING [CreateRect], CMos, CMosContacts, CMosTransistors, IFUPW, IO, PW, PWBasics, Rope; IFUPWLatch: CEDAR PROGRAM IMPORTS CD, CDCells, CDRects, CMosContacts, CMosTransistors, CMos, IO, IFUPW, PW, PWBasics, Rope EXPORTS IFUPW = BEGIN OPEN IFUPW; <<>> IFULatchRow: PUBLIC PROC [ design: CD.Design, enable: PW.ROPE, top: LIST OF REF, in: LIST OF REF, out: LIST OF REF, bot: LIST OF REF, seq: BOOL _ FALSE ] RETURNS [cell: PW.ObjName] = { cells: LIST OF PW.ObjName; FOR ii: INT DECREASING IN [0..rngByte*rngBit) DO index: INT _ IF seq THEN ii MOD rngBit ELSE ii / rngByte; byte: INT _ IF seq THEN ii / rngBit ELSE ii MOD rngByte; cells _ CONS[ Latch[ design: design, enable: enable, top: AddGV[ExpandList[byte, index, top]], in: ExpandList[byte, index, in], out: ExpandList[byte, index, out], bot: AddGV[ExpandList[byte, index, bot]]], cells]; ENDLOOP; RETURN[PW.AbutListX[cells]]}; Latch: PROC [ design: CD.Design, enable: PW.ROPE, disable: PW.ROPE _ "VBB", top: List, in: List, out: List, bot: List] RETURNS [PW.ObjName] = { topTail: INT = 4; botTail: INT = 2; pitch: Size = [mPitch, pBigPitch]; cell: CD.ObPtr _ CDCells.CreateEmptyCell[]; rangeX: INT _ nofVWires; inN: PW.ROPE _ IF in=NIL THEN NIL ELSE in.first; outN: PW.ROPE _ IF out=NIL THEN NIL ELSE out.first; <> FOR i: INT IN [0..nofVWires) DO Add: PROC[bindex, tindex, toptail, bottail: INT] = { loc.y _ bindex*pitch.y - bottail; size.y _ (tindex-bindex)*pitch.y + toptail + bottail; IF size.y>0 THEN AddRet[cell:cell, size:size, loc:loc, level: CMos.met]}; size: Size _ [6, 0]; loc: Location _ [i*pitch.x, 0]; tIO: PW.ROPE _ ListIndexItem[top, i]; bIO: PW.ROPE _ ListIndexItem[bot, i]; IF tIO#NIL THEN SELECT TRUE FROM Rope.Equal[tIO, bIO] => {Add[0, 4, 4+topTail, botTail]}; Rope.Equal[outN, tIO] => {Add[2, 4, 4+topTail, 0]}; Rope.Equal[inN, tIO] => {Add[3, 4, 4+topTail, 0]}; ENDCASE => ERROR; -- top not connected anywhere ABORT; IF bIO#NIL THEN SELECT TRUE FROM Rope.Equal[bIO, tIO] => LOOP; Rope.Equal[inN, bIO] => {Add[0, 3, 0, botTail]}; Rope.Equal[outN, bIO] => {Add[0, 2, 0, botTail]}; ENDCASE => ERROR; -- bottom not connected anywhere ABORT ENDLOOP; <> FOR i: INT IN [0..nofVWires) DO tName: PW.ROPE _ ListIndexItem[top, i]; bName: PW.ROPE _ ListIndexItem[bot, i]; size: Size _ [6, 6]; loc: Location _ [i*pitch.x, 4*pitch.y+4+topTail-size.y]; IF tName #NIL THEN PutPin [cell, size, loc, CMos.met, tName]; IF bName #NIL THEN PutPin [cell, size, [loc.x, -botTail], CMos.met, bName]; ENDLOOP; <> AddRet[cell:cell, size:[cellWidth, 4], loc:[-leftTail, 68], level: CMos.pol]; AddRet[cell:cell, size:[cellWidth,20], loc:[-leftTail, 48], level: CMos.met2]; AddRet[cell:cell, size:[cellWidth,20], loc:[-leftTail, 0], level: CMos.met2]; AddRet[cell:cell, size:[cellWidth, 4], loc:[-leftTail, 0], level: CMos.pol]; <> PutPin [cell, [4, 4], [-leftTail, 68], CMos.pol, disable]; PutPin [cell, [4, 4], [cellWidth-leftTail-4, 68], CMos.pol, disable]; PutPin [cell, [4,20], [-leftTail, 48], CMos.met2, "GND"]; PutPin [cell, [4,20], [cellWidth-leftTail-4, 48], CMos.met2, "GND"]; PutPin [cell, [4,20], [-leftTail, 2], CMos.met2, "VDD"]; PutPin [cell, [4,20], [cellWidth-leftTail-4, 2], CMos.met2, "VDD"]; PutPin [cell, [4, 4], [-leftTail, 0], CMos.pol, enable]; PutPin [cell, [4, 4], [cellWidth-leftTail-4, 0], CMos.pol, enable]; <> FOR i: INT IN [0..nofVWires) DO loc: Location _ [i * pitch.x, 0]; ioT: PW.ROPE _ ListIndexItem[top, i]; ioB: PW.ROPE _ ListIndexItem[bot, i]; loc.y _ 2*pitch.y; IF inN#NIL THEN IF Rope.Equal[inN, ioT] OR Rope.Equal[inN, ioB] THEN { [] _ PWBasics.IncludeApplication [cell, CMosContacts.CreatePolyCon[l: 8], [loc.x, loc.y-2]]; AddRet[cell:cell, size:[(nofVWires-i) * pitch.x, 4], loc:loc, level:CMos.pol]}; loc.y _ 1*pitch.y; IF outN#NIL THEN IF Rope.Equal[outN, ioT] OR Rope.Equal[outN, ioB] THEN { [] _ PWBasics.IncludeApplication [cell, CMosContacts.CreateMmCon[l: 10], [loc.x, loc.y-4]]; AddRet[cell:cell, size:[(nofVWires-i) * pitch.x, 10], loc:loc, level:CMos.met2]}; ENDLOOP; <> IF inN#NIL THEN { loc: Location _ [(nofVWires-2)*pitch.x, 0]; [] _ PWBasics.IncludeApplication[ cell: cell, subcell: PWBasics.ObjFromName[design, "GVLatch"], location: loc]; PWBasics.RepositionCell[design, cell]; RETURN[PWBasics.NameFromObj[cell]]}; IFUMuxRow: PUBLIC PROC [ design: CD.Design, top: LIST OF REF, ctl: List, in: LIST OF REF, out: LIST OF REF, bot: LIST OF REF, seq: BOOL _ FALSE ] RETURNS [cell: PW.ObjName] = { cells: LIST OF PW.ObjName; FOR ii: INT DECREASING IN [0..rngByte*rngBit) DO index: INT _ IF seq THEN ii MOD rngBit ELSE ii / rngByte; byte: INT _ IF seq THEN ii / rngBit ELSE ii MOD rngByte; 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; RETURN[PW.AbutListX[cells]]}; IFUMuxBytesRow: PUBLIC PROC [ -- Hack to go around compiler limitation design: CD.Design, top: LIST OF REF, ctl: List, in: LIST OF REF, -- Nesting order changed to Byte, Wd, Bit out: LIST OF REF, bot: LIST OF REF, seq: BOOL _ FALSE ] RETURNS [cell: PW.ObjName] = { cells: LIST OF PW.ObjName; byteIns: ARRAY [0..rngByte) OF LIST OF REF; byteInLengths: ARRAY [0..rngByte) OF INT _ ALL[0]; FOR byte: INT IN [0..rngByte) DO list: LIST OF REF; FOR bb: INT IN [0..byte) DO FOR list _ byteIns[bb], list.rest WHILE list#NIL DO byteIns[byte] _ CONS[NIL, byteIns[byte]]; byteInLengths[byte] _ byteInLengths[byte] + 1; ENDLOOP; ENDLOOP; FOR list _ NARROW[LISTIndexItem[in, byte]], list.rest WHILE list#NIL DO byteIns[byte] _ CONS[NIL, byteIns[byte]]; byteInLengths[byte] _ byteInLengths[byte] + 1; ENDLOOP; ENDLOOP; FOR byte: INT DECREASING IN [0..rngByte) DO THROUGH [byteInLengths[byte]..byteInLengths[rngByte-1]) DO byteIns[byte] _ CONS[NIL, byteIns[byte]]; ENDLOOP; ENDLOOP; FOR byte: INT IN [0..rngByte) DO list: LIST OF REF _ byteIns[byte]; byteIns[byte] _ NIL; FOR list _ list, list.rest WHILE list#NIL DO byteIns[byte] _ CONS[list.first, byteIns[byte]]; ENDLOOP; ENDLOOP; FOR ii: INT DECREASING IN [0..rngByte*rngBit) DO index: INT _ IF seq THEN ii MOD rngBit ELSE ii / rngByte; byte: INT _ IF seq THEN ii / rngBit ELSE ii MOD rngByte; cells _ CONS[ Mux[ design: design, ctl: ctl, in: ExpandList[index, 0, byteIns[byte]], top: ExpandList[byte, index, top], out: ExpandList[byte, index, out], bot: ExpandList[byte, index, bot]], cells]; ENDLOOP; RETURN[PW.AbutListX[cells]]}; Mux: PROC [ design: CD.Design, top: List, ctl: List, in: List, out: List, bot: List] RETURNS [PW.ObjName] = { pitch: Size = [mPitch, pBigPitch]; topTail: INT = 4; botTail: INT = 2; muxEvenDn: BOOL = TRUE; cell: CD.ObPtr _ CDCells.CreateEmptyCell[]; range: Size _ [MAX[ListLength[top],ListLength[bot]], ListLength[ctl]]; outN: PW.ROPE _ IF out=NIL THEN NIL ELSE out.first; iRect: CD.Rect; outIndex: INT _ ListItemIndexMin[top, outN]; outIndexBot: INT _ 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; <> FOR i: INT IN [0..range.x) DO size: Size _ [6, 0]; loc: Location _ [i*pitch.x, 0]; tIO: PW.ROPE _ ListIndexItem[top, i]; bIO: PW.ROPE _ ListIndexItem[bot, i]; tY: INT _ IF tIO=outN THEN ListNonNILIndexMin[in] ELSE ListItemIndexMin[in,tIO]; bY: INT _ IF bIO=outN THEN ListNonNILIndexMax[in] ELSE ListItemIndexMax[in,bIO]; tY _ tY + ((tY + (IF (tIO=outN)=muxEvenDn THEN 1 ELSE 2)) MOD 2); bY _ bY + ((bY + (IF (bIO=outN)=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: CMos.met, size: [6, (range.y-tY) * pitch.y + 8 + topTail ], loc: [i*pitch.x, tY * pitch.y - 10 ]]; IF bIO#NIL THEN AddRet[cell:cell, level: CMos.met, size: [6, bY * pitch.y + botTail ], loc: [i*pitch.x, 0 * pitch.y - 10 - botTail ]]; ENDLOOP; FOR i: INT IN [0..range.x) DO tName: PW.ROPE _ ListIndexItem[top, i]; bName: PW.ROPE _ ListIndexItem[bot, i]; size: Size _ [6, 6]; loc: Location _ [i*pitch.x, range.y*pitch.y-2+topTail-size.y]; IF tName #NIL THEN PutPin [cell, size, loc, CMos.met, tName]; IF bName #NIL THEN PutPin [cell, size, [loc.x, - 10 - botTail], CMos.met, bName]; ENDLOOP; <> FOR i: INT IN [0..range.y) DO cName: PW.ROPE _ ListIndexItem[ctl, i]; size: Size _ [cellWidth, 4]; loc: Location _ [-leftTail, i*pitch.y ]; AddRet[cell:cell, size:size, loc:loc, level:CMos.pol]; PutPin [cell, [4, 4], loc, CMos.pol, cName]; PutPin [cell, [4, 4], [cellWidth-leftTail-4, loc.y], CMos.pol, cName] ENDLOOP; <> FOR ctlIndex: INT IN [0..range.y) DO AddMux: PROC [index: Location] = { OPEN PWB: PWBasics; xstr: CD.ObPtr _ CMosTransistors.CreateTransistor[w: 8, l: 4, difLev: CMos.ndif]; ctct: CD.ObPtr _ CMosContacts.CreateDifCon[l: 8, difLev: CMos.ndif]; dif: CD.ObPtr _ CDRects.CreateRect[[(ABS[outIndex-index.x])*pitch.x+8, 8], CMos.ndif]; half: INT _ IF ((index.y MOD 2)=0)=muxEvenDn THEN pitch.y/2 ELSE -pitch.y/2; yloc: INT _ index.y*pitch.y-2; [] _ PWB.IncludeApplication[cell, dif, [MIN[outIndex, index.x]*pitch.x, yloc+half]]; [] _ PWB.IncludeApplication[cell, ctct, [ outIndex *pitch.x, yloc+half]]; [] _ PWB.IncludeApplication[cell, ctct, [ index.x *pitch.x, yloc-half]]; [] _ PWB.IncludeApplication[cell, xstr, [ index.x *pitch.x-4, yloc-2]]}; ioIndex: INT _ -1; ioItem: PW.ROPE _ ListIndexItem[in, ctlIndex]; IF ioItem = NIL THEN LOOP; IF ioIndex < 0 THEN ioIndex _ ListItemIndexMax[top, ioItem]; IF ioIndex < 0 THEN ioIndex _ ListItemIndexMax[bot, ioItem]; IF ioIndex < 0 THEN LOOP; AddMux[index: [ioIndex, ctlIndex]]; ENDLOOP; PWBasics.RepositionCell[design, cell]; iRect _ CD.InterestRect[cell]; IF outIndex=-1 AND bot=NIL OR ListAllNil[bot] THEN iRect.y1 _ iRect.y1-10-botTail; iRect.y2 _ iRect.y1 + range.y*pitch.y+botTail+8+topTail; CDCells.SetInterestRect[cell, iRect]; RETURN[PWBasics.NameFromObj[cell]]}; IFUDecoderRow: PUBLIC PROC [ design: CD.Design, top: LIST OF REF, ctl: List, -- nof names must be 2*nof significant bits - 1st is MSB TRUE val: REF ValArray, out: LIST OF REF, bot: LIST OF REF, seq: BOOL _ FALSE ] RETURNS [cell: PW.ObjName] = { cells: LIST OF PW.ObjName; FOR ii: INT DECREASING IN [0..rngByte*rngBit) DO index: INT _ IF seq THEN ii MOD rngBit ELSE ii / rngByte; byte: INT _ IF seq THEN ii / rngBit ELSE ii MOD rngByte; cells _ CONS[ Decoder[ design: design, ctl: ctl, val: val[byte][index], top: AddGV[ExpandList[byte, index, top]], out: ExpandList[byte, index, out], bot: AddGV[ExpandList[byte, index, bot]] ], cells]; ENDLOOP; RETURN[PW.AbutListX[cells]]}; Decoder: PROC [ design: CD.Design, top: List, ctl: List, val: INT, out: List, bot: List] RETURNS [PW.ObjName] = { pitch: Size = [mPitch, pBigPitch]; topTail: INT = 4; botTail: INT = 2; cell: CD.ObPtr _ CDCells.CreateEmptyCell[]; rangeY: INT _ ListLength[ctl]+1; outN: PW.ROPE _ IF out=NIL THEN NIL ELSE out.first; iRect: CD.Rect; <> FOR i: INT IN [0..nofVWires) DO size: Size _ [6, 0]; loc: Location _ [i*pitch.x, 0]; tIO: PW.ROPE _ ListIndexItem[top, i]; bIO: PW.ROPE _ ListIndexItem[bot, i]; tY: INT _ ListItemIndexMin[ctl,tIO] +1; bY: INT _ ListItemIndexMax[ctl,bIO] +1; IF tIO=outN THEN tY_0 ELSE IF tY=0 THEN tY_-1; IF bY=0 AND bIO#outN THEN bY_-1; 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: CMos.met, size: [6, (rangeY-tY) * pitch.y + 8 + topTail ], loc: [i*pitch.x, tY * pitch.y - 10 ]]; IF bIO#NIL THEN AddRet[cell:cell, level: CMos.met, size: [6, bY * pitch.y + botTail ], loc: [i*pitch.x, 0 * pitch.y - 10 - botTail ]]; ENDLOOP; FOR i: INT IN [0..nofVWires) DO tName: PW.ROPE _ ListIndexItem[top, i]; bName: PW.ROPE _ ListIndexItem[bot, i]; size: Size _ [6, 6]; loc: Location _ [i*pitch.x, rangeY*pitch.y-2+topTail-size.y]; IF tName #NIL THEN PutPin [cell, size, loc, CMos.met, tName]; IF bName #NIL THEN PutPin [cell, size, [loc.x, - 10 - botTail], CMos.met, bName]; ENDLOOP; <> FOR xIndex: INT IN [0..nofVWires-2) DO loc: Location _ [xIndex*pitch.x, 0 ]; IF Rope.Equal[outN, ListIndexItem[top, xIndex]] OR Rope.Equal[outN, ListIndexItem[bot, xIndex]] THEN { AddRet[cell:cell, size:[(nofVWires-2-xIndex)*pitch.x, 4], loc:loc, level:CMos.pol]; [] _ PWBasics.IncludeApplication[cell, CMosContacts.CreatePolyCon[l:8], loc] }; ENDLOOP; <> FOR cIndex: INT IN (0..rangeY) DO cName: PW.ROPE _ ListIndexItem[ctl, cIndex-1]; size: Size _ [cellWidth, 4]; loc: Location _ [-leftTail, cIndex*rangeY ]; AddRet[cell:cell, size:size, loc:loc, level:CMos.pol]; PutPin [cell, [4, 4], loc, CMos.pol, cName]; PutPin [cell, [4, 4], [cellWidth-leftTail-4, loc.y], CMos.pol, cName]; loc.y _ loc.y-2; FOR xIndex: INT IN [0..nofVWires-2) DO loc.x _ xIndex*pitch.x; IF Rope.Equal[cName, ListIndexItem[top, xIndex]] OR Rope.Equal[cName, ListIndexItem[bot, xIndex]] THEN [] _ PWBasics.IncludeApplication[cell, CMosContacts.CreatePolyCon[l:8], loc]; ENDLOOP; ENDLOOP; AddRet[cell:cell, level: CMos.met, size:[8, (rangeY-2)*pitch.y], loc: [154, 6]]; AddRet[cell:cell, level: CMos.met, size:[26, (rangeY-1)*pitch.y], loc: [170, 6]]; AddRet[cell:cell, level: CMos.nwel, size:[26, (rangeY+0)*pitch.y+6], loc: [142, -4]]; BEGIN -- Mux connections Put: PROC[obj: CD.ObPtr, loc: Location] = {[] _ PWBasics.IncludeApplication[cell, obj, loc]}; currIsXstr, lastIsXstr: BOOL _ FALSE; nXstr: CD.ObPtr _ CMosTransistors.CreateTransistor[w: 32, l: 4, difLev: CMos.ndif]; pXstr: CD.ObPtr _ CMosTransistors.CreateTransistor[w: 24, l: 4, difLev: CMos.pdif]; nCtct: CD.ObPtr _ CMosContacts.CreateDifCon[l: 8, difLev: CMos.ndif]; pCtct: CD.ObPtr _ CMosContacts.CreateDifCon[l: 8, difLev: CMos.pdif]; wCtct: CD.ObPtr _ CMosContacts.CreateDifShortCon[difLev: CMos.ndif]; nDif: CD.ObPtr _ CDRects.CreateRect[[32, 4], CMos.ndif]; pDif: CD.ObPtr _ CDRects.CreateRect[[24, 4], CMos.pdif]; met: CD.ObPtr _ CDRects.CreateRect[[8, 16], CMos.met]; FOR ctlIndex: INT IN (0..rangeY) DO yloc: INT _ ctlIndex*pitch.y-10; xloc: INT _ (nofVWires-2)*pitch.x; currIsXstr _ PW.XthBitOfN[(rangeY+1-ctlIndex)/2, val]; IF (ctlIndex MOD 2) =1 THEN currIsXstr _ NOT currIsXstr; IF NOT currIsXstr THEN { Put[met, [xloc+28, yloc ]]; IF lastIsXstr THEN Put[nCtct, [xloc+28, yloc ]] } ELSE { Put[nDif, [xloc+4, yloc+2 ]]; Put[nDif, [xloc+4, yloc+2+16]]; Put[nXstr, [xloc+4, yloc+4 ]]; IF NOT lastIsXstr THEN Put[nCtct, [xloc+28, yloc ]]; Put[pDif, [xloc+62, yloc+2 ]]; Put[pDif, [xloc+62, yloc+2+16]]; Put[pXstr, [xloc+62, yloc+4 ]]; Put[wCtct, [xloc+92, yloc +16]]; IF (ctlIndex MOD 2) =1 THEN { Put[pCtct, [xloc+62, yloc +16]]; Put[pCtct, [xloc+78, yloc ]] }; }; lastIsXstr _ currIsXstr; ENDLOOP; END; [] _ PWBasics.IncludeApplication[ cell: cell, subcell: PWBasics.ObjFromName[design, "DecoderTop"], location: [0,0]]; [] _ PWBasics.IncludeApplication[ cell: cell, subcell: PWBasics.ObjFromName[design, "DecoderBot"], location: [0,(rangeY-1)*pitch.y-2]]; PWBasics.RepositionCell[design, cell]; <> <> <> <> RETURN[PWBasics.NameFromObj[cell]]}; IFUMuxLatchRow: PUBLIC PROC [ design: CD.Design, enable: PW.ROPE, top: LIST OF REF, ctl: List, in: LIST OF REF, out: LIST OF REF, bot: LIST OF REF, seq: BOOL _ FALSE ] RETURNS [cell: PW.ObjName] = { cells: LIST OF PW.ObjName; FOR ii: INT DECREASING IN [0..rngByte*rngBit) DO index: INT _ IF seq THEN ii MOD rngBit ELSE ii / rngByte; byte: INT _ IF seq THEN ii / rngBit ELSE ii MOD rngByte; cells _ CONS[ MuxLatch[ design: design, ctl: ctl, in: ExpandList[byte, index, in], enable: enable, top: ExpandList[byte, index, top], out: ExpandList[byte, index, out], bot: ExpandList[byte, index, bot]], cells]; ENDLOOP; RETURN[PW.AbutListX[cells]]}; <<>> ioRestRef: List _ LIST["VDD", "GND"]; <<>> MuxLatch: PROC [ design: CD.Design, enable: PW.ROPE, top: List, ctl: List, in: List, out: List, bot: List] RETURNS [PW.ObjName] = { AddMux: PROC [index: Location] = { patch: CD.ObPtr _ CDRects.CreateRect[[8,8], CMos.ndif]; dif: CD.ObPtr _ CDRects.CreateRect[[(range.x+ioRestLength-index.x)*pitch.x,8], CMos.ndif]; xstr: CD.ObPtr _ CMosTransistors.CreateTransistor[w: 8, l: 4, difLev: CMos.ndif]; ctct: CD.ObPtr _ CMosContacts.CreateDifCon[l: 8, difLev: CMos.ndif]; half: INT _ IF (index.y MOD 2)=0 THEN pitch.y/2 ELSE -pitch.y/2; loc: Location _ [index.x*pitch.x, (mIBias+index.y)*pitch.y-2]; IF range.y=1 -- noMux Latch THEN [] _ PWBasics.IncludeApplication[cell, patch, [loc.x, loc.y]] ELSE [] _ PWBasics.IncludeApplication[cell, xstr, [loc.x-4, loc.y-2]]; [] _ PWBasics.IncludeApplication[cell, dif, [loc.x, loc.y+half]]; [] _ PWBasics.IncludeApplication[cell, ctct, [loc.x, loc.y-half]] }; pitch: Size = [mPitch, pBigPitch]; mIBias: INT = 5; oIBias: INT = 2; topTail: INT = 4; botTail: INT = 2; -- Need tails to prevend pins from appearing on two sides cell: CD.ObPtr _ CDCells.CreateEmptyCell[]; range: Size _ [MAX[ListLength[top],ListLength[bot]], ListLength[ctl]+mIBias]; ioRest: List _ ioRestRef; ioRestLength: CARDINAL _ ListLength[ioRest]; noMux: BOOL _ range.y=1; noIORest: BOOL _ FALSE; blank: BOOL _ in=NIL OR ListAllNil[in]; FOR ioRest _ ioRest, ioRest.rest WHILE ioRest#NIL DO -- are VDD or GND used IF ListItemIndexMax[in, ioRest.first]#-1 THEN EXIT ENDLOOP; IF ioRest#NIL THEN ioRest _ ioRestRef -- at least one is used so do regular case ELSE noIORest _ TRUE; IF noIORest THEN {ioRest _ NIL; ioRestLength_0}; -- noMux/noIORest latch <> FOR i: INT IN [0..range.x) DO size: Size _ [6, 0]; loc: Location _ [i*pitch.x, 0]; tIO: PW.ROPE _ ListIndexItem[top, i]; bIO: PW.ROPE _ ListIndexItem[bot, i]; bY: INT _ ListItemIndexMax[in, bIO]; tY: INT _ ListItemIndexMin[in, tIO]; bY _ IF bY#-1 THEN bY+mIBias ELSE IF ListItemIndexMax[out, bIO]#-1 THEN oIBias ELSE -1; tY _ IF ListItemIndexMin[out, tIO]#-1 THEN oIBias ELSE IF tY#-1 THEN tY+mIBias ELSE range.y+mIBias; IF tY >=mIBias THEN tY _ (tY -((tY +1-mIBias) MOD 2)); IF bY >=mIBias THEN bY _ (bY -((bY +1-mIBias) MOD 2)); IF Rope.Equal[tIO, bIO] THEN tY_bY_0 ELSE IF tY<=bY THEN ERROR Error[IO.PutFR ["2 signals (%g, %g) in same channel - ABORT", IO.rope[tIO], IO.rope[bIO]]]; size.y _ (range.y-tY) *pitch.y - pitch.y/2 + topTail; loc.y _ tY *pitch.y+6; IF tIO#NIL THEN AddRet[cell:cell, size:size, loc:loc, level: CMos.met]; size.y _ bY *pitch.y+6 + botTail; loc.y _ - botTail; IF bIO#NIL THEN AddRet[cell:cell, size:size, loc:loc, level: CMos.met]; ENDLOOP; <> IF NOT(noIORest OR blank) THEN FOR ix: INT IN [0..ioRestLength) DO bY: INT _ ListItemIndexMax[in, ListIndexItem[ioRest, ix]]; IF bY=-1 THEN LOOP; AddRet[ cell: cell, level: CMos.met, loc: [(range.x+ix) * pitch.x, mIBias * pitch.y - 2], size: [8, (bY+(bY MOD 2)) * pitch.y - pitch.y/2 + topTail]]; ENDLOOP; <> IF NOT(noMux OR blank) THEN { bY: INT _ range.y-mIBias-1; AddRet[ cell: cell, level: CMos.met, loc: [(range.x+ioRestLength) * pitch.x, (mIBias+1) * pitch.y-2], size: [8, (bY-(bY MOD 2)) * pitch.y]]}; <> FOR i: INT IN [0..range.x) DO tName: PW.ROPE _ ListIndexItem[top, i]; bName: PW.ROPE _ ListIndexItem[bot, i]; size: Size _ [6, 6]; loc: Location _ [i*pitch.x, range.y*pitch.y-2+topTail-size.y]; IF tName #NIL THEN PutPin [cell, size, loc, CMos.met, tName]; IF bName #NIL THEN PutPin [cell, size, [loc.x, -botTail], CMos.met, bName]; ENDLOOP; <> AddRet[cell:cell, size:[cellWidth, 8], loc:[-leftTail, 70], level: CMos.met2]; AddRet[cell:cell, size:[cellWidth,18], loc:[-leftTail, 42], level: CMos.met2]; AddRet[cell:cell, size:[cellWidth,20], loc:[-leftTail, 0], level: CMos.met2]; AddRet[cell:cell, size:[cellWidth, 4], loc:[-leftTail, 0], level: CMos.pol]; <> PutPin [cell, [4, 8], [-leftTail, 70], CMos.met2, "VBB"]; PutPin [cell, [4, 8], [cellWidth-leftTail-4, 70], CMos.met2, "VBB"]; PutPin [cell, [4,18], [-leftTail, 42], CMos.met2, "VDD"]; PutPin [cell, [4,18], [cellWidth-leftTail-4, 42], CMos.met2, "VDD"]; PutPin [cell, [4,20], [-leftTail, 0], CMos.met2, "GND"]; PutPin [cell, [4,20], [cellWidth-leftTail-4, 0], CMos.met2, "GND"]; PutPin [cell, [4, 4], [-leftTail, 0], CMos.pol, enable]; PutPin [cell, [4, 4], [cellWidth-leftTail-4, 0], CMos.pol, enable]; <> FOR i: INT IN [0..range.y-mIBias) DO cName: PW.ROPE _ ListIndexItem[ctl, i]; ctct: CD.ObPtr _ CMosContacts.CreateDifCon[l: 8, difLev: CMos.ndif]; size: Size _ [cellWidth, 4]; loc: Location _ [-leftTail, (mIBias+i)*pitch.y ]; IF NOT blank AND (i MOD 2)=0 THEN [] _ PWBasics.IncludeApplication [cell, ctct, [(range.x+ioRestLength)*pitch.x, loc.y+6]]; IF noMux THEN EXIT; -- noMux latch AddRet[cell:cell, size:size, loc:loc, level:CMos.pol]; <> IF cName #NIL THEN { PutPin [cell, [4, 4], loc, CMos.pol, cName]; PutPin [cell, [4, 4], [cellWidth-leftTail-4, loc.y], CMos.pol, cName]}; ENDLOOP; <> FOR ctlIndex: INT IN [0..range.y-mIBias) DO ioIndex: INT _ -1; ioItem: PW.ROPE _ ListIndexItem[in, ctlIndex]; IF ioItem = NIL THEN LOOP; IF ioIndex < 0 THEN ioIndex _ ListItemIndexMax[top, ioItem]; IF ioIndex < 0 THEN ioIndex _ ListItemIndexMax[bot, ioItem]; IF ioIndex < 0 THEN { ioIndex _ ListItemIndexMax[ioRest, ioItem]; IF ioIndex < 0 THEN LOOP; ioIndex _ ioIndex+range.x}; AddMux[index: [ioIndex, ctlIndex]]; ENDLOOP; <> IF NOT blank THEN FOR i: INT IN [0..range.x) DO IF ListItemIndexMax[out, ListIndexItem[top, i]]#-1 OR ListItemIndexMax[out, ListIndexItem[bot, i]]#-1 THEN { loc: Location _ [i*pitch.x, oIBias*pitch.y+4]; size: Size _ [(range.x-i+(IF noIORest THEN 0 ELSE 1))*pitch.x, 4]; [] _ PWBasics.IncludeApplication[cell, CMosContacts.CreatePolyCon[l: 8], loc]; AddRet[cell:cell, size:size, loc:[loc.x, loc.y+2], level:CMos.pol]}; ENDLOOP; <> IF ~blank THEN [] _ PWBasics.IncludeApplication[ cell: cell, subcell: PWBasics.ObjFromName[design, (IF noIORest THEN "SimLatch" ELSE "MuxLatch")], location: [range.x*pitch.x, 0]]; PWBasics.RepositionCell[design, cell]; RETURN[PWBasics.NameFromObj[cell]]}; <> <> <> <> <> <> <> <> MuxLatch6x7x6: PW.UserProc = { mux: PW.ObjName _ Mux[ design: design, top: LIST["XB", "Alpa", "Beta", "Pass", "Out", "In"], ctl: LIST["Reset", "Hold", "Set", "BSel", "ASel", "Adv", "RdXBus"], in: LIST["GND", "Last", "VDD", "Beta", "Alpa", "In", "XB"], out: LIST["Out"], bot: LIST["XB", "Alpa", "Beta", "Pass", "Out", "Last"] ]; latch: PW.ObjName _ Latch[ design: design, enable: "PhB", top: LIST["XB", "Alpa", "Beta", "Pass", "Out", "In"], in: LIST["GND", "Last", "VDD", "Beta", "Alpa", "In", "XB"], out: LIST["Out"], bot: LIST["XB", "Alpa", "Beta", "Pass", "Out", "Last"] ]; RETURN[ PW.AbutY[latch, mux] ]}; Mux6x6: PW.UserProc = { RETURN[ Mux[ design: design, top: LIST["XB", "Alpa", "Beta", "Pass", NIL, "In", "Out2"], ctl: LIST["Reset", "Hold", "Set", "BSel", "ASel", "Adv", "RdXBus"], in: LIST["XB", "Alpa", "Beta", "Pass", NIL, "Out2", "In"], out: LIST["Out"], bot: LIST["XB", "Alpa", "Beta", "Pass", "Out", NIL, "Out2"]] ]}; MuxBlank: PW.UserProc = { RETURN[ Mux[ design: design, top: NIL, ctl: LIST["Reset", "Hold", "Set", "BSel", "ASel", "Adv", "RdXBus"], in: NIL, out: NIL, bot: NIL ] ]}; <<>> <> <> <> <> <> <> <> <> <> PW.Register[MuxBlank, "MuxBlank"]; PW.Register[Mux6x6, "Mux6x6"]; END. <<>>