-- ChipNetExtract.mesa
-- A circuit extraction package
-- that runs inside Chipmonk.
-- last modified by E. McCreight, December 21, 1982 3:26 PM
-- written by E. McCreight, November 3, 1981 3:06 PM
DIRECTORY
Ascii,
CellInstPQ,
ChipDRC,
ChipExpand,
ChipFeature,
ChipNetDefs,
ChipOrient,
ChipReticle,
ChipUserInt,
ChipWire,
CWF,
FeaturePST,
InlineDefs,
LeftFeaturePQ,
ppdefs,
RightFeaturePQ,
ZoneAllocDefs;
ChipNetExtract: PROGRAM
IMPORTS CellInstPQ, ChipDRC, ChipExpand, ChipFeature,
ChipNetDefs, ChipOrient, ChipReticle,
ChipUserInt, ChipWire, CWF, FeaturePST,
InlineDefs, LeftFeaturePQ,
ppdefs, RightFeaturePQ,
ZoneAllocDefs
EXPORTS ChipNetDefs, ppdefs =
BEGIN OPEN ppdefs,
ChipUserInt, ChipNetDefs, CellInstPQ;
aux: PUBLIC TYPE = CellProto;
currentX: PUBLIC Coord;
deltaOrigin: PUBLIC CoordPoint;
notingMark: PUBLIC BOOLEAN ← FALSE;
ItemInWorld: PUBLIC PROCEDURE[c: ItemRef]
RETURNS[CoordRect] =
BEGIN
ob: obPtr ← c.head.proto.ob;
r: Rect ← ChipOrient.MapRect[
itemInCell: getRect[ItemRefToLp[c]],
cellInstOrient: c.head.orient,
cellSize: [x: ob.size[0], y: ob.size[1]]];
min: CoordPoint ← c.head.min;
scale: Coord ← coordScale[c.head.proto.locNumScale];
RETURN[[x1: min.x+scale*r.x1, y1: min.y+scale*r.y1,
x2: min.x+scale*r.x2, y2: min.y+scale*r.y2]];
END; -- of ItemInWorld
ShowFeature: PUBLIC PROCEDURE[f: FeaturePtr] =
BEGIN
s: STRING ← [100];
CWF.SWF1[sto: s, s: "Feature on layer %s.", a: levelNames[f.lev]];
RemarkAtPoint[p: RefCoordPt[f.cover], s: s];
END;
RefCoordPt: PUBLIC PROCEDURE[r: CoordRect]
RETURNS[Point] =
BEGIN
corner1, corner2: Point;
corner1 ← ScalePointToChipmonk[[x: r.x1, y: r.y1]];
corner2 ← ScalePointToChipmonk[[x: r.x2, y: r.y2]];
RETURN[ChipOrient.RefPt[
[x1: corner1.x, y1: corner1.y,
x2: corner2.x, y2: corner2.y]]];
END; -- of RefCoordPt
DistributeNetsToSources: PROCEDURE[id: NetIdPtr]
RETURNS[NetIdPtr] =
BEGIN
nextNetId: NetIdPtr;
unclaimed: NetIdPtr ← NIL;
FOR netId: NetIdPtr ← id, nextNetId WHILE netId#NIL DO
nextNetId ← netId.next;
WITH did: netId SELECT FROM
free => {did.next ← unclaimed; unclaimed ← @did};
well => NULL;
normal =>
IF did.source#NIL THEN
{did.next ← did.source.nets; did.source.nets ← @did}
ELSE {did.next ← unclaimed; unclaimed ← @did};
ENDCASE;
ENDLOOP;
RETURN[unclaimed];
END; -- of DistributeNetsToSources
HeSetsParamsAndSaysYes: PUBLIC PROCEDURE[
s1, s2: STRING ← NIL] RETURNS[bit: BOOLEAN] =
BEGIN
DO
answer: STRING;
BEGIN
bit ← ChipUserInt.HeSaysYes[s1, s2
! Punt => GOTO SetParameters];
RETURN;
EXITS SetParameters => NULL;
END;
answer ← RequestString["Set debugging parameters:"L,
"(Pause at -M-ark)"];
IF answer.length>=1 THEN
SELECT answer[0] FROM
'm, 'M => notingMark ← NOT notingMark;
ENDCASE => NULL;
ppdefs.FreeString[answer];
ENDLOOP;
END; -- of HeSetsParamsAndSaysYes
ExtractNets: PROCEDURE[univLp: listPtr] =
BEGIN OPEN ChipOrient, LeftFeaturePQ, RightFeaturePQ;
-- Scan proceeds from left to right.
univ: Rect;
leftFq: LeftFeaturePQHandle;
rightFq: RightFeaturePQHandle;
cq, deadcq: CellInstPQHandle;
rootC: CellCallPtr;
c: InstancePtr;
lp: listPtr;
slice: ChipWire.SlicePtr;
topSelections, topItemCount: CARDINAL ← 0;
Action: TYPE = {enterCellItem, enterFeatures,
exitFeatures, exitCell, none};
delay: ARRAY Action OF Coord ← [
enterCellItem: ScaleFromChipmonk[0],
enterFeatures: ScaleFromChipmonk[featureDelay],
exitFeatures: ScaleFromChipmonk[featureDelay],
exitCell: ScaleFromChipmonk[3*featureDelay],
none: ScaleFromChipmonk[0]];
SelectNext: PROCEDURE RETURNS [next: Action] =
BEGIN
x: Coord;
next ← none;
IF CellInstPQSize[cq]>0 THEN
{next ← enterCellItem; x ← CellInstPQMin[cq].x};
IF LeftFeaturePQSize[leftFq]>0 AND
(LeftFeaturePQMin[leftFq].cover.x1+delay[enterFeatures]<
x+delay[next] OR next=none) THEN
BEGIN
next ← enterFeatures;
x ← LeftFeaturePQMin[leftFq].cover.x1
END;
IF RightFeaturePQSize[rightFq]>0 AND
(RightFeaturePQMin[rightFq].cover.x2+delay[exitFeatures]<
x+delay[next] OR next=none) THEN
BEGIN
next ← exitFeatures;
x ← RightFeaturePQMin[rightFq].cover.x2
END;
IF CellInstPQSize[deadcq]>0 AND
(CellInstPQMin[deadcq].x+delay[exitCell]<
x+delay[next] OR next=none) THEN
{next ← exitCell; x ← CellInstPQMin[deadcq].x};
END;
IF univLp=NIL THEN RETURN;
FOR lpp: listPtr ← univLp, lpp.nxt WHILE lpp#NIL DO
topItemCount ← topItemCount+1;
IF lpp.selected THEN topSelections ← topSelections+1;
ENDLOOP;
IF topSelections=0 THEN
BEGIN
Explain["Nothing selected, nothing extracted!"];
RETURN;
END;
univ ← ChipOrient.BoundingRect[univLp];
deltaOrigin ← [x: ScaleFromChipmonk[univ.x1-featureDelay],
y: ScaleFromChipmonk[univ.y1-featureDelay]];
rootC ← instanceZ.NEW[cell Instance ←
[min: ScalePointFromChipmonk[[x: 0, y: 0]],
proto: ChipExpand.MakeProto[
ob: uz.NEW[cell object ←
[p: NIL,
size: [univ.x2-univ.x1,
univ.y2-univ.y1,
univ.x2-univ.x1],
refCnt: 1,
l: snerd, -- if anybody uses this, he's in trouble
returnable: FALSE,
marked: FALSE,
varpart: cell[cnt: topItemCount, ptr: univLp]]],
name: "Top level design"],
caller: [NIL, 0],
nets: cell[]
]];
ColorOff[];
rightFq ← NewRightFeaturePQ[uz];
leftFq ← NewLeftFeaturePQ[uz];
cq ← NewCellInstPQ[uz];
deadcq ← NewCellInstPQ[uz];
slice ← ChipWire.NewSlice[];
[] ← ChipExpand.ProtoSeq[rootC];
InsertCellInstPQ[p: cq,
item: [ScalePointFromChipmonk[[univ.x1, univ.y1]].x,
[rootC, 0]]];
InsertCellInstPQ[p: deadcq,
item: [ScalePointFromChipmonk[[univ.x2, univ.y2]].x,
[rootC, 0]]];
DO SELECT SelectNext[] FROM
enterCellItem =>
BEGIN -- enter a new item from a cell
lps: ListPtrSeqPtr;
cir: ItemRef;
idx: CellIndex;
cqi: CellInstPt ← ExtractCellInstPQ[cq];
[x: currentX, call: cir] ← cqi;
[head: c, idx: idx] ← cir;
lps ← c.proto.seq[orientToSortClass[c.orient]];
lp ← lps[idx];
ChipExpand.MakeInstance[item: [c, idx],
slice: slice, futureFeatures: leftFq, presentFeatures: rightFq,
cellQ: cq, deadCellQ: deadcq];
END;
enterFeatures =>
BEGIN
EnterAFeature: PROCEDURE[f: FeaturePtr] =
BEGIN
IF notingMark THEN
ChipFeature.NoteMark[f.cover,
"New %s feature at f↑ contains mark.", levelNames[f.lev]];
ChipWire.WireEntered[f, slice];
FeaturePST.InsertFeaturePST[p: slice[f.lev], item: f];
InsertRightFeaturePQ[rightFq, f];
END; -- of EnterAFeature
sampleCover: CoordRect ← LeftFeaturePQMin[leftFq].cover;
currentX ← sampleCover.x1;
ChipFeature.BWCursor[world: [
x: sampleCover.x1, y: sampleCover.y1]];
MapEqualLeftFeaturePQ[p: leftFq, proc: EnterAFeature];
IF ChipDRC.doingDRC THEN ChipDRC.LeftEdges[leftFq];
DeleteEqualLeftFeaturePQ[leftFq];
END;
exitFeatures =>
BEGIN
ExitAFeature: PROCEDURE[f: FeaturePtr] =
BEGIN
FeaturePST.DeleteFeaturePST[p: slice[f.lev], item: f];
IF notingMark THEN
ChipFeature.NoteMark[f.cover,
"Old %s feature at f↑ contains mark.", levelNames[f.lev]];
ChipWire.WireLeft[f, slice];
IF NOT ChipDRC.doingDRC THEN
f ← ChipFeature.DestroyFeature[f];
END; -- of ExitAFeature
currentX ← RightFeaturePQMin[rightFq].cover.x2;
MapEqualRightFeaturePQ[p: rightFq, proc: ExitAFeature];
IF ChipDRC.doingDRC THEN ChipDRC.RightEdges[rightFq];
DeleteEqualRightFeaturePQ[rightFq];
END;
exitCell =>
BEGIN
cqi: CellInstPt ← ExtractCellInstPQ[deadcq];
[x: currentX, call: [head: c]] ← cqi;
ChipExpand.ExitInstance[c];
END;
ENDCASE => EXIT;
ENDLOOP;
slice ← ChipWire.DestroySlice[slice];
cq ← DestroyCellInstPQ[cq];
leftFq ← DestroyLeftFeaturePQ[leftFq];
rightFq ← DestroyRightFeaturePQ[rightFq];
IF ChipDRC.doingDRC THEN
BEGIN
currentX ← ScalePointFromChipmonk[[univ.x2, univ.y2]].x+1;
FOR id: NetIdPtr ← allNets, id.next WHILE id#NIL DO
ChipDRC.PurgeDRCViolations[id];
ENDLOOP;
END;
allNets ← DistributeNetsToSources[allNets];
ChipDRC.FinishDRC[rootC];
WriteSimFile[rootC];
ColorOn[];
END; -- of ExtractNets
-- M a i n P r o g r a m
featureZ: PUBLIC UNCOUNTED ZONE ←
ZoneAllocDefs.GetAnXMZone[checkSegments: TRUE];
netZ: PUBLIC UNCOUNTED ZONE ←
ZoneAllocDefs.GetAnXMZone[checkSegments: TRUE];
netIdZ: PUBLIC UNCOUNTED ZONE ←
ZoneAllocDefs.GetAnXMZone[checkSegments: TRUE];
instanceZ: PUBLIC UNCOUNTED ZONE ←
ZoneAllocDefs.GetAnXMZone[checkSegments: TRUE];
clusterZ: PUBLIC UNCOUNTED ZONE ←
ZoneAllocDefs.GetAnXMZone[checkSegments: TRUE];
uz: PUBLIC UNCOUNTED ZONE ←
ZoneAllocDefs.GetAnXMZone[checkSegments: TRUE];
transZ: PUBLIC UNCOUNTED ZONE ←
ZoneAllocDefs.GetAnXMZone[checkSegments: TRUE];
levelNames: PUBLIC ARRAY ExtractLevel OF STRING ← ALL[NIL];
isConductor: PUBLIC ARRAY ExtractLevel OF BOOLEAN ←
ALL[FALSE];
levelNames[unknown] ← "?";
levelNames[nWell] ← "nWell";
levelNames[nWellRequired] ← "nWellRequired";
levelNames[nWellForbidden] ← "nWellForbidden";
levelNames[pWell] ← "pWell";
levelNames[pWellRequired] ← "pWellRequired";
levelNames[pWellForbidden] ← "pWellForbidden";
levelNames[nDepletion] ← "nDepletionImplant";
levelNames[nDepletionRequired] ← "nDepletionRequired";
levelNames[nDepletionForbidden] ← "nDepletionForbidden";
levelNames[nBuriedContact] ← "nBuriedContact";
levelNames[nBuriedContactRequired] ← "nBuriedContactRequired";
levelNames[nBuriedContactForbidden] ← "nBuriedContactForbidden";
levelNames[thinOx] ← "ThinOx";
levelNames[nPlus] ← "nPlus";
levelNames[nPlusRequired] ← "nPlusRequired";
levelNames[nPlusForbidden] ← "nPlusForbidden";
levelNames[pPlus] ← "pPlus";
levelNames[pPlusRequired] ← "pPlusRequired";
levelNames[pPlusForbidden] ← "pPlusForbidden";
levelNames[nImplant] ← "nSDImplant";
levelNames[pImplant] ← "pSDImplant";
levelNames[nGate] ← "nGate";
levelNames[nGateRequired] ← "nGateRequired";
levelNames[nGateForbidden] ← "nGateForbidden";
levelNames[pGate] ← "pGate";
levelNames[pGateRequired] ← "pGateRequired";
levelNames[pGateForbidden] ← "pGateForbidden";
levelNames[poly] ← "Poly";
levelNames[polyRequired] ← "polyRequired";
levelNames[polyForbidden] ← "polyForbidden";
levelNames[cut] ← "Cut";
levelNames[metal] ← "Metal";
levelNames[via] ← "Via";
levelNames[metal2] ← "Metal2";
levelNames[pad] ← "Pad";
isConductor[nPlus] ← TRUE;
isConductor[pPlus] ← TRUE;
isConductor[poly] ← TRUE;
isConductor[metal] ← TRUE;
isConductor[metal2] ← TRUE;
BEGIN
ENABLE
BEGIN
Punt => GOTO Exit; -- for exits
UNWIND => ColorOn[];
END;
SELECT TRUE FROM
HeSetsParamsAndSaysYes["Extract selected circuit?"L] =>
BEGIN
ChipDRC.SetupDRC[
HeSetsParamsAndSaysYes[
"Shall I also check design rules?"L,
"(..slows things down a bit...)"L]];
ExtractNets[masterList];
END;
HeSetsParamsAndSaysYes["Then I'll make reticles, OK?"L] =>
ChipReticle.ExtractReticles[masterList];
ENDCASE => Explain["That's all I can do at the moment."L];
EXITS Exit => NULL;
END;
-- give back the storage we allocated
featureZ ← ZoneAllocDefs.DestroyAnXMZone[featureZ];
netZ ← ZoneAllocDefs.DestroyAnXMZone[netZ];
netIdZ ← ZoneAllocDefs.DestroyAnXMZone[netIdZ];
instanceZ ← ZoneAllocDefs.DestroyAnXMZone[instanceZ];
clusterZ ← ZoneAllocDefs.DestroyAnXMZone[clusterZ];
uz ← ZoneAllocDefs.DestroyAnXMZone[uz];
transZ ← ZoneAllocDefs.DestroyAnXMZone[transZ];
END. -- of ChipNetExtract