IFUCoreDataMuxImpl:
CEDAR
PROGRAM
IMPORTS CCDUtils, CD, CDBasics, CDCells, CDRects, CDSatellites, CDTexts, CoreCreate, CoreFrame, CoreLibrary, CoreName, CoreOps, CoreWire, CoreXform, IFUCoreCells, IFUCoreData, CoreInstCell, IO, Lists, Rope =
BEGIN OPEN CCDUtils;
ROPE: TYPE = Core.ROPE;
VDD: ROPE ← CoreName.RopeNm["VDD"];
GND: ROPE ← CoreName.RopeNm["GND"];
nil: ROPE ← CoreName.RopeNm["nil"];
Signal: SIGNAL = CODE;
ExpandDataMuxFrameSoft: CoreFrame.ExpandProc = {
-- frameCT
nil: ROPE ← CoreName.RopeNm["nil"];
data: IFUCoreData.DpCellData ← NARROW[frameCT.data];
xform: CoreXform.Xform ← CoreXform.GetXform[data.type];
domain: NAT ← CoreXform.XformSize[xform];
rowPub: CoreWire.CWire ← [frameCT.public];
rowPwr: CoreWire.CWire ← rowPub.f["pwr"];
rowIn: CoreWire.CWire ← rowPub.f["in"];
rowOut: CoreWire.CWire ← rowPub.f["out"];
rowLeft: CoreWire.CWire ← rowPub.f["left"];
rowRight: CoreWire.CWire ← rowPub.f["right"];
rowTop: CoreWire.CWire ← rowPub.f["top"];
rowBot: CoreWire.CWire ← rowPub.f["bot"];
rowCtl: CoreWire.CWire ← IF rowLeft.w.size#0 THEN rowLeft ELSE rowRight;
frame: REF CoreFrame.FrameRec ← NEW[CoreFrame.FrameRec ← [first: left]];
frame.seq ← NEW[CoreFrame.FrameSeq[domain]];
FOR ii:
INT
DECREASING
IN [0..domain)
DO
bitPub: Core.Wires ← NIL;
blank: BOOL ← rowOut.i[0].x[ii].n[]=nil;
mux: Core.CellType ← NIL;
instances: CoreClasses.CellInstances ← NIL;
ctx: CoreName.Context ← CoreName.NewContext[];
out: CoreWire.CWire ← rowOut.i[0].x[ii];
FOR index:
INT
IN [0..rowPwr.w.size)
DO
bitPub ← CONS[ CoreName.CtxCopyWire[ctx, rowPwr.i[index].w], bitPub];
ENDLOOP;
IF
NOT blank
THEN {
bitPub ← CONS[ CoreName.CtxCopyWire[ctx, out.w], bitPub];
FOR index:
INT
IN [0..rowCtl.w.size)
DO
ctl: CoreWire.CWire ← rowCtl.i[index].x[ii];
in: CoreWire.CWire ← rowIn.i[index].x[ii];
instance: CoreClasses.CellInstance ← CoreCreate.Instance[
CoreCreate.Transistor[ ],
["gate", ctl.w ],
["ch1", in.w ],
["ch2", out.w ] ];
instances ← CONS[ instance, instances];
bitPub ← CONS[ CoreName.CtxCopyWire[ctx, ctl.w], bitPub];
bitPub ← CONS[ CoreName.CtxCopyWire[ctx, in.w], bitPub];
ENDLOOP };
mux ← CoreCreate.Cell[
public: CoreOps.CreateWire[bitPub],
onlyInternal: NIL,
instances: instances,
name: NIL,
props: NIL];
frame.seq[ii] ← CoreFrame.NewFrameCell[0, NIL, [first: left, cell: mux]];
ctx ← CoreName.KillContext[ctx];
ENDLOOP;
frameCT.class ← CoreFrame.frameCellClass;
frameCT.data ← frame;
CoreFrame.SetFrameExpandProc[soft, frameCT, NIL]};
ExpandDataMuxFrameHard: CoreFrame.ExpandProc = {
-- frameCT
data: IFUCoreData.DpCellData ← NARROW[frameCT.data];
xform: CoreXform.Xform ← CoreXform.GetXform[data.type];
domain: NAT ← CoreXform.XformSize[xform];
rowPub: CoreWire.CWire ← [frameCT.public];
rowPwr: CoreWire.CWire ← rowPub.f["pwr"];
rowIn: CoreWire.CWire ← rowPub.f["in"];
rowOut: CoreWire.CWire ← rowPub.f["out"];
rowLeft: CoreWire.CWire ← rowPub.f["left"];
rowRight: CoreWire.CWire ← rowPub.f["right"];
rowTop: CoreWire.CWire ← rowPub.f["top"];
rowBot: CoreWire.CWire ← rowPub.f["bot"];
rowCtl: CoreWire.CWire ← IF rowLeft.w.size#0 THEN rowLeft ELSE rowRight;
frame: REF CoreFrame.FrameRec ← NEW[CoreFrame.FrameRec ← [first: left]];
frame.seq ← NEW[CoreFrame.FrameSeq[domain]];
FOR ii:
INT
DECREASING
IN [0..domain)
DO
renameProc: CoreInstCell.RenameProc ~
{new ← code.Decode[letter: old]; IF new=NIL THEN Signal[]; RETURN[new]};
mux: Core.CellType;
code: IFUCoreData.NameLetterCode ← IFUCoreData.CreateNameLetterCode
["Mux", LIST[rowTop, rowCtl, rowIn, rowOut, rowBot], ii];
generic: Core.CellType ← CoreLibrary.Get[IFUCoreCells.library, code.name];
IF generic=
NIL
THEN {
GenList:
PROC[cwire: CoreWire.CWire]
RETURNS[list:
LIST
OF
ROPE ] = {
FOR index:
INT
DECREASING
IN [0..cwire.w.size)
DO
letter: ROPE ← NIL;
name: ROPE ← cwire.i[index].x[ii].n;
IF name#NIL THEN letter ← code.Encode[name];
list ← CONS[letter, list] ENDLOOP};
obj:
CD.Object ← Mux[
channels: data.channels,
top: GenList[rowTop ],
ctl: GenList[rowCtl ],
in: GenList[rowIn ],
out: GenList[rowOut ],
bot: GenList[rowBot ] ];
generic ← CoreLibrary.ObjCell[obj, code.name];
CoreLibrary.Set[IFUCoreCells.library, code.name, generic]};
mux ← CoreInstCell.SpecificGeneric[generic, renameProc];
frame.seq[ii] ← CoreFrame.NewFrameCell[0, NIL, [first: left, cell: mux]];
ENDLOOP;
frameCT.class ← CoreFrame.frameCellClass;
frameCT.data ← frame;
frame.cell ← CoreFrame.RecastFrameHard[frameCT];
IFUCoreData.BlockSides[frame.cell, [frameCT.public]];
frame.seq ← NEW[CoreFrame.FrameSeq[0]]; -- free the children
CoreFrame.SetFrameExpandProc[hard, frameCT, NIL]};
textScale: INT ← 2;
font: CDTexts.CDFont ← CDTexts.MakeFont["Xerox/TiogaFonts/Helvetica7", textScale];
dwText: CD.Object ← CDTexts.Create["driveWeak", font];
Mux:
PROC [
channels: INT,
top: LIST OF ROPE,
ctl: LIST OF ROPE,
in: LIST OF ROPE,
out: LIST OF ROPE,
bot:
LIST
OF
ROPE]
RETURNS [cell: CD.Object] = {
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: CD.Position = [metPitch, met2Pitch];
muxEvenDn: BOOL = TRUE;
range: CD.Position;
outN: ROPE ← IF out=NIL THEN NIL ELSE out.first;
iRect: CD.Rect;
vdd: INT ← channels+1;
gnd: INT ← channels;
cellWidth: INT ← IFUCoreData.CellWidth[channels];
cnctBiasx: INT ← (cnctSize-metW)/2;
outIndex, outIndexBot: INT;
top ← FixGVCharInList[channels, top];
bot ← FixGVCharInList[channels, bot];
range ← [MAX[Lists.ListLength[top],Lists.ListLength[bot]], Lists.ListLength[ctl]];
outIndex ← Lists.ListItemIndexMin[top, outN];
outIndexBot ← Lists.ListItemIndexMin[bot, outN];
IF outIndex # Lists.ListItemIndexMax[top, outN]
OR
outIndexBot # Lists.ListItemIndexMax[bot, outN] OR
(outIndex#-1
AND outIndexBot#-1
AND outIndex#outIndexBot)
THEN {
log.PutF["Multiple column output %g- ABORT", IO.rope[outN]];
Signal[]};
IF outIndex = -1 THEN outIndex ← outIndexBot;
log.PutRope["."];
Metal wires and their pins
cell ← CDCells.CreateEmptyCell[];
IF outN#
NIL
AND Lists.ListItemIndexMax[top, outN]=-1
AND Lists.ListItemIndexMax[bot, outN]=-1
THEN {
log.PutF["\n Output signal (%g) is not in either top or bot lists - ABORT",
IO.rope[outN]];
Signal[]};
IF outN#
NIL
AND Lists.ListItemIndexMax[in, outN]#-1
THEN{
log.PutF["\n Output signal (%g) is also used as input - ABORT", IO.rope[outN]];
Signal[]};
FOR i:
INT
IN [0..range.x)
DO
loc: CD.Position ← [i*pitch.x, 0];
tIO: ROPE ← Lists.ListIndexItem[top, i];
bIO: ROPE ← Lists.ListIndexItem[bot, i];
topOut: BOOL ← Rope.Equal[tIO,outN];
botOut: BOOL ← Rope.Equal[bIO,outN];
tY: INT ← IF topOut THEN Lists.ListNonNILIndexMin[in] ELSE Lists.ListItemIndexMin[in,tIO];
bY: INT ← IF botOut THEN Lists.ListNonNILIndexMax[in] ELSE Lists.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 {
log.PutF["\n 2 signals (%g, %g) in same channel - ABORT",
IO.rope[tIO], IO.rope[bIO]];
Signal[]};
IF tIO#
NIL
THEN CCDUtils.AddRet[cell:cell, level: cmosMet,
size: [metW, (range.y-tY) * pitch.y + topExtra ],
loc: [i*pitch.x, tY * pitch.y ]];
IF bIO#
NIL
THEN CCDUtils.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 CCDUtils.AddRet[cell: cell, level: cmosMet,
size: [pwrW, range.y * pitch.y + topExtra + botExtra ],
loc: [vgIndex*pitch.x-pFrng, - botExtra ]] ENDLOOP;
AddMetalPins
[cell, top, bot, 0, range.y*pitch.y+ topExtra, - botExtra, TRUE];
BEGIN
xstr: CD.Object ← TransistorObject[size: [xstrWth, xstrLgth], difLayer: cmosNDif];
dcon: CD.Object ← Contact[cmosNDif];
pcon: CD.Object ← Contact[cmosPoly];
vcon: CD.Object ← Contact[cmosMet2];
scon: CD.Object ← Contact[cmosPWCont];
pvconn: CD.Object ← CDRects.CreateRect[[2*cnctSize, cnctSize], cmosMet];
lstIONotGnd: BOOL ← TRUE;
lstGndClear: BOOL ← TRUE;
thsIONotGnd: BOOL ← TRUE;
thsGndClear: BOOL ← TRUE;
FOR ctlIndex:
INT
IN [0..range.y)
DO
Include:
PROC[object:
CD.Object, location:
CD.Position] =
{[] ← 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:
CD.Position] = {
inst0, inst1: CD.Instance;
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[pvconn, [range.x *pitch.x -cnctBiasx, yloc -cnctSize/2 ]];
Include[vcon, [range.x *pitch.x -cnctBiasx+cnctSize+lambda, 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 ]];
inst0 ← IncludeInCell[cell, xstr,
[index.x *pitch.x -tranBiasx, yloc -xstrLgth/2 ]];
inst1 ← IncludeInCell[cell, dwText,
[index.x *pitch.x -tranBiasx, yloc -lambda*textScale/2 ]];
CDSatellites.Associate[inst0, inst1]};
cName: ROPE ← Lists.ListIndexItem[ctl, ctlIndex];
size: CD.Position ← [cellWidth, met2W];
loc: CD.Position ← [metW/2-leftTail, ctlIndex*pitch.y+pitch.y/2-met2W/2];
ioIndex: INT ← -1;
CCDUtils.AddRet[cell:cell, size:size, loc:loc, level: cmosMet2];
CCDUtils.PutPin [cell, [met2W, met2W], loc,
cmosMet2, cName];
CCDUtils.PutPin [cell, [met2W, met2W], [metW/2-leftTail+cellWidth-met2W, loc.y],
cmosMet2, cName];
IF outN#
NIL
THEN {
ioItem: ROPE ← Lists.ListIndexItem[in, ctlIndex];
IF ioItem #
NIL
THEN {
IF ioIndex < 0 THEN ioIndex ← Lists.ListItemIndexMax[top, ioItem];
IF ioIndex < 0 THEN ioIndex ← Lists.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;
iRect ← CD.InterestRect[cell];
IF outIndex=-1 AND bot=NIL OR Lists.ListAllNil[bot] THEN iRect.y1 ← iRect.y1 - botExtra;
iRect.y2 ← iRect.y1 + range.y*pitch.y + topExtra + botExtra;
CDCells.SetInterestRect[NIL, cell, iRect];
[ ] ← CDCells.ResizeCell[NIL, cell];
RETURN[cell]};
AddMetalPins:
PUBLIC
PROC
[cell: CD.Object, top, bot: LIST OF ROPE, refX, topY, botY: INT, realNames: BOOL] = {
length: INT ← MAX[Lists.ListLength[top], Lists.ListLength[bot]];
FOR i:
INT
IN [0..length)
DO
tName: ROPE ← Lists.ListIndexItem[top, i];
bName: ROPE ← Lists.ListIndexItem[bot, i];
size: CD.Position ← [metW, metW];
loc: CD.Position ← [refX+i*metPitch, topY-size.y];
IF tName #
NIL
THEN CCDUtils.PutPin [cell, size, loc, cmosMet,
(IF realNames THEN tName ELSE NIL)];
IF bName #
NIL
THEN CCDUtils.PutPin [cell, size, [loc.x, botY], cmosMet,
(IF realNames THEN bName ELSE NIL)];
ENDLOOP};
IncludeInCell:
PROC [cell: CD.Object, obj: CD.Object, position:
CD.Position ← [0, 0], orientation:
CD.Orientation ← original]
RETURNS [newInst: CD.Instance] =
INLINE {newInst ← CDCells.IncludeOb[design:
NIL, cell: cell, ob: obj, trans: [CDBasics.SubPoints[position, CDBasics.BaseOfRect[CDBasics.MapRect[
CD.InterestRect[obj], [[0, 0], orientation]]]], orientation], mode: dontResize].newInst};
FixGVCharInList:
PROC [chans:
INT, list:
LIST
OF
ROPE]
RETURNS[new: LIST OF ROPE] =
{RETURN[AddGVCharToList[chans, DelGVFromList[list]]]};
DelGVFromList:
PROC [list:
LIST
OF
ROPE]
RETURNS[new:
LIST
OF
ROPE] = {
nonNilItemAdded: BOOL ← FALSE;
IF list=NIL THEN RETURN[NIL];
FOR ii:
INT
DECREASING
IN [0..Lists.ListLength[list])
DO
item: ROPE ← Lists.ListIndexItem[list, ii];
item ← SELECT item FROM GND, VDD, plus, minus => NIL, ENDCASE => item;
IF item=NIL AND NOT nonNilItemAdded THEN LOOP;
nonNilItemAdded ← TRUE;
new ← CONS[item, new] ENDLOOP};
AddGVCharToList:
PROC [chans:
INT, list:
LIST
OF
ROPE]
RETURNS[new: LIST OF ROPE] = {
FOR ii:
INT
DECREASING
IN [0..
MAX[chans+2, Lists.ListLength[list]])
DO
item: ROPE ← Lists.ListIndexItem[list, ii];
IF ii=chans+1 THEN item ← plus;
IF ii=chans THEN item ← minus;
new ← CONS[item, new] ENDLOOP};
plus: ROPE ← CoreName.RopeNm["+"];
minus: ROPE ← CoreName.RopeNm["-"];
log: IO.STREAM ← CoreFrame.GetLog[];
IFUCoreData.RegisterSubClassExpand [soft, "Mux", ExpandDataMuxFrameSoft];
IFUCoreData.RegisterSubClassExpand [hard, "Mux", ExpandDataMuxFrameHard];
END.