DIRECTORY
BondingPads, CD, CDBasics, CDCells, CDInstances, CDProperties, CDRects, CMosB, Core, CoreClasses, CoreCreate, CoreGeometry, CoreOps, CoreProperties, IO, PW, PWCore, RefTab, Rope, Route, Sisyph, TerminalIO;
Types and constants
Wires: TYPE = Core.Wires;
Side: TYPE = CoreGeometry.Side;
Trans: TYPE = CoreGeometry.Transformation;
Instance: TYPE = CoreGeometry.Instance;
Instances: TYPE = CoreGeometry.Instances;
PadArray: TYPE = BondingPads.PadArray;
SidePads: TYPE = BondingPads.SidePads;
Pads: TYPE = BondingPads.Pads;
Pad: TYPE = BondingPads.Pad;
tech: CD.Technology ← CMosB.cmosB;
grid: INT ← tech.lambda*2;
layDeco: CoreGeometry.Decoration ← PWCore.extractMode.decoration;
schDeco: CoreGeometry.Decoration ← Sisyph.mode.decoration;
Layout and Decorate
Layout: PWCore.LayoutProc = {
name: IO.ROPE ← CoreOps.GetCellTypeName[cellType];
instances: CD.InstanceList ← NIL;
padArray: PadArray;
gndPlane: Instance;
recordCellType: CoreClasses.RecordCellType ← NARROW[cellType.data];
subInst: CoreClasses.CellInstance ← recordCellType.instances[0];
size: CD.Position;
ir: CD.Rect;
used: RefTab.Ref ← RefTab.Create[];
widths: ARRAY Side OF INT;
bindPads: CoreOps.EachWirePairProc = {
pubInsts: Instances ← NARROW[CoreProperties.GetWireProp[actualWire, $BondingPads]];
actInsts: Instances ← NARROW[CoreProperties.GetWireProp[publicWire, $BondingPads]];
IF RefTab.Store[used, publicWire, publicWire]
-- Store is TRUE if new
THEN
FOR actInsts ← actInsts, actInsts.rest
WHILE actInsts#
NIL
DO
pubInsts ← CONS[actInsts.first, pubInsts] ENDLOOP;
CoreProperties.PutWireProp[actualWire, $BondingPads, pubInsts]};
BuildCDInstanceList: PROC[w: Core.Wire] = {
geo: Instances ← NARROW[CoreProperties.GetWireProp[w, $PadGeometry]];
CoreProperties.PutWireProp[w, $PadGeometry, NIL];
FOR geo ← geo, geo.rest
WHILE geo#
NIL
DO
inst: CD.Instance ← CDInstances.NewInst[geo.first.obj, geo.first.trans];
CDProperties.PutProp[inst, $SignalName, CoreOps.GetFullWireName[cellType.public, w]];
instances ← CONS[inst, instances] ENDLOOP};
[]←PWCore.Layout[subInst.type];
BondingPads.EnsureBondingPads[subInst.type];
size ← BondingPads.GetSize[subInst.type];
CoreProperties.PutCellTypeProp[cellType, $BondingFrameSize, NEW[CD.Position ← size]];
[]𡤌oreOps.VisitBindingSeq[subInst.actual, subInst.type.public, bindPads];
padArray ← BondingPads.GetPads[cellType];
TerminalIO.PutF["HybridDiePad for: %g.\n", IO.rope[name]];
FOR side: Side
IN Side
DO
twoTier: BOOL ← padArray[side].offSets.rest#NIL;
pads: Pads ← padArray[side].pads;
length: INT ← IF side=top OR side=bottom THEN size.x ELSE size.y;
width: INT ← IF twoTier THEN loc6 ELSE loc3;
trans: Trans;
vddPlane: CD.Object ← CDRects.CreateRect[[loc1, length], layer1];
trans.off ←
SELECT side
FROM
left => [-width, 0 ],
right => [size.x+width, 0 ],
top => [0, size.y+width ],
ENDCASE => [0, -width ];
trans.orient ←
SELECT side
FROM
left => original,
right => mirrorX,
top => rotate270,
ENDCASE => rotate90X;
widths[side] ← width;
WHILE pads#
NIL
DO
wire1: Core.Wire ← pads.first.wire;
pwr: BOOL ← IsVdd[wire1] OR IsGnd[wire1];
centerY: INT ← pads.first.pos.y;
IF twoTier
THEN {
fstOuter: BOOL ← padArray[side].offSets.first=pads.first.pos.x;
scdInner: BOOL ← pads.rest#NIL AND (pads.first.pos.y = pads.rest.first.pos.y);
wire2: Core.Wire ← IF scdInner THEN pads.rest.first.wire ELSE NIL;
signal: IO.ROPE ← NIL;
SELECT
TRUE
FROM
scdInner AND ~pwr => ERROR;
scdInner AND IsVdd[wire2] => ERROR;
scdInner AND IsGnd[wire2] => ERROR;
scdInner => {AddPads[2, centerY, wire1, wire2, trans]; pads←pads.rest};
~pwr => {AddPads[2, centerY, NIL, wire1, trans]};
ENDCASE => {AddPads[2, centerY, wire1, NIL, trans]} }
ELSE AddPads[1, centerY, wire1, NIL, trans];
pads ← pads.rest ENDLOOP;
AddPositionedObject
[CoreOps.FindWire[cellType.public, "Vdd"], vddPlane, 0, length/2, trans, TRUE];
ENDLOOP;
ir ← [-widths[left], -widths[right], size.x + widths[right], size.y + widths[top]];
gndPlane ← [CDRects.CreateRect[CDBasics.SizeOfRect[ir], layer0], [CDBasics.BaseOfRect[ir]] ];
AddInstance[CoreOps.FindWire[cellType.public, "Gnd"], gndPlane, TRUE];
[]𡤌oreOps.VisitRootAtomics[cellType.public, BuildCDInstanceList];
obj ← CDCells.CreateCell[il: instances, ir: ir];
CDCells.ToSequenceMode[obj]};
AddPositionedObject:
PROC
[wire: Core.Wire, obj: CD.Object, posX, centerY: INT, trans: Trans, isPin: BOOL ← FALSE] = {
szY: INT ← CD.InterestSize[obj].y;
trans ← CDBasics.ComposeTransform[ [[posX, centerY-szY/2 ]], trans];
AddInstance[wire, [obj, trans], isPin]};
AddInstance:
PROC
[wire: Core.Wire, inst: Instance, isPin: BOOL ← FALSE] = {
geo: Instances ← NARROW[CoreProperties.GetWireProp[wire, $PadGeometry]];
IF isPin THEN CoreGeometry.AddPins[layDeco, wire, LIST[inst]];
geo ← CONS[inst, geo];
CoreProperties.PutWireProp[wire, $PadGeometry, geo]};
AddPads:
PROC[tiers, centerY:
INT, sig0, sig1: Core.Wire, trans: Trans] = {
SELECT tiers
FROM
1 => {
SELECT
TRUE
FROM
IsVdd[sig0] => {
AddPositionedObject[sig0, cntc23, loc0, centerY, trans, TRUE];
AddPositionedObject[sig0, long1, loc0, centerY, trans, TRUE];
AddPositionedObject[sig0, cntc12, loc1, centerY, trans]};
IsGnd[sig0] => {
AddPositionedObject[sig0, cntc23, loc0, centerY, trans, TRUE];
AddPositionedObject[sig0, cntc12, loc1, centerY, trans];
AddPositionedObject[sig0, cntc01, loc2, centerY, trans]};
ENDCASE =>
AddPositionedObject[sig0, cntc23, loc0, centerY, trans, TRUE]};
2 => {
IF sig1#NIL THEN AddPositionedObject[sig1, cntc23, loc0, centerY, trans, TRUE];
SELECT
TRUE
FROM
IsVdd[sig0] => {
AddPositionedObject[sig0, long1, loc0, centerY, trans, TRUE];
AddPositionedObject[sig0, short1, loc1, centerY, trans];
AddPositionedObject[sig0, long1, loc2, centerY, trans];
AddPositionedObject[sig0, cntc23, loc2, centerY, trans];
AddPositionedObject[sig0, cntc12, loc3, centerY, trans]};
IsGnd[sig0] => {
AddPositionedObject[sig0, cntc23, loc2, centerY, trans];
AddPositionedObject[sig0, cntc12, loc3, centerY, trans];
AddPositionedObject[sig0, cntc01, loc4, centerY, trans]};
ENDCASE};
ENDCASE => ERROR};
The only direct references to CMosB layers
See HybridDiePadRef.dale
sml: INT ← 100 * tech.lambda;
lrg: INT ← 250 * tech.lambda;
loc0: INT ← 0;
loc1: INT ← loc0 + lrg;
loc2: INT ← loc1 + sml;
loc3: INT ← loc2 + lrg;
loc4: INT ← loc3 + sml;
loc5: INT ← loc4 + sml;
loc6: INT ← loc5 + sml;
layer0: CD.Layer ← CMosB.ndif;
layer1: CD.Layer ← CMosB.pol;
short1: CD.Object ← CDRects.CreateRect[[sml, sml], CMosB.pol]; -- for gaps
long1: CD.Object ← CDRects.CreateRect[[lrg, sml], CMosB.pol]; -- for beneath cntc23
cntc01: CD.Object ← MakeContact[CMosB.ndif, CMosB.bur, CMosB.pol, sml, sml, sml/4];
cntc12: CD.Object ← MakeContact[CMosB.pol, CMosB.cut, CMosB.met, sml, sml, sml/4];
cntc23: CD.Object ← MakeContact[CMosB.met, CMosB.cut2, CMosB.met2, lrg, sml, sml/20];
IsVdd:
PROC[wire: Core.Wire]
RETURNS[
BOOL] =
{RETURN[wire#NIL AND CoreOps.GetShortWireName[wire].Equal["Vdd"]]};
{RETURN[CoreOps.GetShortWireName[wire].Find["Vdd", 0, FALSE]#-1]};
IsGnd:
PROC[wire: Core.Wire]
RETURNS[
BOOL] =
{RETURN[wire#NIL AND CoreOps.GetShortWireName[wire].Equal["Gnd"]]};
{RETURN[CoreOps.GetShortWireName[wire].Find["Gnd", 0, FALSE]#-1]};
MakeContact:
PROC[l0, l1, l2:
CD.Layer, sizex, sizey, border:
INT]
RETURNS[obj: CD.Object] = {
node: IO.ROPE ← "node";
insts: CD.InstanceList ← NIL;
middle: CD.Object ← CDRects.CreateRect[[sizex-2*border, sizey-2*border], l1];
insts ← CONS[NEW[CD.InstanceRep ← [middle, [[border, border]]]], insts];
CDProperties.PutProp[insts.first, $SignalName, node];
insts ← CONS[NEW[CD.InstanceRep ← [CDRects.CreateRect[[sizex, sizey], l0]]], insts];
CDProperties.PutProp[insts.first, $SignalName, node];
insts ← CONS[NEW[CD.InstanceRep ← [CDRects.CreateRect[[sizex, sizey], l2]]], insts];
CDProperties.PutProp[insts.first, $SignalName, node];
obj ← PW.CreateCell[instances: insts, ir: [0, 0, sizex, sizey]];
CDProperties.PutProp[obj, PWCore.extractMode.extractProcProp, $ExtractAtomic]};