-- ChipWireImpl.mesa
-- Subroutines to maintain and use of a slice of features
-- with constant x.
-- last modified by E. McCreight, August 31, 1983 9:50 AM
-- written by E. McCreight, March 5, 1982 10:12 AM
DIRECTORY
ChipNetDefs,
ChipDRC,
ChipExpand,
ChipWire,
FeaturePST,
ppdefs;
ChipWireImpl: PROGRAM
IMPORTS ChipDRC, ChipExpand, ChipNetDefs, FeaturePST
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
ContactToWell: PROC [item: FeaturePtr] = {MergeFeatureNets[f, item]};
CheckBuriedContact: PROCEDURE[item: FeaturePtr] =
BEGIN
BogusTransistor1: PROCEDURE[int: Interval] =
BEGIN
IF int.min<int.max THEN
NoteViolation[[
place: RefCoordPt[SharedArea[f.cover, item.cover]],
info: bogusTransistor[lev: 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],
info: bogusTransistor[lev: 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;
nwel =>
BEGIN
SearchFeaturePST[p: slice[nwelCont],
int: [min: f.cover.y1, max: f.cover.y2],
touch: ContactToWell];
END;
nwelCont =>
BEGIN
SearchFeaturePST[p: slice[nwel],
int: [min: f.cover.y1, max: f.cover.y2],
touch: ContactToWell];
END;
pwel =>
BEGIN
SearchFeaturePST[p: slice[pwelCont],
int: [min: f.cover.y1, max: f.cover.y2],
touch: ContactToWell];
END;
pwelCont =>
BEGIN
SearchFeaturePST[p: slice[pwel],
int: [min: f.cover.y1, max: f.cover.y2],
touch: ContactToWell];
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]],
info: bogusTransistor[lev: nPlus]]]};
cond: Conductors;
caps: LayerCapPtr;
id: NormalNetIdPtr;
difFeature: FeaturePtr;
yMin: Coord ← f.cover.y1;
yMax: Coord ← f.cover.y2;
SELECT f.lev FROM
nPlus, nwelCont => cond ← ndif;
pPlus, pwelCont => cond ← pdif;
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
sn: Atom = FindPropValue[ItemRefToLp[f.caller], signalName];
IF sn#NIL THEN
SetupCluster[(f.net ← CanonNet[f.net]), f.caller, @dc, sn];
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, nwelCont => StrengthCond[wire, ndif],
pPlus, pwelCont => StrengthCond[wire, pdif],
poly => StrengthCond[wire, poly],
metal => StrengthCond[wire, metal],
metal2 => StrengthCond[wire, metal2],
pWell => StrengthCond[well, pdif],
nWell => StrengthCond[well, ndif],
ENDCASE => StrengthCond[none, ndif];
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
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: Atom] =
BEGIN
FOR cluster: ClusterPtr ← c.clusters, cluster.next
WHILE cluster#NIL DO
IF 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