--///cd23/SCLibGenImpl.mesa
--Created by: Jacobi June 2, 1986 3:48:19 pm PDT
--Last Edited by: Jacobi July 11, 1986 10:24:58 am PDT
DIRECTORY
CD, CDBasics, CDRects, CDCells, SCLibGen, CDGenerate, CDDirectory, CDOrient, CDProperties, CDRemote, CDSimpleRules, CDSymbolicObjects, CDUtil, Rope;
SCLibGenImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDRects, CDCells, CDGenerate, CDDirectory, CDProperties, CDRemote, CDSimpleRules, CDSymbolicObjects, CDUtil, Rope
EXPORTS SCLibGen =
BEGIN
SetUpTech: PROC [t: CD.Technology] = {
lambda ← t.lambda;
met ← CD.FetchLayer[t, $met];
met2 ← CD.FetchLayer[t, $met2];
};
seeMeProc: PROC[CD.Object] ← NIL;
SeeMe: PUBLIC PROC [p: PROC[CD.Object]] = {seeMeProc←p};
met, met2: CD.Layer;
gDesign: CD.Design;
cell: CD.Object;
ptype: BOOL;
originP, pitchP, bottomContactN, topContactP, m2ContP, heightP: CD.Position;
topPinR, botPinR, vddPinR, gndPinR: CD.Rect;
lambda, pitch, metWidth, limitPy, limitNy: CD.Number;
sizeOb, p1Ob, p2Ob, p3Ob, p4Ob, contactNOb, contactPOb, contactM2Ob, xViaOb: CD.Object;
topPinOb, botPinOb, vddPinOb, gndPinOb: CD.Object;
specialOb, specialDNOb, specialDPOb: CD.Object;
pinOrder: Rope.ROPE;
GetP1: CDGenerate.GeneratorProc = {
ob ← CDUtil.PartialCopy[ob: sizeOb, design: design, instances: LIST["B", "T", "TN", "TP"], remove: FALSE, prop: $X, name: "=template="];
CDCells.SetSimplificationTreshhold[ob, 0.05, FALSE];
};
GetP2: CDGenerate.GeneratorProc = {
ob ← CDUtil.PartialCopy[ob: sizeOb, design: design, instances: LIST["B", "T", "TP"], remove: FALSE, prop: $X, name: "=template="];
CDCells.SetSimplificationTreshhold[ob, 0.05, FALSE];
};
GetP3: CDGenerate.GeneratorProc = {
ob ← CDUtil.PartialCopy[ob: sizeOb, design: design, instances: LIST["B", "T", "TN"], remove: FALSE, prop: $X, name: "=template="];
CDCells.SetSimplificationTreshhold[ob, 0.05, FALSE];
};
GetP4: CDGenerate.GeneratorProc = {
ob ← CDUtil.PartialCopy[ob: sizeOb, design: design, instances: LIST["B"], remove: FALSE, prop: $X, name: "=template="];
CDCells.SetSimplificationTreshhold[ob, 0.05, FALSE];
};
SetUpInput: PROC [design: CD.Design] = {
GetLib: PROC [name: Rope.ROPE] RETURNS [ob: CD.Object] = {
ob ← CDGenerate.FetchNCall[stdCellInput, design, name];
IF ob=NIL THEN ERROR
};
SetUpTech[design.technology];
gDesign ← design;
sizeOb ← GetLib["size"];
specialOb ← GetLib["special"];
specialDNOb ← GetLib["specialDN"];
specialDPOb ← GetLib["specialDP"];
p1Ob ← CDGenerate.FetchNCall[stdCell, design, "=p1="];
p2Ob ← CDGenerate.FetchNCall[stdCell, design, "=p2="];
p3Ob ← CDGenerate.FetchNCall[stdCell, design, "=p3="];
p4Ob ← CDGenerate.FetchNCall[stdCell, design, "=p4="];
contactNOb ← GetLib["contactN"];
contactPOb ← GetLib["contactP"];
contactM2Ob ← GetLib["contactM2"];
xViaOb ← GetLib["xVia"];
topPinOb ← FetchPin[sizeOb, "topPin"].ob;
botPinOb ← FetchPin[sizeOb, "botPin"].ob;
vddPinOb ← FetchPin[sizeOb, "Vdd"].ob;
gndPinOb ← FetchPin[sizeOb, "Gnd"].ob;
metWidth ← CDSimpleRules.MinWidth[met];
GetNumbers[sizeOb];
};
FetchPin: PROC [cell: CD.Object, name: Rope.ROPE] RETURNS [inst: CD.Instance] = {
il: CD.InstanceList ← CDSymbolicObjects.FindSymbolicObs[cell, name];
IF il=NIL OR il.rest#NIL OR il.first.ob=NIL THEN ERROR;
RETURN [il.first]
};
GetNumbers: PROC [ob: CD.Object] =
BEGIN
GetOPoint: PROC [name: Rope.ROPE] RETURNS [p: CD.Position] = {
r: CD.Rect ← CDSymbolicObjects.Denotes[FetchPin[ob, name]];
p ← [r.x1, r.y1];
};
GetRect: PROC [name: Rope.ROPE] RETURNS [r: CD.Rect] = {
r ← CDBasics.MoveRect[
CDSymbolicObjects.Denotes[FetchPin[ob, name]],
CDBasics.NegOffset[originP]
]
};
GetPoint: PROC [name: Rope.ROPE] RETURNS [p: CD.Position] = {
p ← CDBasics.SubPoints[GetOPoint[name], originP];
};
originP ← GetOPoint["origin"];
pitchP ← GetPoint["pitch"];
bottomContactN ← GetPoint["bottomContactN"];
topContactP ← GetPoint["topContactP"];
m2ContP ← GetPoint["m2c"];
heightP ← GetPoint["height"];
limitPy ← GetPoint["limitP"].y;
limitNy ← GetPoint["limitN"].y;
topPinR ← GetRect["topPin"];
botPinR ← GetRect["botPin"];
vddPinR ← GetRect["Vdd"];
gndPinR ← GetRect["Gnd"];
pitch ← pitchP.x;
END;
ContactM2: PUBLIC PROC [pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8, pos9, pos10, pos11, pos12, pos13, pos14, pos15, pos16, pos17, pos18, pos19, pos20, pos21, pos22: INT ← -1] = {
Incl: PROC [n: INT←-1] = {
IF n>=0 THEN {
[] ← CDCells.IncludeOb[cell: cell, ob: contactM2Ob, obCSystem: interrestCoords,
position: [x: m2ContP.x+(n-1)*pitch, y: m2ContP.y]
];
}
};
Incl[pos1];
Incl[pos2];
Incl[pos3];
Incl[pos4];
Incl[pos5];
Incl[pos6];
Incl[pos7];
Incl[pos8];
Incl[pos9];
Incl[pos10];
Incl[pos11];
Incl[pos12];
Incl[pos13];
Incl[pos14];
Incl[pos15];
Incl[pos16];
Incl[pos17];
Incl[pos18];
Incl[pos19];
Incl[pos20];
Incl[pos21];
Incl[pos22];
};
Pins: PUBLIC PROC [cnt: INT ← 1, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22: Rope.ROPENIL] = {
pos: INT ← 0;
SignalPin: PROC [n: Rope.ROPENIL] = {
IF ~Rope.IsEmpty[n] THEN {
i: CD.Instance;
i ← CDCells.IncludeOb[cell: cell, ob: botPinOb, obCSystem: cdCoords,
orientation: CDOrient.rotate90,
position: [x: botPinR.x1+pos*pitch, y: botPinR.y1]
].newInst;
CDSymbolicObjects.SetLayer[i, met2];
CDSymbolicObjects.SetName[i, n];
--for aid to the Spinifex to Thyme extraction
i ← CDCells.IncludeOb[cell: cell,
ob: CDRects.CreateRect[botPinOb.size, met2], obCSystem: cdCoords,
orientation: CDOrient.rotate90,
position: [x: botPinR.x1+pos*pitch, y: botPinR.y1]
].newInst;
CDProperties.PutProp[i, $SignalName, n];
CDProperties.PutProp[i, $Export, $TRUE];
i ← CDCells.IncludeOb[cell: cell, ob: topPinOb, obCSystem: cdCoords,
orientation: CDOrient.rotate270,
position: [x: topPinR.x1+pos*pitch, y: topPinR.y2-topPinOb.size.x]
].newInst;
CDSymbolicObjects.SetLayer[i, met2];
CDSymbolicObjects.SetName[i, n];
};
pos ← pos+1;
};
i: CD.Instance;
gnd: Rope.ROPE = "Gnd";
vdd: Rope.ROPE = "Vdd";
--bottomLeft
i ← CDCells.IncludeOb[cell: cell, ob: gndPinOb, obCSystem: interrestCoords,
position: [x: gndPinR.x1, y: gndPinR.y1]
].newInst;
CDSymbolicObjects.SetLayer[i, met];
CDSymbolicObjects.SetName[i, "Gnd"];
--for aid to the Spinifex to Thyme extraction
i ← CDCells.IncludeOb[cell: cell,
ob: CDRects.CreateRect[gndPinOb.size, met], obCSystem: interrestCoords,
position: [x: gndPinR.x1, y: gndPinR.y1]
].newInst;
CDProperties.PutProp[i, $SignalName, gnd];
CDProperties.PutProp[i, $Export, $TRUE];
--bottomRight
i ← CDCells.IncludeOb[cell: cell, ob: gndPinOb, obCSystem: cdCoords,
orientation: CDOrient.rotate180,
position: [x: gndPinR.x1+cnt*pitch-gndPinOb.size.x, y: gndPinR.y1]
].newInst;
CDSymbolicObjects.SetLayer[i, met];
CDSymbolicObjects.SetName[i, "Gnd"];
--topLeft
i ← CDCells.IncludeOb[cell: cell, ob: vddPinOb, obCSystem: interrestCoords,
position: [x: vddPinR.x1, y: vddPinR.y1]
].newInst;
CDSymbolicObjects.SetLayer[i, met];
CDSymbolicObjects.SetName[i, "Vdd"];
--for aid to the Spinifex to Thyme extraction
i ← CDCells.IncludeOb[cell: cell,
ob: CDRects.CreateRect[vddPinOb.size, met], obCSystem: interrestCoords,
position: [x: vddPinR.x1, y: vddPinR.y1]
].newInst;
CDProperties.PutProp[i, $SignalName, vdd];
CDProperties.PutProp[i, $Export, $TRUE];
--topRight
i ← CDCells.IncludeOb[cell: cell, ob: vddPinOb, obCSystem: cdCoords,
orientation: CDOrient.rotate180,
position: [x: vddPinR.x1+cnt*pitch-vddPinOb.size.x, y: vddPinR.y1]
].newInst;
CDSymbolicObjects.SetLayer[i, met];
CDSymbolicObjects.SetName[i, "Vdd"];
SignalPin[p1];
SignalPin[p2];
SignalPin[p3];
SignalPin[p4];
SignalPin[p5];
SignalPin[p6];
SignalPin[p7];
SignalPin[p8];
SignalPin[p9];
SignalPin[p10];
SignalPin[p11];
SignalPin[p12];
SignalPin[p13];
SignalPin[p14];
SignalPin[p15];
SignalPin[p16];
SignalPin[p17];
SignalPin[p18];
SignalPin[p19];
SignalPin[p20];
SignalPin[p21];
SignalPin[p22];
};
MakeCont: PUBLIC PROC [row: INT, start: INT ← 0, n: INT ← 1, back: BOOL FALSE] = {
ct: CD.Object ← IF ptype THEN contactPOb ELSE contactNOb;
yStep: CD.Number ← IF ptype THEN -CD.InterestSize[ct].y ELSE CD.InterestSize[ct].y;
x: CD.Number ← bottomContactN.x+(row-1)*pitch;
y: CD.Number ← (IF ptype THEN topContactP.y ELSE bottomContactN.y)+(start-1)*yStep;
IF back THEN y←y-yStep/2;
WHILE n>0 DO
[] ← CDCells.IncludeOb[cell: cell, ob: ct, obCSystem: interrestCoords, position: [x: x, y: y]];
y ← y+yStep;
n ← n-1;
ENDLOOP;
};
MakeVia: PUBLIC PROC [row: INT, start: INT𡤀, n: INT ← 1, back: BOOL FALSE] = {
ct: CD.Object ← IF ptype THEN contactPOb ELSE contactNOb;
yStep: CD.Number ← IF ptype THEN -CD.InterestSize[ct].y ELSE CD.InterestSize[ct].y;
x: CD.Number ← bottomContactN.x+(row-1)*pitch;
y: CD.Number ← (IF ptype THEN topContactP.y ELSE bottomContactN.y)+(start-1)*yStep;
IF back THEN y←y-yStep/2;
WHILE n>0 DO
[] ← CDCells.IncludeOb[cell: cell, ob: xViaOb, obCSystem: interrestCoords, position: [x: x, y: y]];
y ← y+yStep;
n ← n-1;
ENDLOOP;
};
ContactSize: PROC [ptype: BOOLFALSE] RETURNS [s: CD.Position] = {
ct: CD.Object ← IF ptype THEN contactPOb ELSE contactNOb;
RETURN [CD.InterestSize[ct]]
};
HorizontalM: PUBLIC PROC [rowL, rowR: INT, h: INT, back: BOOL�LSE, shortStart: BOOLTRUE, shortEnd: BOOLTRUE] = {
m: CD.Object;
y1: CD.Number;
x1: CD.Number ← bottomContactN.x+(rowL-1)*pitch;
x2: CD.Number ← bottomContactN.x+(rowR-1)*pitch;
x1 ← x1 + (IF shortStart THEN ContactSize[ptype].x-metWidth ELSE 0);
x2 ← x2 + (IF shortEnd THEN metWidth ELSE ContactSize[ptype].x);
IF ptype THEN {
y1 ← topContactP.y-(h-1)*ContactSize[ptype].y;
IF back THEN y1 ← y1+ContactSize[ptype].y-metWidth;
}
ELSE {
y1 ← bottomContactN.y+(h-1)*ContactSize[ptype].y;
IF ~back THEN y1 ← y1+ContactSize[ptype].y-metWidth;
};
m ← CDRects.CreateRect[[x2-x1, metWidth], met];
[] ← CDCells.IncludeOb[cell: cell, ob: m, position: [x: x1, y: y1]];
};
PassMetall: PUBLIC PROC [row: INT] = {
m: CD.Object;
x1: CD.Number ← bottomContactN.x+(row-1)*pitch;
y1, y2: CD.Number;
y2 ← topContactP.y-(8-1)*ContactSize[ptype].y+metWidth;
y1 ← bottomContactN.y+4*ContactSize[ptype].y-metWidth;
m ← CDRects.CreateRect[[metWidth, y2-y1], met];
[] ← CDCells.IncludeOb[cell: cell, ob: m, position: [x: x1, y: y1]];
};
PassMs: PUBLIC PROC [r1, r2, r3, r4, r5, r6: INT ← -1] = {
IF r1>=0 THEN PassMetall[r1];
IF r2>=0 THEN PassMetall[r2];
IF r3>=0 THEN PassMetall[r3];
IF r4>=0 THEN PassMetall[r4];
IF r5>=0 THEN PassMetall[r5];
IF r6>=0 THEN PassMetall[r6];
};
VerticalM: PUBLIC PROC [row: INT, h1, h2: INT, front: BOOL�LSE] = {
m: CD.Object;
x1: CD.Number ← bottomContactN.x+(row-1)*pitch;
y1, y2: CD.Number;
IF ~front THEN x1 ← x1+ContactSize[ptype].x-metWidth;
IF ptype THEN {
h2 ← MIN[h2, 9];
y2 ← topContactP.y-(h1-1)*ContactSize[ptype].y;
y1 ← topContactP.y-(h2-1)*ContactSize[ptype].y;
}
ELSE {
h2 ← MIN[h2, 5];
y1 ← bottomContactN.y+h1*ContactSize[ptype].y;
y2 ← bottomContactN.y+h2*ContactSize[ptype].y;
};
y1 ← y1-metWidth;
y2 ← y2+metWidth;
IF ptype THEN y1 ← MAX[limitPy, y1] ELSE y2 ← MIN[y2, limitNy];
m ← CDRects.CreateRect[[metWidth, y2-y1], met];
[] ← CDCells.IncludeOb[cell: cell, ob: m, position: [x: x1, y: y1]];
};
Setup: PUBLIC PROC [design: CD.Design, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22: Rope.ROPENIL] =
BEGIN
SetUpInput[design];
pinOrder ← NIL;
ptype ← TRUE;
cell ← GetBasis[LIST[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22]];
END;
SetN: PUBLIC PROC [] = {
ptype ← FALSE
};
PinOrder: PUBLIC PROC [r: Rope.ROPENIL] = {
pinOrder ← r
};
Finish: PUBLIC PROC [name: Rope.ROPENIL] RETURNS [ob: CD.Object] = {
p: PROC[CD.Object] ← seeMeProc;
[] ← CDCells.RepositionCell[cell, NIL];
[] ← CDDirectory.Include[design: gDesign, object: cell, alternateName: name];
CDProperties.PutProp[cell, $PinOrder, pinOrder];
IF p#NIL THEN p[cell];
ob ← cell;
};
GetBasis: PROC [contents: LIST OF Rope.ROPE] RETURNS [cell: CD.Object] = {
cnt: INT ← 0;
SubCell: PROC [n: Rope.ROPENIL] = {
IF ~Rope.IsEmpty[n] THEN {
subOb: CD.Object;
SELECT TRUE FROM
Rope.Equal[n, "p1"] => subOb ← p1Ob;
Rope.Equal[n, "p2"] => subOb ← p2Ob;
Rope.Equal[n, "p3"] => subOb ← p3Ob;
Rope.Equal[n, "p4"] => subOb ← p4Ob;
Rope.Equal[n, "weakP1"] => subOb ← specialOb;
Rope.Equal[n, "connectDiffN"] => {subOb ← specialDNOb; cnt ← cnt-1};
Rope.Equal[n, "connectDiffP"] => {subOb ← specialDPOb; cnt ← cnt-1};
ENDCASE => ERROR;
[] ← CDCells.IncludeOb[cell: cell, ob: subOb, obCSystem: interrestCoords, position: [x: cnt*pitch, y: 0]];
cnt ← cnt+1;
};
};
cell ← CDCells.CreateEmptyCell[];
CDCells.SetSimplificationTreshhold[cell, 0.125, FALSE];
FOR l: LIST OF Rope.ROPE ← contents, l.rest WHILE l#NIL DO
SubCell[l.first];
ENDLOOP
};
CreateAll: CDGenerate.GeneratorProc =
BEGIN
child: CD.Object;
cnt: INT ← 0; x, y: CD.Number ← 0;
ob ← CDCells.CreateEmptyCell[];
FOR l: LIST OF RegPair ← contents, l.rest WHILE l#NIL DO
child ← CDGenerate.FetchNCall[stdCell, design, l.first.name];
IF child=NIL THEN ERROR;
[] ← CDCells.IncludeOb[cell: ob, ob: child, position: [x: x, y: y]];
cnt ← cnt+1; x ← x+child.size.x+2*pitch;
IF cnt>8 THEN {x ← 0; y ← y+child.size.y+4*pitch; cnt ← 0};
ENDLOOP;
[] ← CDDirectory.Include[design: design, object: ob, alternateName: "All-Standard-Cells"];
END;
Reset: PUBLIC PROC [] = {
contents ← NIL;
stdCell.Clear[];
Register["=p1=", GetP1];
Register["=p2=", GetP2];
Register["=p3=", GetP3];
Register["=p4=", GetP4];
};
RegPair: TYPE = RECORD[name: Rope.ROPE, proc: CDGenerate.GeneratorProc];
Register: PUBLIC PROC [name: Rope.ROPE, proc: CDGenerate.GeneratorProc] = {
[] ← stdCell.Register[name, proc];
contents ← CONS[[name, proc], contents];
};
input: Rope.ROPE ← "StdCellBase";
user: CDGenerate.Table ← CDGenerate.AssertTable["USER"];
stdCell: CDGenerate.Table ← CDGenerate.AssertTable["STDCELLGEN"];
stdCellInput: CDGenerate.Table ← CDRemote.GetTable[input];
contents: LIST OF RegPair ← NIL;
[] ← user.Register["CreateStandardCells", CreateAll, FALSE];
Reset[];
END.