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. 8IFUPWLatch.mesa, Copyright c 1985 by Xerox Corporation. All rights reserved. RemoveButton CD; CreateButton L Compile Latch; Run Latch Last Edited by Curry, April 12, 1985 8:54:55 am PST Metal wires Insert Metal Pins Enables and power Wires Insert Enable and power Pins Poly connections Cell Metal wires and their pins Poly wires and their pins Mux connections Metal wires and their pins Out poly wire Ctl Poly wires and their pins 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]; Primary Metal wires IORest metal wires Collection node metal wire Insert Metal Pins Enable and power Wires Insert Enable and power Pins Poly wires and latch input node contacts Insert Pins Mux connections Ouput connections Latch Cell MuxLatch6x6x6: PW.UserProc = { RETURN[ MuxLatch[ design: design, enable: "PhB", top: LIST["XB", "Alpa", "Beta", "Pass", "Out", "In"], ctl: LIST["Reset", "Hold", "Set", "ASel", "Adv", "RdXBus"], in: LIST["GND", "Last", "VDD", "Alpa", "In", "XB"], out: LIST["Out"], bot: LIST["XB", "Alpa", "Beta", "Pass", "Out", "Last"]] ]}; PW.Register[MuxLatch6x6x6, "Latch6x6x6"]; PW.Register[MuxLatch6x7x6, "Latch6x7x6"]; PW.Register[Latch6x6, "Latch6x6"]; PW.Register[IFULatchRowTest, "IFULatchRowTest"]; PW.Register[IFULatchRows, "IFULatchRows"]; PW.Register[Latch0, "Latch0"]; PW.Register[Latch1, "Latch1"]; PW.Register[Latch2, "Latch2"]; PW.Register[Latch3, "Latch3"]; Ê9˜šÐbl™Jšœ<™˜>JšœE˜E—Jš¡™šžœžœžœž˜Jšœ!˜!Jšœžœžœ˜%Jšœžœžœ˜%Jšœ˜š žœžœžœžœžœ˜@šžœ˜šœ ˜ Jšœ;˜;—JšœO˜O——Jšœ˜š žœžœžœžœžœ˜Cšžœ˜šœ ˜ Jšœ:˜:—JšœQ˜Q——Jšžœ˜—Jš¡™˜Jšœ+˜+šœ!˜!Jšœ ˜ Jšœ1˜1Jšœ˜——Jšœ&˜&Jšžœ˜$—J˜J˜šŸ œžœžœ˜Jšœžœ˜Jšœžœžœžœ˜Jšœ ˜ Jšœžœžœžœ˜Jšœžœžœžœ˜Jšœžœžœžœ˜šœžœžœ˜Jšžœžœ ˜—Jšœžœžœžœ ˜š žœžœž œžœž˜0Jš œžœžœžœžœžœ˜9Jš œžœžœžœ žœžœ ˜8šœžœ˜Jšœ˜Jšœ ˜ Jšœ"˜"Jšœ#˜#Jšœ#˜#Jšœ,˜,—Jšžœ˜—Jšžœžœ˜J˜—šŸœžœžœ+˜FJšœžœ˜Jšœžœžœžœ˜Jšœ ˜ Jšœžœžœžœ¢)˜˜>Jšžœžœžœ1˜CJšžœžœžœ?˜QJšžœ˜—Jš¡™šžœžœžœž˜Jšœžœžœ˜'Jšœ˜Jšœ(˜(Jšœ6˜6Jšœ3˜3JšœE˜EJšžœ˜—Jš¡™šžœ žœžœž˜$šŸœžœ˜"Jšžœžœ ˜JšœžœI˜QJšœžœ<˜DJšœžœžœ.˜VJš œžœžœ žœžœ žœ ˜LJšœžœ˜Jšœžœ žœ*˜UJšœžœH˜PJšœžœE˜MJšœžœD˜L—Jšœ žœ˜Jšœžœžœ˜.Jšžœ žœžœžœ˜Jšžœ žœ)˜˜>šžœ ¢˜Jšžœ?˜CJšžœC˜G—JšœB˜BJšœE˜E—Jšœ#˜#Jšœžœ˜Jšœžœ˜Jšœ žœ˜Jšœ žœ¢9˜KJšœžœ$˜-Jšœžœ;˜NJšœ˜Jšœžœ˜,Jšœ žœ ˜Jšœ žœžœ˜Jšœ žœžœžœ˜*š žœžœžœžœ¢˜KJšžœ'žœžœžœ˜;—šžœž˜ Jšžœ¢*˜BJšžœ žœ˜—Jšžœ žœ žœ¢˜HJ˜Jš ™šžœžœžœž˜Jšœ˜Jšœ˜Jšœžœžœ˜%Jšœžœžœ˜%Jšœžœ˜$Jšœžœ˜%šœžœ˜ Jš žœ žœžœžœžœ˜I—šœžœ˜%Jš žœžœžœžœ žœ˜=—Jšžœ žœžœ˜6Jšžœ žœžœ˜6šžœ˜Jšžœ˜ š žœžœžœžœžœ˜(Jšœ/žœ žœ ˜L——Jšœ5˜5Jšœ!˜!Jšžœžœžœ8˜GJšœ!˜!Jšœ˜Jšžœžœžœ8˜GJšžœ˜—Jš ™šžœžœ žœž˜šžœžœžœž˜#Jšœžœ3˜:Jšžœžœžœ˜šœ$˜$Jšœ7˜7Jšœžœ'˜B—Jšžœ˜——Jš ™šžœžœžœžœ˜Jšœžœ˜šœ$˜$Jšœ@˜@Jšœžœ˜/—J˜—Jš¡™šžœžœžœž˜Jšœžœžœ˜'Jšœžœžœ˜'Jšœ˜Jšœ>˜>Jšžœžœžœ.˜@Jšžœžœžœ9˜KJšžœ˜—š¡™JšœO˜OJšœO˜OJšœN˜NJšœM˜M—š¡™Jšœ=˜=JšœD˜DJšœ=˜=JšœD˜DJšœ=˜=JšœD˜DJšœ>˜>JšœE˜E—Jš¡(™(šžœžœžœž˜$Jšœžœžœ˜'Jšœžœ<˜DJšœ!˜!Jšœ1˜1š žœžœžœžœžœ!˜BJšœ8˜8—Jšžœžœžœ¢˜"Jšœ6˜6Jš¡ ™ šžœžœžœ˜Jšœ3˜3JšœG˜G—Jšžœ˜—Jš¡™šžœ žœžœž˜+Jšœ žœ˜Jšœžœžœ˜.Jšžœ žœžœžœ˜Jšžœ žœ)˜