NMosContactsImpl.mesa (part of ChipNDale)
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
by Christian Jacobi, June 24, 1983 5:03 pm
last edited Christian Jacobi, March 25, 1986 4:41:25 pm PST
DIRECTORY
NMosContacts,
CD,
CDCallSpecific,
CDIO,
CDBasics,
CDLRUCache,
CDOrient,
CDStretchyExtras,
NMos,
Rope,
TokenIO;
NMosContactsImpl: CEDAR PROGRAM
IMPORTS CDCallSpecific, CDBasics, CDIO, CDLRUCache, CDOrient, CDStretchyExtras, NMos, TokenIO
EXPORTS NMosContacts =
BEGIN OPEN NMos;
lambda: CD.Number = NMos.lambda;
ContactType: TYPE = NMosContacts.ContactType;
ContactPtr: TYPE = NMosContacts.ContactPtr;
ContactRec: TYPE = NMosContacts.ContactRec;
wXExtension: CD.Number = 2*lambda;
lXExtension: CD.Number = 2*lambda;
difCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
polyCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
dsCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
butCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
burCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
mmCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 5, aequivalenceProc: Aequivalent, newProc: NewCont];
ToPosition: PROC [x: REF] RETURNS [class: CD.Position] =
--y field defaults to lambda, x field defaults to 0
--[0, 0] if not done
BEGIN
IF x=NIL THEN class ← [0, lambda]
ELSE WITH x SELECT FROM
rp: REF CD.Position => class ← rp^;
rn: REF CD.Number => class ← [0, rn^];
ENDCASE => class ← [0, 0];
END;
Aequivalent: PROC[mySpecific, other: REF ANY] RETURNS [BOOL] = {
WITH other SELECT FROM
p2: ContactPtr => RETURN [NARROW[mySpecific, ContactPtr]^=p2^];
ENDCASE => RETURN [FALSE]
};
NewCont: PROC [] RETURNS [CD.Object] = {
ob: CD.Object ← NEW[CD.ObjectRep];
ob.specificRef ← NEW[ContactRec];
RETURN [ob]
};
MatchContact: PROC [me: CD.Object, r: CD.Rect, layer: CD.Layer, prim: BOOL, horz: BOOL] RETURNS [BOOL] =
BEGIN
IF layer=me.layer THEN RETURN [TRUE]
ELSE {
cp: ContactPtr = NARROW[me.specificRef];
RETURN [
SELECT cp.typ FROM
burr => (layer=NMos.pol),
mDif => (layer=NMos.met),
butt => (layer=NMos.met OR layer=NMos.pol),
mPol => (layer=NMos.met),
mm2 => (layer=NMos.met2),
ENDCASE => FALSE
]
}
END;
Describe: PROC[me: CD.Object] RETURNS [Rope.ROPE] =
BEGIN
RETURN [
SELECT NARROW[me.specificRef, ContactPtr].typ FROM
burr => "buried contact",
mDif => "dif contact",
butt => "button contact",
mPol => "poly contact",
mm2 => "via",
ENDCASE => "unknown contact"
]
END;
-- Dif and Pol -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForDifPolCon: CD.ObjectClass ~ RegisterObjectClass[$NMosContactDifAndPol];
difpolRimWidth: CD.Number = lambda;
CreateDifCon: PUBLIC PROC [l: CD.Number] RETURNS [CD.Object] =
--connect diffusion with metal
BEGIN
cob: CD.Object ~ difCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
l ← MAX[l, butConSX];
cp.typ ← mDif;
cob.class ← pForDifPolCon; -- does not use specicRef !
cob.layer ← dif;
cob.size ← [butConSX, l];
RETURN [difCache.ReplaceByAequivalent[cob]]
END;
CreatePolyCon: PUBLIC PROC [l: CD.Number] RETURNS [CD.Object] =
--connect poly with metal
BEGIN
cob: CD.Object ~ polyCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
l ← MAX[l, butConSX];
cp.typ ← mPol;
cob.class ← pForDifPolCon; -- does not use specicRef !
cob.size ← [butConSX, l];
cob.layer ← pol;
RETURN [polyCache.ReplaceByAequivalent[cob]]
END;
LengthenDifPol: CDCallSpecific.CallProc =
BEGIN
amount: CD.Position = ToPosition[x];
IF amount.y=0 OR amount.x#0 THEN done ← FALSE
ELSE {
cp: ContactPtr ← NARROW[inst.ob.specificRef];
ap: CD.Instance ← NEW[CD.InstanceRep ← inst^];
sz: CD.Position ← CDBasics.AddPoints[inst.ob.size, amount];
IF sz.x<=0 OR sz.y<=0 THEN {done ← FALSE; RETURN};
IF inst.ob.layer=pol THEN ap.ob ← CreatePolyCon[sz.y] ELSE ap.ob ← CreateDifCon[sz.y];
include ← LIST[ap];
removeMe ← TRUE;
repaintMe ← amount.y<0;
repaintInclude ← amount.y>0;
}
END;
DefaultenDifPol: CDCallSpecific.CallProc =
BEGIN
cp: ContactPtr ← NARROW[inst.ob.specificRef];
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
IF inst.ob.layer=pol THEN ap.ob ← CreatePolyCon[4*lambda] ELSE ap.ob ← CreateDifCon[4*lambda];
include ← LIST[ap];
removeMe ← TRUE;
repaintMe ← TRUE;
repaintInclude ← TRUE;
END;
ReadDifPolCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
lev: CD.Layer = CDIO.ReadLayer[];
IF lev=pol THEN RETURN [ CreatePolyCon[TokenIO.ReadInt[]] ]
ELSE RETURN [ CreateDifCon[TokenIO.ReadInt[]] ]
END;
WriteDifPolCon: CD.InternalWriteProc -- PROC [me: Object] -- =
BEGIN
CDIO.WriteLayer[me.layer];
TokenIO.WriteInt[me.size.y];
END;
SetLengthDifPol: CDCallSpecific.CallProc =
BEGIN
newLength: CD.Number ← NARROW[x, REF CD.Number]^;
oldLength: CD.Number ← inst.ob.size.y;
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
IF inst.ob.layer=dif THEN
ap.ob ← CreateDifCon[newLength] ELSE ap.ob ← CreatePolyCon[newLength];
include←LIST[ap];
removeMe←TRUE;
IF newLength>oldLength THEN repaintInclude←TRUE ELSE repaintMe←TRUE;
END;
DrawDifAndPolContact: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] =
--does not read specificRef !!!!!!
BEGIN
IF CDBasics.Intersect[CDOrient.RectAt[pos, inst.ob.size, orient], pr.interestClip] THEN
BEGIN
r: CD.Rect = CDOrient.RectAt[pos, inst.ob.size, orient];
pr.drawRect[r, met, pr];
pr.drawRect[r, inst.ob.layer, pr];
pr.drawRect[CDBasics.Extend[r, -difpolRimWidth], cut, pr];
END
END;
-- DifShort -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForDifShorts: CD.ObjectClass ~ RegisterObjectClass[$NMosContactDifShort];
difShortRimWidth: CD.Number = lambda;
CreateDifShortCon: PUBLIC PROC [] RETURNS [CD.Object] =
BEGIN
cob: CD.Object ~ dsCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
cp.typ ← difShort;
cob.class ← pForDifShorts;
cob.layer ← dif;
cob.size ← [butConSX, 8*lambda];
RETURN [dsCache.ReplaceByAequivalent[cob]]
END;
ReadDifShortCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
RETURN [ CreateDifShortCon[] ]
END;
WriteDifShortCon: CD.InternalWriteProc -- PROC [me: Object] -- =
BEGIN
END;
DrawDifShortContact: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
Draw: PROC[r: CD.Rect, l: CD.Layer] = INLINE
uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: inst.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
IF CDBasics.Intersect[CDOrient.RectAt[pos, inst.ob.size, orient], pr.interestClip] THEN
BEGIN
r: CD.Rect = CDOrient.RectAt[[0, 0], inst.ob.size];
mr: CD.Rect = CDBasics.Extend[r, -difShortRimWidth];
h: CD.Number = (r.y2-r.y1)/2;
Draw[r, met];
Draw[[x1: r.x1, y1: r.y1, x2: r.x2, y2: r.y1+h], inst.ob.layer];
Draw[[x1: r.x1, y1: r.y1+h, x2: r.x2, y2: r.y2], nwelCont];
Draw[[x1: mr.x1, x2: mr.x2, y1: mr.y1, y2: mr.y1+2*lambda], cut];
Draw[[x1: mr.x1, x2: mr.x2, y1: mr.y2-2*lambda, y2: mr.y2], cut];
END
END;
-- But -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForButContact: CD.ObjectClass ~ RegisterObjectClass[$NMosContactBut];
butConSX: CD.Number = 4*lambda;
butConSY: CD.Number = 6*lambda;
butContactPolyYS: CD.Number = 3*lambda;
butContactDiffY: CD.Number = butContactPolyYS-lambda;
butContactRimWidth: CD.Number = lambda;
CreateButCon: PUBLIC PROC [] RETURNS [CD.Object] =
--connects metal with poly and diffusion
BEGIN
cob: CD.Object ~ butCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
cp.typ ← butt;
cob.class ← pForButContact;
cob.layer ← dif;
cob.size ← [butConSX, butConSY];
RETURN [butCache.ReplaceByAequivalent[cob]]
END;
ReadButCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
RETURN [ CreateButCon[] ]
END;
WriteButCon: CD.InternalWriteProc -- PROC [me: Object] -- =
BEGIN
END;
DrawButContact: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
Draw: PROC[r: CD.Rect, l: CD.Layer] = INLINE
--uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: inst.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
--DrawButContact
Draw[[0, 0, butConSX, butConSY], met];
Draw[[0, 0, butConSX, butContactPolyYS], pol];
Draw[[0, butContactDiffY, butConSX, butConSY], inst.ob.layer];
Draw[[butContactRimWidth, butContactRimWidth,
butConSX-butContactRimWidth, butConSY-butContactRimWidth], cut]; 
END;
-- Bur -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForBurCon: CD.ObjectClass ~ RegisterObjectClass[$NMosBurContact];
CreateBurCon: PUBLIC PROC [w, l: CD.Number,
wex: CD.Number←wXExtension,
lex: CD.Number←lXExtension] RETURNS [CD.Object] =
-- connects diffusion with poly without accessing metal
BEGIN
cob: CD.Object ~ burCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
burAct: CD.Number = 2*lambda;
actWidth, xMargins: CD.Number;
wex ← MAX[0, wex];
lex ← MAX[0, lex];
xMargins ← burAct +
(IF wex< burAct THEN MAX[wex+lambda, burAct] ELSE wex);
actWidth ← MAX[2*lambda, w-xMargins];
w ← actWidth+xMargins;
l ← MAX[l,
(IF lex<burAct THEN MAX[lex+lambda, burAct] ELSE lex)*2+lambda*MAX[6*lambda/actWidth, 2]
];
cp.typ ← burr;
cp.wExt ← wex;
cp.lExt ← lex;
cob.class ← pForBurCon;
cob.size ← [w, l];
cob.layer ← dif;
RETURN [burCache.ReplaceByAequivalent[cob]]
END;
ReadBurCon: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
w: INT = TokenIO.ReadInt[];
l: INT = TokenIO.ReadInt[];
wex: INT = TokenIO.ReadInt[];
lex: INT = TokenIO.ReadInt[];
RETURN [ CreateBurCon[w, l, wex, lex] ]
END;
WriteBurCon: CD.InternalWriteProc -- PROC [me: Object] -- =
BEGIN
cp: ContactPtr = NARROW[me.specificRef];
TokenIO.WriteInt[me.size.x];
TokenIO.WriteInt[me.size.y];
TokenIO.WriteInt[cp.wExt];
TokenIO.WriteInt[cp.lExt];
END;
DrawMeForBurrNMosContacts: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
Draw: PROC[r: CD.Rect, l: CD.Layer] = INLINE
uses outer stuff!!
BEGIN
pr.drawRect[
CDOrient.MapRect[
itemInCell: r,
cellSize: inst.ob.size,
cellInstOrient: orient,
cellInstPos: pos],
l,
pr];
END;
--DrawMeForBurrNMosContacts
class: ContactPtr = NARROW[inst.ob.specificRef];
dBur: CD.Number = lambda/2;
burAct: CD.Number = lambda*2;
diffBur: CD.Position = [
x: IF class.wExt<burAct THEN MAX[class.wExt+lambda, burAct] ELSE class.wExt-lambda,
y: IF class.lExt<burAct THEN MAX[class.lExt+lambda, burAct] ELSE class.lExt-lambda
];
Draw[[dBur, dBur, inst.ob.size.x-dBur, inst.ob.size.y-dBur], bur];
Draw[[burAct, class.lExt, inst.ob.size.x-class.wExt, inst.ob.size.y-class.lExt], pol];
Draw[[lambda, diffBur.y, inst.ob.size.x-diffBur.x, inst.ob.size.y-diffBur.y], inst.ob.layer];
END;
LengthenBur: CDCallSpecific.CallProc =
BEGIN
amount: CD.Position = ToPosition[x];
IF amount.y=0 AND amount.x=0 THEN done ← FALSE
ELSE {
cp: ContactPtr = NARROW[inst.ob.specificRef];
ap: CD.Instance = NEW[CD.InstanceRep ← inst^];
ap.ob ← CreateBurCon[
w: inst.ob.size.x+amount.x,
l: inst.ob.size.y+amount.y,
wex: cp.wExt,
lex: cp.lExt
];
include ← LIST[ap];
removeMe ← TRUE;
repaintMe ← amount.x<0 OR amount.y<0;
repaintInclude ← amount.x>0 OR amount.y>0;
};
END;
ChangeExtensionBur: CDCallSpecific.CallProc =
BEGIN
amount: CD.Position = ToPosition[x];
IF amount.y=0 AND amount.x=0 THEN done ← FALSE
ELSE {
cp: ContactPtr ← NARROW[inst.ob.specificRef];
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
ap.ob ← CreateBurCon[
w: inst.ob.size.x+amount.x,
l: inst.ob.size.y+amount.y,
wex: cp.wExt+amount.x,
lex: cp.lExt+amount.y
];
include ← LIST[ap];
removeMe ← TRUE;
repaintMe ← amount.x<0 OR amount.y<0;
repaintInclude ← amount.x>0 OR amount.y>0;
}
END;
SetLengthBur: CDCallSpecific.CallProc =
BEGIN
newLength: CD.Number ← NARROW[x, REF CD.Number]^;
oldLength: CD.Number ← inst.ob.size.y;
cp: ContactPtr ← NARROW[inst.ob.specificRef];
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
ap.ob ← CreateBurCon[w: inst.ob.size.x, l: newLength, wex: cp.wExt, lex: cp.lExt];
include ← LIST[ap];
removeMe ← TRUE;
IF newLength>oldLength THEN repaintInclude ← TRUE ELSE repaintMe ← TRUE;
END;
DefaultenBur: CDCallSpecific.CallProc =
BEGIN
cp: ContactPtr ← NARROW[inst.ob.specificRef];
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
ap.ob ← CreateBurCon[w: inst.ob.size.x, l: 4*lambda, wex: cp.wExt, lex: cp.lExt];
include←LIST[ap];
removeMe←TRUE;
repaintMe←TRUE;
repaintInclude←TRUE;
END;
-- Mm -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pForVia: CD.ObjectClass ~ RegisterObjectClass[$NMosMmContact];
mmRimWidth: CD.Number = lambda;
cut2min: CD.Number = 3*lambda;
CreateMmCon: PUBLIC PROC [l: CD.Number,
wex: CD.Number←wXExtension,
lex: CD.Number←lXExtension] RETURNS [CD.Object] =
-- ignores wex and lex in chipmonk, why???
-- connects two layers of metal
BEGIN
cob: CD.Object ~ mmCache.UnusedOrNew[];
cp: ContactPtr ~ NARROW[cob.specificRef];
mins: CD.Number = cut2min+2*mmRimWidth;
oldMins: CD.Number = cut2min+2*--mmRimWidth--2*lambda;
l ← MAX[l, mins];
cp.typ ← mm2;
--cp.wExt ← ;
--cp.wExt ← ;
cob.class ← pForVia;
IF l<oldMins THEN --new technology; we use new technology only for small sizes--
cob.size ← [mins, l]
ELSE --old technology--
cob.size ← [oldMins, l];
--cob.layer ← ;
RETURN [mmCache.ReplaceByAequivalent[cob]]
END;
ReadVia: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
RETURN [ CreateMmCon[TokenIO.ReadInt[]] ]
END;
WriteVia: CD.InternalWriteProc -- PROC [me: Object] -- =
BEGIN
TokenIO.WriteInt[me.size.y];
END;
ShortenMm: CDCallSpecific.CallProc =
BEGIN
cp: ContactPtr ← NARROW[inst.ob.specificRef];
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
ap.ob ← CreateMmCon[l: inst.ob.size.y-lambda, wex: cp.wExt, lex: cp.lExt];
include←LIST[ap];
removeMe←TRUE;
repaintMe←TRUE;
END;
LengthenVia: CDCallSpecific.CallProc =
BEGIN
amount: CD.Position = ToPosition[x];
IF amount.y=0 OR amount.x#0 THEN done ← FALSE
ELSE {
cp: ContactPtr ← NARROW[inst.ob.specificRef];
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
sz: CD.Position ← CDBasics.AddPoints[inst.ob.size, amount];
IF sz.x<=0 OR sz.y<=0 THEN {done←FALSE; RETURN};
ap.ob ← CreateMmCon[l: sz.y, wex: cp.wExt, lex: cp.lExt];
include ← LIST[ap];
removeMe ← TRUE;
repaintMe ← amount.y<0;
repaintInclude ← amount.y>0;
}
END;
SetLengthVia: CDCallSpecific.CallProc =
BEGIN
newLength: CD.Number ← NARROW[x, REF CD.Number]^;
oldLength: CD.Number ← inst.ob.size.y;
cp: ContactPtr ← NARROW[inst.ob.specificRef];
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
ap.ob ← CreateMmCon[l: newLength, wex: cp.wExt, lex: cp.lExt];
include ← LIST[ap];
removeMe ← TRUE;
IF newLength>oldLength THEN repaintInclude ← TRUE ELSE repaintMe ← TRUE;
END;
DefaultenVia: CDCallSpecific.CallProc =
BEGIN
cp: ContactPtr ← NARROW[inst.ob.specificRef];
ap: CD.Instance ← NEW[CD.InstanceRep←inst^];
ap.ob ← CreateMmCon[l: 4*lambda, wex: cp.wExt, lex: cp.lExt];
include ← LIST[ap];
removeMe ← TRUE;
repaintMe ← TRUE;
repaintInclude ← TRUE;
END;
DrawVia: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] =
--does not read specificRef !!!!!!
BEGIN
mins: CD.Number = cut2min+2*mmRimWidth;
r: CD.Rect = CDOrient.RectAt[pos, inst.ob.size, orient];
pr.drawRect[r, met, pr];
pr.drawRect[r, met2, pr];
IF inst.ob.size.x>mins THEN --old technology--
pr.drawRect[CDBasics.Extend[r, -2*lambda --oldmmRimWidth-- ], cut2, pr]
ELSE --new technology--
pr.drawRect[CDBasics.Extend[r, -mmRimWidth], cut2, pr];
END;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Init: PROC [] =
BEGIN
pForDifPolCon.drawMe ← pForDifPolCon.quickDrawMe ← DrawDifAndPolContact;
CDCallSpecific.Register[$Lengthen, pForDifPolCon, LengthenDifPol];
CDCallSpecific.Register[$Default, pForDifPolCon, DefaultenDifPol];
CDCallSpecific.Register[$SetLength, pForDifPolCon, SetLengthDifPol];
pForDifPolCon.internalRead ← ReadDifPolCon;
pForDifPolCon.internalWrite ← WriteDifPolCon;
pForDifPolCon.describe ← Describe;
CDStretchyExtras.InstallMatch[pForDifPolCon, MatchContact];
pForButContact.drawMe ← pForButContact.quickDrawMe ← DrawButContact;
pForButContact.internalRead ← ReadButCon;
pForButContact.internalWrite ← WriteButCon;
pForButContact.describe ← Describe;
CDStretchyExtras.InstallMatch[pForButContact, MatchContact];
pForBurCon.drawMe ← pForBurCon.quickDrawMe ← DrawMeForBurrNMosContacts;
CDCallSpecific.Register[$Lengthen, pForBurCon, LengthenBur];
CDCallSpecific.Register[$Default, pForBurCon, DefaultenBur];
CDCallSpecific.Register[$SetLength, pForBurCon, SetLengthBur];
CDCallSpecific.Register[$ChangeExt, pForBurCon, ChangeExtensionBur];
pForBurCon.internalRead ← ReadBurCon;
pForBurCon.internalWrite ← WriteBurCon;
pForBurCon.describe ← Describe;
CDStretchyExtras.InstallMatch[pForBurCon, MatchContact];
pForVia.drawMe ← pForVia.quickDrawMe ← DrawVia;
CDCallSpecific.Register[$Lengthen, pForVia, LengthenVia];
CDCallSpecific.Register[$Default, pForVia, DefaultenVia];
CDCallSpecific.Register[$SetLength, pForVia, SetLengthVia];
pForVia.internalRead ← ReadVia;
pForVia.internalWrite ← WriteVia;
pForVia.describe ← Describe;
CDStretchyExtras.InstallMatch[pForVia, MatchContact];
pForDifShorts.drawMe ← pForDifShorts.quickDrawMe ← DrawDifShortContact;
pForDifShorts.internalRead ← ReadDifShortCon;
pForDifShorts.internalWrite ← WriteDifShortCon;
pForDifShorts.describe ← Describe;
CDStretchyExtras.InstallMatch[pForDifShorts, MatchContact];
END;
Init[];
END.