-- 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