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["."];
Metal wires and their pins
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𡤋Y𡤀
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] = {
ptchOset: INT ← (xstrLgth+difW)/2; -- for gap between transistor and diff wire
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];
dPtch: CD.Object ← CDRects.CreateRect[[xstrWth, 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[dPtch, [index.x *pitch.x -cnctBiasx, yloc +dir*ptchOset -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<gnd)=(outIndex<gnd));
IF ((ctlIndex
MOD 2)=0)=muxEvenDn
THEN {IF thsIONotGnd AND lstIONotGnd THEN AddGndContact[dn]}
ELSE {IF thsGndClear AND lstGndClear THEN AddGndContact[dn]};
IF (ctlIndex+1) = range.y
THEN
IF ((ctlIndex
MOD 2)=0)=muxEvenDn
THEN {IF thsGndClear THEN AddGndContact[up]}
ELSE {IF thsIONotGnd THEN AddGndContact[up]};
lstIONotGnd ← thsIONotGnd;
lstGndClear ← thsGndClear}
ELSE AddGndContact[dn];
ENDLOOP;
END;
PW.IncludeInDirectory[design, cell];
iRect ← CD.InterestRect[cell];
IF outIndex=-1 AND bot=NIL OR ListAllNil[bot] THEN iRect.y1 ← iRect.y1 - botExtra;
iRect.y2 ← iRect.y1 + range.y*pitch.y + topExtra + botExtra;
CDCells.SetInterestRect[cell, iRect];
PW.RenameObject[design, cell, cellName];
RETURN[cell]};
Decoder: PROC [
design: CD.Design,
top: List,
ctl: List,
val: INT,
out: List,
bot: List]
RETURNS [cell: CD.Object] = {
pitch: Size = [metPitch, met2Pitch];
xtraY: INT = (pitch.y-polW-difW)/2;
rangeY: INT ← ListLength[ctl]+1;
outN: PW.ROPE ← IF out=NIL THEN NIL ELSE out.first;
cell ← CDCells.CreateEmptyCell[];
top ← FixGVInList[top];
bot ← FixGVInList[bot];
Metal wires and their pins
FOR i: INT IN [0..nofVWires) DO
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𡤀 ELSE IF tY=0 THEN tY←-1;
IF bY=0 AND bIO#outN THEN bY←-1;
IF tY=-1 AND bY=-1 THEN tY𡤋Y𡤀
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, (rangeY-tY) * pitch.y + polW/2+met2W/2+topTail ],
loc: [i*pitch.x, tY * pitch.y ]];
IF bIO#NIL THEN AddRet[cell:cell, level: cmosMet,
size: [metW, bY * pitch.y + botTail ],
loc: [i*pitch.x, 0 * pitch.y - botTail ]];
ENDLOOP;
AddMetalPins
[cell, top, bot, -leftTail, rangeY*pitch.y+polW/2+met2W/2+topTail, -botTail, TRUE];
All the rest
BEGIN
Put: PROC[obj: CD.Object, location: Location] =
{[] ← PW.IncludeInCell[cell, obj, location]};
colGND: INT = (nofVWires-2) *pitch.x;
colLt: INT = colGND +2 *pitch.x;
colPCnt: INT = colLt +1 *pitch.x;
colRt: INT = colPCnt +2*(4+5+3);
colVDD: INT = colRt +1 *pitch.x;
colWCnt: INT = colVDD +1 *pitch.x;
currIsXstr, lastIsXstr: BOOL ← FALSE;
nXstr: CD.Object ← TransistorObject[size: [32,4], difLayer: cmosNDif];
pXstr: CD.Object ← TransistorObject[size: [32,4], difLayer: cmosPDif];
nCtct: CD.Object ← CDSimpleRules.Contact[cmosMet, cmosNDif];
pCtct: CD.Object ← CDSimpleRules.Contact[cmosMet, cmosPDif];
wCtct: CD.Object ← CDSimpleRules.Contact[cmosMet, cmosWNDif];
polCtct: CD.Object ← CDSimpleRules.Contact[cmosMet, cmosPoly];
viaCtct: CD.Object ← CDSimpleRules.Contact[cmosMet, cmosMet2];
pol: CD.Object ← CDRects.CreateRect[[colRt-colLt, 4], cmosPoly];
nDif: CD.Object ← CDRects.CreateRect[[32, 4], cmosNDif];
pDif: CD.Object ← CDRects.CreateRect[[22, 4], cmosPDif];
met: CD.Object ← CDRects.CreateRect[[8, pitch.y], cmosMet];
AddRet[cell, [8, (rangeY-1)*pitch.y-2], [colRt, -2], cmosMet];
AddRet[cell, [1*pitch.x+8, (rangeY-0)*pitch.y], [colVDD, -3], cmosMet];
AddRet[cell, [2*pitch.x+8+10, (rangeY+0)*pitch.y+10], [colRt-10, -3], cmosNWell];
Out poly wire
IF outN#NIL THEN {
ioIndex: INT ← -1;
IF ioIndex < 0 THEN ioIndex ← ListItemIndexMin[top, outN];
IF ioIndex < 0 THEN ioIndex ← ListItemIndexMin[bot, outN];
IF ioIndex >= 0 THEN {
loc: Location ← [ioIndex*pitch.x, 0 ];
AddRet[cell:cell, size:[colRt-loc.x, polW], loc:loc, level:cmosPoly];
Put[polCtct, [loc.x, loc.y-2 ]] } };
FOR ctlIndex: INT IN [0..rangeY] DO
ycen: INT ← ctlIndex*pitch.y+polW/2;
ylow: INT ← ctlIndex*pitch.y-xtraY-difW;
cName: PW.ROPE ← SELECT ctlIndex FROM
0 => VDD,
rangeY => GND,
ENDCASE => ListIndexItem[ctl, ctlIndex-1];
ioIndex: INT ← -1;
size: Size ← [cellWidth, met2W];
loc: Location ← [-leftTail, ctlIndex*pitch.y+polW/2-met2W/2];
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 cName = NIL THEN LOOP;
IF ioIndex < 0 THEN ioIndex ← ListItemIndexMin[top, cName];
IF ioIndex < 0 THEN ioIndex ← ListItemIndexMin[bot, cName];
IF ioIndex >= 0 THEN Put[viaCtct, [ioIndex*pitch.x-2, loc.y-1]];
SELECT ctlIndex FROM
0 => {
AddRet[cell:cell, size:[8,6], loc:[colLt, ycen], level:cmosMet];
AddRet[cell:cell, size:[8,6], loc:[colRt, ycen], level:cmosMet];
Put[polCtct, [colLt, ycen - 8/2 ]];
Put[polCtct, [colRt, ycen - 8/2 ]];
Put[viaCtct, [colVDD, ycen - 10/2 ]];
LOOP};
rangeY => {
Put[viaCtct, [colLt-1, ycen - 10/2 ]];
Put[wCtct, [colWCnt, ylow ]];
IF lastIsXstr
THEN Put[nCtct, [colLt, ylow ]]
ELSE Put[met, [colLt, ylow ]];
LOOP};
ENDCASE;
currIsXstr ← PW.XthBitOfN[(rangeY-1-ctlIndex)/2, val];
IF (ctlIndex MOD 2) = 0 THEN currIsXstr ← NOT currIsXstr;
IF NOT currIsXstr
THEN {
Put[met, [colLt, ylow ]];
Put[wCtct, [colWCnt, ylow ]];
IF lastIsXstr THEN
Put[nCtct, [colLt, ylow ]] }
ELSE {
Put[pol, [colLt, ycen - polW/2 ]];
Put[polCtct, [colPCnt, ycen - 8/2 ]];
Put[viaCtct, [colPCnt+8, ycen - 10/2 ]];
Put[nDif, [colGND+4, ycen - pitch.y/2 ]];
Put[nDif, [colGND+4, ycen + pitch.y/2-4 ]];
Put[nXstr, [colGND, ycen - 6 ]];
IF NOT lastIsXstr THEN
Put[nCtct, [colLt, ylow ]];
Put[pDif, [colRt, ycen - pitch.y/2 ]];
Put[pDif, [colRt, ycen + pitch.y/2-4 ]];
Put[pXstr, [colRt-4, ycen - 6 ]];
Put[wCtct, [colWCnt, ylow ]];
IF (ctlIndex MOD 2) =1
THEN {
Put[pCtct, [colRt, ylow + pitch.y ]];
Put[pCtct, [colVDD, ylow ]] }
ELSE {
Put[pCtct, [colRt, ylow ]];
Put[pCtct, [colVDD, ylow + pitch.y ]] };
};
lastIsXstr ← currIsXstr;
ENDLOOP;
END;
PW.IncludeInDirectory[design, cell];
RETURN[cell]};
MuxTest: IFUPW.UserProc = { RETURN[ Mux[
design: design,
top: LIST["XB", "Alpha", "Beta", "Pass", NIL, "In1"],
ctl: LIST["RdXBus", "Hold", "Clear", "Set", "Set1", "Set2"],
in: LIST["XB", "Alpha", GND, VDD, "In1", "In2"],
out: LIST["Out2"],
bot: LIST["XB", "Alpha", "Beta", "Pass", "Out2", NIL, GND, VDD, "In2"] ] ]};
MuxTest: IFUPW.UserProc = { RETURN[ Mux[
design: design,
top: LIST["XBus.37", NIL, NIL, NIL, NIL, NIL, "GND", "VDD", NIL, NIL, NIL, NIL, NIL],
ctl: LIST["ARtOSetB", "ARtAlpB", "ARtAlp03B", "ARtAlp47B",
"ARtOp47B", "ARtBetB", "ARtBet03B", "ARtBet47B",
"BRtOSetB", "BRtAlpB", "BRtAlp03B", "BRtAlp47B",
"BRtOp47B", "BRtBetB", "BRtBet03B", "BRtBet47B",
"CRtOSetB", "CRtAlpB", "CRtAlp03B", "CRtAlp47B",
"CRtOp47B", "CRtBetB", "CRtBet03B", "CRtBet47B"],
in: LIST[NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL],
out: LIST[NIL],
bot: LIST["XBus.37", NIL, NIL] ] ]};