-- ChipWireImpl.mesa -- Subroutines to maintain and use of a slice of features -- with constant x. -- last modified by E. McCreight, November 5, 1982 11:28 AM -- written by E. McCreight, March 5, 1982 10:12 AM DIRECTORY ChipNetDefs, ChipDRC, ChipExpand, ChipWire, FeaturePST, ppdddefs, ppdefs, StringDefs; ChipWireImpl: PROGRAM IMPORTS ChipDRC, ChipExpand, ChipNetDefs, FeaturePST, ppdddefs, StringDefs EXPORTS ChipWire = BEGIN OPEN ppdefs, ChipNetDefs, FeaturePST, ChipExpand, ChipDRC, ChipWire; NewSlice: PUBLIC PROCEDURE RETURNS[SlicePtr] = BEGIN slice: SlicePtr ← uz.NEW[Slice]; FOR lev: ExtractLevel IN ExtractLevel DO slice[lev] ← NewFeaturePST[uz]; ENDLOOP; RETURN[slice]; END; DestroySlice: PUBLIC PROCEDURE[slice: SlicePtr] RETURNS[SlicePtr] = BEGIN FOR lev: ExtractLevel IN ExtractLevel DO slice[lev] ← DestroyFeaturePST[slice[lev]]; ENDLOOP; uz.FREE[@slice]; RETURN[NIL]; END; WireEntered: PUBLIC PROCEDURE[f: FeaturePtr, slice: SlicePtr] = BEGIN CheckBuriedContact: PROCEDURE[item: FeaturePtr] = BEGIN BogusTransistor1: PROCEDURE[int: Interval] = BEGIN IF int.min<int.max THEN NoteViolation[[ place: RefCoordPt[SharedArea[f.cover, item.cover]], type: bogusTransistor, lev1: nPlus]]; END; MergeNetsInBuriedContact: PROCEDURE[int: Interval, repItem: FeaturePtr] = {IF int.min<int.max THEN MergeFeatureNets[f, item]}; IF HaveSharedArea[f.cover, item.cover] THEN ClassifyFeaturePSTInterval[p: slice[nBuriedContact], int: SharedYInterval[f, item], covered: MergeNetsInBuriedContact, gap: BogusTransistor1]; END; BogusPTransistor: PROCEDURE[r: CoordRect] = {NoteViolation[[ place: RefCoordPt[r], type: bogusTransistor, lev1: pPlus]]}; JoinConductors[f, slice]; SELECT f.lev FROM poly => BEGIN SearchFeaturePST[p: slice[nPlus], int: [min: f.cover.y1, max: f.cover.y2], touch: CheckBuriedContact]; OverlapIsViolation[p: slice[pPlus], f: f, problem: BogusPTransistor]; END; pPlus => BEGIN OverlapIsViolation[p: slice[poly], f: f, problem: BogusPTransistor]; END; nPlus => BEGIN SearchFeaturePST[p: slice[poly], int: [min: f.cover.y1, max: f.cover.y2], touch: CheckBuriedContact]; END; ENDCASE => NULL; END; -- of WireEntered WireLeft: PUBLIC PROCEDURE[f: FeaturePtr, slice: SlicePtr] = BEGIN deltaSides: INTEGER ← 2; deltaWidth: Coord ← f.cover.y2-f.cover.y1; dw: locNum; -- deltaWidth in locNum's LeaveTouch: PROCEDURE[int: Interval, repItem: FeaturePtr] = BEGIN deltaWidth ← deltaWidth- (MIN[int.max, yMax]-MAX[int.min, yMin]); deltaSides ← deltaSides-2; END; PolyIsBogusTransistor: PROCEDURE[item: FeaturePtr] = BEGIN difFeature ← item; SearchFeaturePST[p: slice[poly], int: SharedYInterval[difFeature, f], touch: BogusTransistor2]; END; BogusTransistor2: PROCEDURE[item: FeaturePtr] = {NoteViolation[[ place: RefCoordPt[ SharedArea[difFeature.cover, item.cover]], type: bogusTransistor, lev1: nPlus]]}; cond: Conductors; caps: LayerCapPtr; id: NormalNetIdPtr; difFeature: FeaturePtr; yMin: Coord ← f.cover.y1; yMax: Coord ← f.cover.y2; SELECT f.lev FROM nPlus, pPlus => cond ← diffusion; poly => cond ← poly; metal => cond ← metal; metal2 => cond ← metal2; nBuriedContact => BEGIN SearchFeaturePST[p: slice[nPlus], int: [min: f.cover.y1, max: f.cover.y2], touch: PolyIsBogusTransistor]; RETURN; END; ENDCASE => RETURN; UpdateAreas[GetNormalNetId[@f.net]]; ClassifyFeaturePSTInterval[p: slice[f.lev], int: [min: yMin-1, max: yMax+1], covered: LeaveTouch, gap: NullFeatureGap]; dw ← ScaleToChipmonk[deltaWidth]; id ← GetNormalNetId[@f.net]; caps ← @id.caps[cond]; caps.cutSides ← caps.cutSides-deltaSides; caps.cutWidth ← caps.cutWidth-dw; caps.perimeter ← caps.perimeter+dw; WITH dc: f.caller.head SELECT FROM cell => BEGIN lp: listPtr ← ItemRefToLp[f.caller]; IF ppdddefs.getTextProp[lp]#NIL THEN SetupCluster[(f.net ← CanonNet[f.net]), f.caller, @dc, ppdddefs.getTextProp[lp].s]; END; ENDCASE => NULL; END; -- of WireLeft JoinConductors: PROCEDURE[f: FeaturePtr, slice: SlicePtr] = BEGIN deltaSides: INTEGER ← 2; deltaWidth: Coord ← f.cover.y2-f.cover.y1; dw: locNum; -- deltaWidth in locNum's yMin: Coord ← f.cover.y1; yMax: Coord ← f.cover.y2; Strength: TYPE = {wire, well, none}; StrengthCond: TYPE = RECORD[ strength: Strength, cond: Conductors ]; EnterTouch: PROCEDURE[int: Interval, repItem: FeaturePtr] = BEGIN deltaWidth ← deltaWidth- (MIN[int.max, yMax]-MAX[int.min, yMin]); deltaSides ← deltaSides-2; MergeFeatureNets[f, repItem]; END; strength: Strength; cond: Conductors; [strength: strength, cond: cond] ← SELECT f.lev FROM nPlus, pPlus => StrengthCond[wire, diffusion], poly => StrengthCond[wire, poly], metal => StrengthCond[wire, metal], metal2 => StrengthCond[wire, metal2], pWell, nWell => StrengthCond[well, diffusion], ENDCASE => StrengthCond[none, diffusion]; SELECT strength FROM wire => BEGIN caps: LayerCapPtr; IF f.net=NIL THEN BEGIN nid: NormalNetIdPtr; f.net ← NewNet[]; nid ← GetNormalNetId[@f.net]; nid.source ← NearestCellInstance[f.caller.head]; nid.final ← [lev: f.lev, r: f.cover]; END; UpdateAreas[GetNormalNetId[@f.net]]; ClassifyFeaturePSTInterval[p: slice[f.lev], int: [min: yMin-1, max: yMax+1], covered: EnterTouch, gap: NullFeatureGap]; dw ← ScaleToChipmonk[deltaWidth]; caps ← @GetNormalNetId[@f.net].caps[cond]; caps.cutSides ← caps.cutSides+deltaSides; caps.cutWidth ← caps.cutWidth+dw; caps.perimeter ← caps.perimeter+dw; END; well => BEGIN IF f.net=NIL THEN BEGIN cn: CanonNetPtr ← f.net ← NewNet[]; cn.id.details ← well[attachedTo: NIL]; cn.id.final ← [lev: f.lev, r: f.cover]; END; ClassifyFeaturePSTInterval[p: slice[f.lev], int: [min: yMin-1, max: yMax+1], covered: EnterTouch, gap: NullFeatureGap]; END; ENDCASE => NULL; END; -- of JoinConductors MergeFeatureNets: PROCEDURE[f1, f2: FeaturePtr] = BEGIN id: NetIdPtr; net: netPtr; SELECT f1.net FROM #NIL => SELECT f2.net FROM #NIL => net ← MergeNets[f1.net, f2.net]; ENDCASE => net ← RefCanonNet[f1.net]; ENDCASE => SELECT f2.net FROM #NIL => net ← RefCanonNet[f2.net]; ENDCASE => BEGIN net ← NewNet[2]; SELECT f1.lev FROM nWell, pWell => CanonNet[net].id.details ← well[attachedTo: NIL]; ENDCASE => GetNormalNetId[@net].source ← NearestCellInstance[f1.caller.head]; END; id ← (f1.net ← f2.net ← CanonNet[net]).id; IF id.final.r.x2<f1.cover.x2 THEN id.final ← [lev: f1.lev, r: f1.cover]; IF id.final.r.x2<f2.cover.x2 THEN id.final ← [lev: f2.lev, r: f2.cover]; END; -- of MergeFeatureNets HaveSharedArea: PUBLIC PROCEDURE[r1, r2: CoordRect] RETURNS[BOOLEAN] = {RETURN[MAX[r1.x1, r2.x1]<MIN[r1.x2, r2.x2] AND MAX[r1.y1, r2.y1]<MIN[r1.y2, r2.y2]]}; SharedArea: PUBLIC PROCEDURE[r1, r2: CoordRect] RETURNS[CoordRect] = {RETURN[[x1: MAX[r1.x1, r2.x1], x2: MIN[r1.x2, r2.x2], y1: MAX[r1.y1, r2.y1], y2: MIN[r1.y2, r2.y2]]]}; SharedYInterval: PROCEDURE[f1, f2: FeaturePtr] RETURNS[Interval] = {RETURN[[min: MAX[f1.cover.y1, f2.cover.y1], max: MIN[f1.cover.y2, f2.cover.y2]]]}; OverlapIsViolation: PUBLIC PROCEDURE[p: FeaturePSTHandle, f: FeaturePtr, problem: PROCEDURE[r: CoordRect]] = BEGIN CouldBeBad: PROCEDURE[item: FeaturePtr] = {IF HaveSharedArea[f.cover, item.cover] THEN problem[SharedArea[f.cover, item.cover]]}; IF f.cover.y1+1<=f.cover.y2-1 THEN SearchFeaturePST[p: p, int: [f.cover.y1+1, f.cover.y2-1], touch: CouldBeBad]; END; SetupCluster: PROCEDURE[fNet: CanonNetPtr, source: ItemRef, c: CellCallPtr, name: STRING] = BEGIN FOR cluster: ClusterPtr ← c.clusters, cluster.next WHILE cluster#NIL DO IF StringDefs.EquivalentString[name, cluster.netName] THEN BEGIN FOR mustConnect: MustConnectPtr ← @cluster.first, mustConnect.next WHILE mustConnect#NIL DO IF (mustConnect.net ← CanonNet[mustConnect.net])=fNet THEN GOTO Finished; ENDLOOP; cluster.first.next ← clusterZ.NEW[MustConnect ← [ next: cluster.first.next, net: RefCanonNet[fNet], source: source]]; GOTO Finished; END; ENDLOOP; c.clusters ← clusterZ.NEW[Cluster ← [next: c.clusters, netName: name, first: [net: RefCanonNet[fNet], source: source]]]; EXITS Finished => NULL END; END. -- of ChipWireImpl