DIRECTORY CD, CDRects, CDSatellites, CDSimpleRules, CDTexts, CMosB, CMosBObjects, Core, CoreClasses, CoreGeometry, CoreOps, CoreProperties, CoreRoute, DataPath, IO, PW, PWCore, Rope, Sisyph, TerminalIO; DataPathMuxVPwr: CEDAR PROGRAM IMPORTS CDRects, CDSatellites, CDSimpleRules, CDTexts, CMosB, CMosBObjects, CoreGeometry, CoreOps, CoreProperties, CoreRoute, DataPath, IO, PW, PWCore, Rope, Sisyph, TerminalIO = BEGIN Signal: SIGNAL = CODE; MuxForm: TYPE = REF MuxFormRec; MuxFormRec: TYPE = RECORD[in, top, bot, ctl, out: Wire]; Wire: TYPE = Core.Wire; Wires: TYPE = Core.Wires; CellType: TYPE = Core.CellType; muxFormProp: ATOM _ $DataPathForm; blank: Wire _ CoreOps.CreateWires[0, "Blank"]; textScale: INT _ 2; font: CDTexts.CDFont _ CDTexts.MakeFont["Xerox/TiogaFonts/Helvetica7", textScale]; dwText: CD.Object _ CDTexts.Create["driveWeak", font]; Vdd: IO.ROPE _ "Vdd"; Gnd: IO.ROPE _ "Gnd"; plus: IO.ROPE _ "+"; minus: IO.ROPE _ "-"; log: IO.STREAM _ TerminalIO.TOS[]; lambda: INT _ CMosB.lambda; topTail: INT _ 2* lambda; botTail: INT _ 1* lambda; cnctSize: INT _ 4* lambda; layRules: ATOM _ $cmosB; schDeco: CoreGeometry.Decoration _ Sisyph.mode.decoration; layDeco: CoreGeometry.Decoration _ PWCore.extractMode.decoration; MuxAttributes: PWCore.AttributesProc = { OPEN CG: CoreGeometry; spec: DataPath.DPSpec _ DataPath.NewCellTypeSpec[cellType]; data: CoreClasses.RecordCellType _ NARROW[cellType.data]; wires: Wires; gnd: Wire _ CoreOps.FindWire[cellType.public, "Gnd"]; vdd: Wire _ CoreOps.FindWire[cellType.public, "Vdd"]; form: MuxForm _ NEW[MuxFormRec]; char: CHAR _ 'a; EachSideWire: CG.EachSortedPinProc = {wires _ CONS[wire, wires]}; EachChanWire: CG.EachSortedPinProc = { -- wire min max layer count: INT _ 0; chan: INT _ (DataPath.SchHalfBus[spec, (min+max)/2]-1)/2; FOR ws: Wires _ wires, ws.rest WHILE ws#NIL DO count _ count+1 ENDLOOP; FOR chanIndex: INT IN (count..chan] DO wires _ CONS[blank, wires] ENDLOOP; wires _ CONS[wire, wires]}; InsertGndVdd: PROC[orig: Wires] RETURNS[new: Wires _ NIL] = { FOR index: INT _ 0, index + 1 DO next: Wire; IF MAX[spec.gndBus, spec.vddBus] < index AND orig=NIL THEN EXIT; SELECT TRUE FROM index = spec.gndBus => {next _ gnd; IF gnd=NIL THEN ERROR}; index = spec.vddBus => {next _ vdd; IF vdd=NIL THEN ERROR}; orig#NIL => {next _ orig.first}; ENDCASE => {next _ blank}; IF orig#NIL THEN {IF next#orig.first AND orig.first#blank THEN ERROR; orig _ orig.rest}; new _ CONS[next, new]; ENDLOOP; RETURN[CoreOps.Reverse[new]]}; Name: PROC[w: Wire, prefix: IO.ROPE, index: INT] = { IF CoreOps.GetShortWireName[w].Length[]=0 THEN { nm: IO.ROPE _ IO.PutFR["%g%g", IO.rope[prefix], IO.int[index]]; CheckForConflict: CoreOps.EachWireProc = {IF nm.Equal[CoreOps.GetShortWireName[wire]] THEN ERROR}; []_CoreOps.VisitWire[cellType.public, CheckForConflict]; []_CoreOps.SetShortWireName[w, nm]}}; wires _ NIL; []_CG.EnumerateSortedSides[schDeco, cellType, top, EachChanWire]; form.top _ CoreOps.CreateWire[InsertGndVdd[ CoreOps.Reverse[wires]]]; wires _ NIL; []_CG.EnumerateSortedSides[schDeco, cellType, bottom, EachChanWire]; form.bot _ CoreOps.CreateWire[InsertGndVdd[ CoreOps.Reverse[wires]]]; wires _ NIL; []_CG.EnumerateSortedSides[schDeco, cellType, left, EachSideWire]; form.ctl _ CoreOps.CreateWire[CoreOps.Reverse[wires]]; form.in _ CoreOps.CreateWires[form.ctl.size]; FOR child: NAT IN [0..data.size) DO gate: Wire _ data[child].actual[CoreOps.GetWireIndex[data[child].type.public, "gate"]]; ch1: Wire _ data[child].actual[CoreOps.GetWireIndex[data[child].type.public, "ch1"]]; ch2: Wire _ data[child].actual[CoreOps.GetWireIndex[data[child].type.public, "ch2"]]; FOR index: INT IN [0..form.ctl.size) DO IF form.ctl[index]#gate THEN LOOP; IF form.in[index]#NIL THEN Signal[]; form.in[index] _ ch1; IF form.out#NIL AND form.out#ch2 THEN Signal[]; form.out _ ch2; EXIT REPEAT FINISHED=> Signal[] ENDLOOP; ENDLOOP; FOR i: NAT IN [0..form.ctl.size) DO Name[form.ctl[i], "ctl", i] ENDLOOP; FOR i: NAT IN [0..form.in.size) DO Name[form.in[i], "in", i] ENDLOOP; FOR i: NAT IN [0..form.top.size) DO Name[form.top[i], "top", i] ENDLOOP; FOR i: NAT IN [0..form.bot.size) DO Name[form.bot[i], "bot", i] ENDLOOP; Name[form.out, "out", 0]; CoreOps.FlushNameCaches[cellType.public]; CoreOps.FlushNameCaches[data.internal]; CoreProperties.PutCellTypeProp[cellType, muxFormProp, form]}; MuxLayout: PWCore.LayoutProc = { spec: DataPath.DPSpec _ DataPath.NewCellTypeSpec[cellType]; data: CoreClasses.RecordCellType _ NARROW[cellType.data]; f: MuxForm _ NARROW[CoreProperties.GetCellTypeProp[cellType, muxFormProp]]; name: IO.ROPE _ CoreOps.GetCellTypeName[cellType]; insts: CD.InstanceList _ NIL; cellWidth: INT _ DataPath.BitWidth[spec]; xstrLgth: INT _ 8*lambda; xstrWth: INT _ (4+4)*lambda; xstrWthBig: INT _ (4+8)*lambda; tranBiasx: INT _ (xstrWth-spec.metW)/2; tranBiasLtx: INT _ tranBiasx + 4*lambda; xstrHt: INT _ xstrLgth + 2*spec.difW; pFrng: INT _ (spec.pwrW-spec.metW)/2; topExtra: INT _ cnctSize/2 + topTail; botExtra: INT _ cnctSize/2 + botTail; cnctBiasx: INT _ (cnctSize-spec.metW)/2; viaPolSpace: INT _ 3*cnctSize; -- actually 2+4+1+4+1 lambda muxEvenDn: BOOL = TRUE; minTranUsd: BOOL _ FALSE; gnd: INT _ spec.gndBus; vdd: INT _ spec.vddBus; rangeXMax: INT _ spec.buses+(spec.layDWidth - viaPolSpace)/spec.layBusW; range: CD.Position _ [MIN[rangeXMax, MAX[f.top.size, f.bot.size]+1], f.ctl.size]; pitch: CD.Position _ [spec.metPitch, spec.met2Pitch]; outIndex: INT _ WireIndexMax[f.top, f.out]; outIndexBot: INT _ WireIndexMax[f.bot, f.out]; IF outIndex # WireIndexMin[f.top, f.out] OR outIndexBot # WireIndexMin[f.bot, f.out] OR outIndex#-1 AND outIndexBot#-1 AND outIndex#outIndexBot THEN {log.PutF["*** Multiple column output\n"]; ERROR}; outIndex _ MAX[outIndex, outIndexBot]; IF f.out#blank AND WireIndexMax[f.in, f.out]#-1 THEN {log.PutF["*** Output signal is also used as input\n"]; ERROR}; FOR i: INT IN [0..range.x) DO loc: CD.Position _ [i*pitch.x, 0]; topOut: BOOL _ f.out # blank AND IW[f.top, i] = f.out; botOut: BOOL _ f.out # blank AND IW[f.bot, i] = f.out; tY: INT _ IF topOut THEN WireNonBlankIndexMin[f.in] ELSE WireIndexMin[f.in, IW[f.top, i]]; bY: INT _ IF botOut THEN WireNonBlankIndexMax[f.in] ELSE WireIndexMax[f.in, IW[f.bot, i]]; 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 ~(IW[f.top, i] = IW[f.bot, i]) AND tY<=bY AND IW[f.top, i]#blank AND IW[f.bot, i]#blank THEN {log.PutF["*** 2 signals in same channel\n"]; ERROR}; IF IW[f.top, i]#blank THEN insts _ AddRetInst[ insts: insts, internal: data.internal, wire: f.top[i], level: CMosB.met, size: [spec.metW, (range.y-tY) * pitch.y + topExtra ], loc: [i*pitch.x, tY * pitch.y ]]; IF IW[f.bot, i]#blank THEN insts _ AddRetInst[ insts: insts, internal: data.internal, wire: f.bot[i], level: CMosB.met, size: [spec.metW, bY * pitch.y + botExtra ], loc: [i*pitch.x, 0 * pitch.y - botExtra ]]; ENDLOOP; IF gnd>-1 THEN { gndWire: Wire _ CoreOps.FindWire[data.internal, "Gnd"]; insts _ AddRetInst[ insts: insts, internal: data.internal, wire: gndWire, level: CMosB.met, size: [spec.pwrW, range.y * pitch.y + topExtra + botExtra ], loc: [gnd*pitch.x-pFrng , - botExtra ]]}; IF vdd>-1 THEN { vddWire: Wire _ CoreOps.FindWire[data.internal, "Vdd"]; insts _ AddRetInst[ insts: insts, internal: data.internal, wire: vddWire, level: CMosB.met, size: [spec.pwrW, range.y * pitch.y + topExtra + botExtra ], loc: [vdd*pitch.x-pFrng , - botExtra ]]}; BEGIN xstr: CD.Object _ CMosBObjects.CreateTransistor [size: [xstrWth, xstrLgth], difLayer: CMosB.ndif]; xstrBig: CD.Object _ CMosBObjects.CreateTransistor [size: [xstrWthBig, xstrLgth], difLayer: CMosB.ndif]; dcon: CD.Object _ CDSimpleRules.Contact[layRules, CMosB.met, CMosB.ndif]; pcon: CD.Object _ CDSimpleRules.Contact[layRules, CMosB.met, CMosB.pol]; vcon: CD.Object _ CDSimpleRules.Contact[layRules, CMosB.met, CMosB.met2]; scon: CD.Object _ CMosBObjects.CreateDifCon[CMosB.pwellCont]; pvconn: CD.Object _ CDRects.CreateRect[[2*cnctSize, cnctSize], CMosB.met]; 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] = {insts _ CONS[ NEW[CD.InstanceRep _ [object, [location]]], insts]}; 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, lt, rt: BOOL] = { 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, spec.polW], CMosB.pol]; dif: CD.Object _ CDRects.CreateRect[[dWL, spec.difW], CMosB.ndif]; 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 -spec.polW/2 ]]; Include[dif, [minX *pitch.x -cnctBiasx, yloc +dir*pitch.y/2 -spec.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[dwText, [index.x *pitch.x -tranBiasx, yloc -lambda*textScale/2 ]]; SELECT TRUE FROM lt => Include[xstrBig, [index.x *pitch.x -tranBiasLtx, yloc -xstrLgth/2 ]]; rt => Include[xstrBig, [index.x *pitch.x -tranBiasx, yloc -xstrLgth/2 ]]; ENDCASE => Include[xstr, [index.x *pitch.x -tranBiasx, yloc -xstrLgth/2 ]]; CDSatellites.Associate[master: insts.first, text: insts.rest.first]}; size: CD.Position _ [DataPath.BitWidth[spec], spec.met2W]; loc: CD.Position _ [spec.metW/2-spec.leftTail, ctlIndex*pitch.y+pitch.y/2-spec.met2W/2]; insts _ AddRetInst[insts: insts, internal: data.internal, wire: f.ctl[ctlIndex], size:size, loc:loc, level: CMosB.met2]; IF f.out#blank THEN { ioIndex: INT _ IOIndex[ctlIndex, f]; IF ioIndex >=0 THEN { inDn: BOOL _ ((ctlIndex MOD 2)=0)=muxEvenDn; ioIndexUp: INT _ IF inDn THEN -1 ELSE IOIndex[ctlIndex+1, f]; ioIndexDn: INT _ IF ~inDn THEN -1 ELSE IOIndex[ctlIndex-1, f]; extLt: BOOL _ ioIndex # (gnd+1) AND ioIndex # 0 AND (ioIndexUp=-1 OR ioIndexUp#(ioIndex-1)) AND (ioIndexDn=-1 OR ioIndexDn#(ioIndex-1)); extRt: BOOL _ ioIndex # (gnd-1) AND ioIndex < (range.x-1) AND (ioIndexUp=-1 OR ioIndexUp#(ioIndex+1)) AND (ioIndexDn=-1 OR ioIndexDn#(ioIndex+1)); IF NOT(extLt OR extRt) THEN minTranUsd _ TRUE; AddMux[[ioIndex, ctlIndex], extLt, extRt]}; thsIONotGnd _ ioIndex # gnd; thsGndClear _ thsIONotGnd AND ((ioIndex -1 THEN RETURN[ioIndex]; ioIndex _ WireIndexMax[form.bot, form.in[ctl]]}; IW: PROC[wire: Wire, index: INT] RETURNS[subwire: Wire] = {RETURN[IF index IN [0..wire.size) THEN wire[index] ELSE blank]}; WireIndexMax: PROC[root, subWire: Wire] RETURNS[index: INT _ -1] = {FOR i: INT DECREASING IN [0..root.size) DO IF root[i]=subWire THEN RETURN[i] ENDLOOP}; WireIndexMin: PROC[root, subWire: Wire] RETURNS[index: INT _ -1] = {FOR i: INT IN [0..root.size) DO IF root[i]=subWire THEN RETURN[i] ENDLOOP}; WireNonBlankIndexMin: PUBLIC PROC [wire: Wire] RETURNS[index: INT] = { FOR index IN [0..wire.size) DO IF wire[index]#blank THEN RETURN[index] ENDLOOP; RETURN[-1]}; WireNonBlankIndexMax: PUBLIC PROC [wire: Wire] RETURNS[index: INT] = { FOR index DECREASING IN [0..wire.size) DO IF wire[index]#blank THEN RETURN[index] ENDLOOP; RETURN[-1]}; AddRetInst: PROC[insts: CD.InstanceList, internal, wire: Wire, size: CD.Position, loc: CD.Position, level: CD.Layer] RETURNS[CD.InstanceList] = { name: IO.ROPE _ CoreRoute.LabelInternal[internal, wire]; props: CD.PropList _ LIST[[$SignalName, name]]; IF size.x<0 OR size.y<0 THEN { log.PutF["*** Strange rectangle size [%g, %g]\n", IO.int[size.x], IO.int[size.y] ]; Signal[]}; IF size.x=0 OR size.y=0 THEN RETURN[insts]; insts _ CONS[ NEW[CD.InstanceRep _ [ ob: CDRects.CreateRect[size, level], trans: [loc], properties: props ]], insts]; RETURN[insts]}; [] _ PWCore.RegisterLayoutAtom [$DataPathMuxVPwr, MuxLayout, PWCore.DecorateValue, MuxAttributes]; END. ~DataPathMuxVPwr.mesa, Copyright c 1986 by Xerox Corporation. All rights reserved. Don Curry November 10, 1987 1:05:28 pm PST Types and constants Attribute and Layout procs Heresy: This Attribute procedure changes the source by giving names to unnamed publics. This is done so that names can be used to do the decorating. They also improve the legibility of the cellType when seen in the debugger or simulation. Other alternatives would be: 1. Write an extract proc for multiplexors (which would provide the names). 2. Write a variation of PWCore.DecorateValue that used some other property on the source public to do the binding. 3. Require that the designer always put valid names in the mux schematic. I don't see any harm in providing the names here but I'm sure Bertrand would. He's not here though (heh heh). Find and check outIndex Vertical Metal First try to make the transistor larger If inDn then there can be no clash above to making the transistor larger since that is the side of the output connection. In this case, ioIndexUp will get -1 even if the correcsponding control really does gate some input. Utilities Runtime ΚT˜šœ™Jšœ<™˜QJšœ œ œ˜6Jšœ œ˜-šœœœ˜#JšœW˜WJšœU˜UJšœU˜Ušœœœ˜'Jšœœœ˜"Jšœœœ ˜>Jšœ œœœ˜?Jšœœœ œ˜(—Jšœ˜—Jš œœœœ˜HJš œœœœ˜FJš œœœœ˜HJš œœœœ˜HJšœ˜Jšœ)˜)Jšœ'˜'Jšœ=˜=J˜—šž œ˜ Jšœ=˜=Jšœ%œ˜;Jšœœ8˜NJšœœœ%˜4Jšœ œœ˜Jšœ œ˜+Jšœ œ˜Jšœ œ˜Jšœ œ˜!Jšœ œ˜*Jšœ œ˜*Jšœ œ˜(Jšœœ˜(Jšœ œ˜(Jšœ œ˜(Jšœ œ˜*Jšœ œ ˜=Jšœ œœ˜Jšœ œœ˜Jšœœ˜Jšœœ˜Jšœ œ<˜JJšœ œ œ œ)˜SJšœ œ,˜7J˜J˜JšŸ™Jšœ œ ˜.Jšœ œ ˜0šœ(˜,Jšœ*˜,šœ œœ˜8Jšœ,œ˜7——Jšœ œ˜&šœ œ˜4Jšœ8œ˜?—J™JšŸ™šœœœ˜Jšœœ˜#Jšœœœœ˜6Jšœœœœ˜6šœœœ˜Jšœœœ ˜F—šœœœ˜Jšœœœ ˜F—Jš œœœœœ˜?Jš œœœœœ˜?Jšœœœ ˜ šœœ œ œœœœœ˜ZJšœ/œ˜:—šœœœ˜.JšœH˜HJšœ6˜6Jšœ$˜$—šœœœ˜.JšœH˜HJšœ/˜/Jšœ/˜/—Jšœ˜—šœœ˜Jšœ7˜7šœ˜JšœG˜GJšœ<˜JšœœA˜KJšœœœ˜Jšœœœ˜Jšœ œœ˜Jšœœœ˜šœ œœ˜$šžœœ œœ ˜9Jšœ œœœ.˜C—šž œœœ˜1JšœH˜LJšœJ˜N—šžœœ œœ˜3Jšœœœ%˜5Jšœœ˜&Jšœœœ˜$Jšœœœ˜$Jšœœ;˜CJšœœ<˜DJš œœœ œœœ˜Jš œ œœœœ˜>šœœœ ˜4Jšœœ˜+Jšœœ˜(—šœœœ˜>Jšœœ˜+Jšœœ˜(—Jš œœœœœ˜.Jšœ+˜+—Jšœ˜Jšœœ ˜=šœ œ˜!Jšœœ œ œ˜—šœœœ œ˜@Jšœœœ˜3Jšœœœ˜3—Jšœ˜Jšœ˜—Jšœ˜—Jšœ˜Jšœ˜—šœœ/˜7Jšœ0˜0JšœJ˜J—Jšœ œ;˜M——™ š žœœœœ œ˜@Jš œœœœœ˜/Jšœœœ˜&Jšœ/˜/Jšœœœ ˜%Jšœ0˜0J˜—šœœœœ˜9Jš œœœœœ œ ˜AJ˜—šž œœœœ˜BJšœœœ œœœœœœœ˜WJ˜—šž œœœœ˜BJšœœœœœœœœœ˜LJ˜—š žœœœœœ˜Fšœœ˜Jšœœœœ˜0—Jšœ˜ J˜—š žœœœœœ˜Fšœ œœ˜)Jšœœœœ˜0—Jšœ˜ J™—šž œœœ$˜>šœœœœ˜5Jšœœ˜—Jšœœœ,˜9Jšœœ œ˜/šœ œ œ˜Jšœ2œœ˜SJšœ ˜ —Jšœ œ œœ˜+šœœœœ˜$Jšœ$˜$Jšœ ˜ Jšœ˜—Jšœ˜Jšœ ˜——™šœ˜JšœC˜C—J˜Jšœ˜—J˜—…—4ΠH’