-- procedure exporting module of silicon (pretty picture) program
-- last modified by McCreight, January 30, 1984 4:37 PM
-- to re-do buried contacts
-- modified by Dillon March 14, 1984 6:49 PM
-- to change buried contact sizing algorithm

DIRECTORY
InlineDefs,
ppCache,
ppdddefs,ppddefs,
pppdefs,
ppdefs;

ppprocs: PROGRAM IMPORTS ppCache, ppdefs, ppddefs, ppdddefs, InlineDefs, pppdefs
EXPORTS ppdefs,ppdddefs =
BEGIN OPEN ppdefs, ppdddefs,ppddefs, InlineDefs, pppdefs;

anyChanges, sinceIOchanges: PUBLIC BOOLEAN ← FALSE;

diffusionType: PUBLIC DiffusionType ← n;
diffusionPurpose: PUBLIC DiffusionPurpose ← wiring;

Width: TYPE = locNum ← 0;
minWidthAr: PUBLIC ARRAY level OF Width ← [
cut: 2*Lambda,
dif: 2*Lambda,
pol: 2*Lambda,
met: 3*Lambda,
cut2: 3*Lambda,
pdif: 2*Lambda,
met2: 4*Lambda,
nwelCont: 3*Lambda,
pwelCont: 3*Lambda
];

bwGrain: PUBLIC INTEGER ← 10;
colGrain: PUBLIC INTEGER ← 1;


wireList: PUBLIC ARRAY level OF LONG POINTER TO wire object ← ALL[NIL];
tranList: PUBLIC LONG POINTER TO xstr object ← NIL;
puList: PUBLIC LONG POINTER TO xstr object ← NIL;
contList: PUBLIC LONG POINTER TO cont object ← NIL;

textProcs:Procs ← [
drawme:ALL[drText],inBox:rectIB,inMe:inMeRect,release:nullRel,
anotherme:permAnother,setParm:setNullParm];
rectProcs:Procs ← [
drawme:[
drRect0,drRect0,drRect0,drRect0,drRect2,drRect2,drRect2,drRect2,
drRect0,drRect0,drRect0,drRect0,drRect2,drRect2,drRect2,drRect2],
inBox:rectIB,inMe:inMeRect,release:refCntRelease,anotherme:permAnother,
setParm:setWireParm];
xstrProcs:Procs ← [
drawme:[
drXstr0,drXstr0,drXstr0,drXstr0,drXstr2,drXstr2,drXstr2,drXstr2,
drXstr0,drXstr0,drXstr0,drXstr0,drXstr2,drXstr2,drXstr2,drXstr2],
inBox:rectIB,inMe:inMeRect,release:refCntRelease,anotherme:permAnother,
setParm:setXstrParm];
angxstrProcs:Procs ← [
drawme:[
drAXstr0,drAXstrR0,drAXstr0,drAXstrR0,drAXstr2,drAXstrR2,drAXstr2,drAXstrR2,
drAXstr4,drAXstrR4,drAXstr4,drAXstrR4,drAXstr6,drAXstrR6,drAXstr6,drAXstrR6],
inBox:rectIB,inMe:inMeRect,release:refCntRelease,anotherme:permAnother,
setParm:setAXstrParm];

cellProcs:Procs ← [
drawme:[
drCell0,drCell0R,drCell0,drCell0R,drCell2,drCell2R,drCell2,drCell2R,
drCell4,drCell4R,drCell4,drCell4R,drCell6,drCell6R,drCell6,drCell6R],
inBox:rectIB,inMe:inMeRect,release:cellRel,anotherme:permAnother,
setParm:setNullParm];
wireProcs:Procs ← [
drawme:[
drWire0,drWire0,drWire0,drWire0,drWire2,drWire2,drWire2,drWire2,
drWire0,drWire0,drWire0,drWire0,drWire2,drWire2,drWire2,drWire2],
inBox:rectIB,inMe:inMeRect,release:refCntRelease,anotherme:permAnother,
setParm:setWireParm];
difWireProcs:Procs ← [
drawme:[
drDifWire0,drDifWire0,drDifWire0,drDifWire0,drDifWire2,
drDifWire2,drDifWire2,drDifWire2,
drDifWire0,drDifWire0,drDifWire0,drDifWire0,drDifWire2,
drDifWire2,drDifWire2,drDifWire2],
inBox:rectIB,inMe:inMeRect,release:refCntRelease,anotherme:permAnother,
setParm:setWireParm];

busProcs:Procs ← [
drawme:[
drBus0,drBusR0,drBus0,drBusR0,drBus2,drBusR2,drBus2,drBusR2,
drBus4,drBusR4,drBus4,drBusR4,drBus6,drBusR6,drBus6,drBusR6],
inBox:rectIB,inMe:inMeRect,release:uniqueRelease,anotherme:busAnother,
setParm:setBusParm];
puProcs:Procs ← [
drawme:[
drPu0,drPu0,drPu0,drPu0,drPu2,drPu6,drPu2,drPu6,drPu4,drPu4,drPu4,
drPu4,drPu6,drPu2,drPu6,drPu2],inBox:rectIB,inMe:inMeRect,
release:refCntRelease,anotherme:permAnother,setParm:setPuParm];
bcProcs:Procs ← [
drawme:[
drBC0,drBC0,drBC0,drBC0,drBC2,drBC6,drBC2,drBC6,drBC4,drBC4,drBC4,
drBC4,drBC6,drBC2,drBC6,drBC2],inBox:rectIB,inMe:inMeRect,
release:nullRel,anotherme:permAnother,setParm:setNullParm];
difShortProcs:Procs ← [
drawme:[
drDifShort0,drDifShort0,drDifShort0,drDifShort0,
drDifShort2,drDifShort6,drDifShort2,drDifShort6,
drDifShort4,drDifShort4,drDifShort4,drDifShort4,
drDifShort6,drDifShort2,drDifShort6,drDifShort2],inBox:rectIB,inMe:inMeRect,
release:nullRel,anotherme:permAnother,setParm:setNullParm];
dcProcs:Procs ← [
drawme:[
drDC0,drDC0,drDC0,drDC0,drDC2,drDC2,drDC2,drDC2,drDC0,drDC0,drDC0,
drDC0,drDC2,drDC2,drDC2,drDC2],inBox:rectIB,inMe:inMeRect,
release:refCntRelease,anotherme:permAnother,setParm:setContParm];
bucProcs:Procs ← [
drawme:[
drBuC0,drBuC4,drBuC0,drBuC4,drBuC2,drBuC2,drBuC2,drBuC2,
drBuC4,drBuC0,drBuC4,drBuC0,drBuC6,drBuC6,drBuC6,drBuC6],
inBox:rectIB,inMe:inMeRect,
release:refCntRelease,anotherme:permAnother,setParm:setBuContParm];
mmcProcs:Procs ← [
drawme:[
drMM0,drMM0,drMM0,drMM0,drMM2,drMM2,drMM2,drMM2,drMM0,drMM0,drMM0,
drMM0,drMM2,drMM2,drMM2,drMM2],inBox:rectIB,inMe:inMeRect,
release:refCntRelease,anotherme:permAnother,setParm:setContParm];
cnTextProcs:Procs ← [
drawme:ALL[drCnText],inBox:rectIB,inMe:inMeRect,release:cnRelease,
anotherme:permAnother,setParm:setNullParm];

nullRel: relProc = BEGIN ob.refCnt ← ob.refCnt - 1; END;
refCntRelease: relProc =
BEGIN
ob.refCnt ← ob.refCnt - 1;
IF ob.refCnt<1 THEN ppCache.FlushObjectCache[ob];
--
IF ob.refCnt>1 THEN ob.refCnt←ob.refCnt-1
--
ELSE FreeSpace[ob];
END;
cellRel: relProc =
BEGIN
cc: LONG POINTER TO cell object;
ob.refCnt ← ob.refCnt - 1;
IF ob.refCnt > 0 OR NOT ob.returnable THEN RETURN;
ppCache.FlushObjectCache[ob];
cc ← LOOPHOLE[ob];
flushDel[cc.ptr];
freeCell[cc];
END;
cnRelease: relProc =
BEGIN
p: LONG POINTER TO cnText object = LOOPHOLE[ob];
FreeString[p.s];
FreeSpace[ob];
END;
uniqueRelease: relProc =
BEGIN
ppCache.FlushObjectCache[ob];
FreeSpace[ob];
END;

permAnother: anoProc = BEGIN ob.refCnt ← ob.refCnt + 1; RETURN[ob]; END;
busAnother: anoProc =
BEGIN
nob:LONG POINTER TO bus object ← alocBusD[];
oob:LONG POINTER TO bus object = LOOPHOLE[ob];
nob↑←oob↑;
RETURN[nob];
END;

CurrentDif: PROC RETURNS [level] =
{RETURN[IF diffusionPurpose = wiring THEN
(IF diffusionType = n THEN dif ELSE pdif)
ELSE (IF diffusionType = n THEN nwelCont ELSE pwelCont)]};

CurrentDifType: PROC RETURNS [level] =
{RETURN[IF diffusionType = n THEN dif ELSE pdif]};

makePullup: PUBLIC PROCEDURE [w,l:INTEGER,wExt:INTEGER←wXExtension,lExt:INTEGER←lXExtension,
difLev: level ← unspecified]
RETURNS [p: obPtr] =
BEGIN
dp: LONG POINTER TO xstr object ← puList;
IF difLev=unspecified THEN difLev ← CurrentDifType[];
w ← MAX[w, 2*Lambda];
l ← MAX[l, 2*Lambda];
wExt ← MAX[wExt, 0];
lExt ← MAX[lExt, 0];
WHILE dp # NIL DO
IF dp.width = w AND dp.length = l
AND dp.wExt = wExt AND dp.lExt = lExt AND dp.l=difLev
THEN {p ← dp.p.anotherme[dp]; RETURN};
dp ← dp.super;
ENDLOOP;
p ← dp ← alocXstrD[];
dp.super ← puList;
puList ← dp;
p.p ← @puProcs;
dp.l ← difLev;
dp.width ← w;
dp.length ← l;
dp.wExt ← wExt;
dp.lExt ← lExt;
dp.impl ← LAST[DepletionStrength]; -- I guess...
dp.pullup ← TRUE;
dp.size[0] ← dp.size[2] ←
MAX[dp.width + dp.wExt*2, 4*Lambda];
dp.size[1] ← MAX[dp.length + dp.lExt + 3*Lambda, 6*Lambda];
dp.surround ← SELECT dp.l FROM
pdif, dif => wellSurround,
pwelCont, nwelCont => 0,
ENDCASE => 0;
END; -- of makePullup

makeXstr: PUBLIC PROCEDURE [w, l: INTEGER, imp: DepletionStrength ← enhancement
, wExt: INTEGER ← wXExtension, lExt: INTEGER ← lXExtension,
difLev: level ← unspecified]
RETURNS [p: obPtr] =
BEGIN
dp: LONG POINTER TO xstr object ← tranList;
IF difLev=unspecified THEN difLev ← CurrentDifType[];
w ← MAX[w, 2*Lambda];
l ← MAX[l, 2*Lambda];
wExt ← MAX[wExt, 0];
lExt ← MAX[lExt, 0];
WHILE dp # NIL DO
IF dp.width = w AND dp.length = l AND dp.impl = imp
AND dp.wExt = wExt AND dp.lExt = lExt AND NOT dp.angle AND dp.l=difLev
THEN
BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
dp ← dp.super;
ENDLOOP;
p ← dp ← alocXstrD[];
dp.super ← tranList;
tranList ← dp;
p↑.p ← @xstrProcs;
dp↑.l ← difLev;
dp↑.width ← w;
dp↑.length ← l;
dp↑.wExt ← wExt;
dp↑.lExt ← lExt;
dp↑.impl ← imp;
dp↑.pullup ← FALSE;
dp↑.size[0] ← dp↑.size[2] ← dp.width + dp.wExt*2;
dp↑.size[1] ← dp.length + dp.lExt*2;
dp.surround ← SELECT dp.l FROM
pdif, dif => wellSurround,
pwelCont, nwelCont => 0,
ENDCASE => 0;
END; -- of makeXstr

makeAngleXstr: PUBLIC PROCEDURE [w, l: INTEGER, imp: DepletionStrength ← enhancement
, wExt: INTEGER ← wXExtension, lExt: INTEGER ← lXExtension,aExt:INTEGER←0,
difLev: level ← unspecified]
RETURNS [p: obPtr] =
BEGIN
dp: LONG POINTER TO xstr object ← tranList;
siz1:INTEGER;
IF difLev=unspecified THEN difLev ← CurrentDifType[];
wExt ← MAX[wExt, 0];
lExt ← MAX[lExt, 0];
aExt ← MAX[aExt, -lExt];
l ← MAX[l, 2*Lambda];
w ← MAX[w, 2*lExt]; -- the width of the straight-line
-- parts of the gate, excluding the corner
siz1 ← wExt+2*lExt+aExt+l;
WHILE dp # NIL DO
IF dp.width = w AND dp.length = l AND dp.impl = imp AND dp.wExt=wExt
AND dp.lExt=lExt AND dp.angle AND dp.size[1]=siz1 AND dp.l=difLev
THEN
BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
dp ← dp.super;
ENDLOOP;
p ← dp ← alocXstrD[];
dp.super ← tranList;
tranList ← dp;
p↑.p ← @angxstrProcs;
dp↑.l ← difLev;
dp↑.width ← w;
dp↑.length ← l;
dp↑.wExt ← wExt;
dp↑.lExt ← lExt;
dp↑.impl ← imp;
dp↑.angle ← TRUE;
dp↑.pullup ← FALSE;
dp↑.size[0] ← dp↑.size[2] ← wExt+(w-lExt-aExt)+l+lExt;
dp↑.size[1] ← siz1;
dp.surround ← SELECT dp.l FROM
pdif, dif => wellSurround,
pwelCont, nwelCont => 0,
ENDCASE => 0;
END;

makeRect: PUBLIC PROCEDURE [x, y: INTEGER, l: level]
RETURNS [p: LONG POINTER TO object] =
BEGIN
dp: LONG POINTER TO rect object;
x ← MAX[x, 1];
y ← MAX[y, 1];
p ← dp ← alocRectD[];
p↑.p ← @rectProcs;
dp↑.size[0] ← dp↑.size[2] ← x;
dp↑.size[1] ← y;
dp↑.l ← l;
END;

makeText: PUBLIC PROCEDURE [s: STRING] RETURNS [p: LONG POINTER TO object] =
BEGIN
dp: LONG POINTER TO text object;
p ← dp ← alocTextD[];
p↑.p ← @textProcs;
dp↑.size[0] ← dp↑.size[2] ← 6*s.length;
dp↑.size[1] ← 8;
dp↑.s ← s;
dp↑.l ← cut;
END;

makeCnText: PUBLIC PROCEDURE [
s: STRING, xw, byw, yw: INTEGER, op: LONG POINTER TO cell object,
np: LONG POINTER TO cList] RETURNS [p: LONG POINTER TO object] =
BEGIN
dp: LONG POINTER TO cnText object;
p ← dp ← alocCnTextD[];
p↑.p ← @cnTextProcs;
dp↑.size[0] ← xw;
dp↑.size[1] ← byw;
dp↑.size[2] ← byw*yw;
dp↑.s ← newString[s];
dp↑.np ← np;
dp↑.op ← op;
END;

makeBuCont: PUBLIC PROCEDURE [wid,len,wex,lex: INTEGER, difLev: level ← unspecified]
RETURNS [p: obPtr] =
BEGIN
dp: LONG POINTER TO cont object ← contList;
burAct: locNum = 2*lambda;
actWidth, xMargins: locNum;
IF difLev=unspecified THEN difLev ← CurrentDif[];
IF wex<0 THEN wex←0;
IF lex<0 THEN lex←0;
-- wid ← MAX[wid, burAct + (IF wex < burAct
-- THEN 3*lambda+MAX[wex+lambda, burAct] ELSE 2*lambda+wex)];
-- actWidth ← wid-burAct-
-- (IF wex < burAct THEN lambda+MAX[wex+lambda, burAct] ELSE wex);
-- len ← MAX[len, 2*MAX[burAct, lex]+lambda*MAX[2, (6*lambda+actWidth-1)/actWidth]];

xMargins ← burAct + MAX[(IF wex < burAct THEN MAX[wex+lambda, burAct] ELSE wex-lambda), wex];
actWidth ← MAX[2*lambda, wid - xMargins];
wid ← actWidth + xMargins;
len ← MAX[len, 2*MAX[(IF lex < burAct THEN MAX[lex+lambda, burAct] ELSE lex-lambda), lex]+lambda*MAX[2, 6*lambda/actWidth]];

WHILE dp # NIL DO
IF dp.typ=burr AND dp.size[1] = len AND dp.size[0] = wid AND
dp.wExt=wex AND dp.lExt=lex AND dp.l=difLev THEN
{p ← dp.p.anotherme[dp]; RETURN};
dp ← dp.super;
ENDLOOP;
p ← dp ← alocContD[];
dp.super ← contList;
contList ← dp;
dp.size[0] ← dp.size[2] ← wid;
dp.size[1] ← len;
dp.p ← @bucProcs;
dp.typ ← burr;
dp.l ← difLev;
dp.wExt←wex;
dp.lExt←lex;
dp.surround ← SELECT dp.l FROM
pdif, dif => wellSurround,
pwelCont, nwelCont => 0,
ENDCASE => 0;
END;

makeDifcon: PUBLIC PROCEDURE [lll: INTEGER, difLev: level ← unspecified]
RETURNS [p: obPtr] =
BEGIN
dp: LONG POINTER TO cont object ← contList;
IF difLev=unspecified THEN difLev ← CurrentDif[];
IF lll < butconSX THEN lll ← butconSX;
WHILE dp # NIL DO
IF dp.size[1] = lll AND dp.typ = mDif AND dp.l=difLev THEN
{p ← dp.p.anotherme[dp]; RETURN};
dp ← dp.super;
ENDLOOP;
p ← dp ← alocContD[];
dp.super ← contList;
contList ← dp;
dp.size[0] ← dp.size[2] ← butconSX;
dp.size[1] ← lll;
dp.p ← @dcProcs;
dp.typ ← mDif;
dp.magicN ← butconSX/4;
dp.l←difLev;
dp.surround ← SELECT dp.l FROM
pdif, dif => wellSurround,
pwelCont, nwelCont => 0,
ENDCASE => 0;
END;

makeButcon: PUBLIC PROCEDURE [difLev: level ← unspecified]
RETURNS [p: obPtr] =
BEGIN
dp: LONG POINTER TO cont object ← contList;
IF difLev=unspecified THEN difLev ← CurrentDif[];
WHILE dp # NIL DO
IF dp.typ = butt AND dp.l = difLev THEN
BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
dp ← dp.super;
ENDLOOP;
p ← dp ← alocContD[];
dp.super ← contList;
contList ← dp;
dp.size[0] ← dp.size[2] ← butconSX;
dp.size[1] ← butconSY;
dp.p ← @bcProcs;
dp.typ ← butt;
dp.magicN ← butconSX/4;
dp.l←difLev;
dp.surround← SELECT dp.l FROM
pdif, dif => wellSurround,
pwelCont, nwelCont => 0,
ENDCASE => 0;
END;

makeDifShortCont: PUBLIC PROCEDURE [difLev: level ← unspecified]
RETURNS [p: obPtr] =
BEGIN
dp: LONG POINTER TO cont object ← contList;
IF difLev=unspecified THEN difLev ← CurrentDifType[];
WHILE dp # NIL DO
IF dp.typ = difShort AND dp.l = difLev THEN
BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
dp ← dp.super;
ENDLOOP;
p ← dp ← alocContD[];
dp.super ← contList;
contList ← dp;
dp.size[0] ← dp.size[2] ← butconSX;
dp.size[1] ← 8*Lambda;
dp.p ← @difShortProcs;
dp.typ ← difShort;
dp.magicN ← butconSX/4;
dp.l←difLev;
dp.surround← SELECT dp.l FROM
pdif, dif => wellSurround,
pwelCont, nwelCont => 0,
ENDCASE => 0;
END;

makePolycon: PUBLIC PROCEDURE [lll: INTEGER]
RETURNS [p: obPtr] =
BEGIN
dp: LONG POINTER TO cont object ← contList;
IF lll < butconSX THEN lll ← butconSX;
WHILE dp # NIL DO
IF dp.size[1] = lll AND dp.typ = mPol THEN
BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
dp ← dp.super;
ENDLOOP;
p ← dp ← alocContD[];
dp.super ← contList;
contList ← dp;
dp.size[0] ← dp.size[2] ← butconSX;
dp.size[1] ← lll;
dp.p ← @dcProcs;
dp.typ ← mPol;
dp.magicN ← butconSX/4;
dp.l←pol
END;

makeMmCont: PUBLIC PROCEDURE [len,wex,lex: INTEGER]
RETURNS [p: obPtr] =
BEGIN
mins:INTEGER=cut2min+2*mmContExt;
dp: LONG POINTER TO cont object ← contList;
IF len < mins THEN len ← mins;
-- IF wex<0 THEN wex←0;IF lex<0 THEN lex←0;
-- IF wid < 2*wex+2 THEN wid ← 2*wex+2;
-- IF len < 2*lex+4 THEN len ← 2*lex+4;
WHILE dp # NIL DO
IF dp.typ=mm2 AND dp.size[1] = len --AND dp.size[0] = wid AND
--dp.wExt=wex AND dp.lExt=lex --THEN
BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
dp ← dp.super;
ENDLOOP;
p ← dp ← alocContD[];
dp.super ← contList;
contList ← dp;
dp.size[0] ← dp.size[2] ← mins;
dp.size[1] ← len;
dp.p ← @mmcProcs;
dp.typ ← mm2;
-- dp.wExt←wex;
-- dp.lExt←lex;
dp.magicN←mmContExt;
END;

makeWire:PUBLIC PROCEDURE[len,wid:INTEGER,l:level,surr:INTEGER←wellSurround]
RETURNS [p: obPtr] =
BEGIN
dc: LONG POINTER TO wire object;
IF wireOK[l]--=dif OR l=pol OR l=met OR l=met2-- THEN
BEGIN
dc ← wireList[l];
WHILE dc # NIL DO
IF dc.size[0] = wid AND dc.size[1] = len
AND (l#pdif OR dc.surround=surr) THEN
BEGIN p ← dc.p.anotherme[dc]; RETURN; END;
dc ← dc.super;
ENDLOOP;
END;
p ← dc ← alocWireD[];
IF wireOK[l] THEN BEGIN dc.super ← wireList[l]; wireList[l] ← dc; END;
p.p ← SELECT TRUE FROM
l=pdif, l=dif, l=pwelCont, l=nwelCont => @difWireProcs,
wireOK[l] => @wireProcs,
ENDCASE => @rectProcs;
dc.size[0] ← dc.size[2] ← wid;
dc.size[1] ← len;
dc.surround← SELECT l FROM
pdif, dif => surr,
pwelCont, nwelCont => 0,
ENDCASE => 0;
dc.l ← l;
END;

makeBus: PUBLIC PROCEDURE [len, wid: INTEGER, l: level, cnt, spc, tinc, binc: INTEGER]
RETURNS [p: obPtr] =
BEGIN
b: LONG POINTER TO bus object;
p ← b ← alocBusD[];
p↑.p ← @busProcs;
b.wspace ← spc;
b.firstLength ← len;
b.topIncr ← tinc;
b.lenIncr ← binc - tinc;
b.wwidth ← wid;
b.wCnt ← cnt;
p.l ← l;
setBusSizes[b];
p.surround ← SELECT p.l FROM
pdif, dif => wellSurround,
pwelCont, nwelCont => 0,
ENDCASE => 0;
END;

setBusSizes:PROCEDURE[p:LONG POINTER TO bus object] =
BEGIN
binc:INTEGER←p.lenIncr+p.topIncr;
p.offsetFirst ← IF p.topIncr>=0 THEN 0 ELSE (1-p.wCnt)*p.topIncr;
p.size[0] ← p.size[2] ← (p.wCnt-1)*p.wspace + p.wwidth;
p.size[1] ← IF binc>0 THEN p.offsetFirst+p.firstLength+(p.wCnt-1)*binc
ELSE p.offsetFirst+p.firstLength;
END;

makeRep: PUBLIC PROC [ob:obPtr,winc,linc,dx,dy,cnt:INTEGER,
idx:orientationIndex] RETURNS [p: obPtr] =
BEGIN
repeat: cellPtr ← p ← makeCell[sx: 0, sy: 0, cnt: cnt, ptr: NIL];
FOR i: INTEGER IN [0..cnt) DO
repeat.ptr ← insertList[mp: repeat.ptr,
lp: makeList[p: ob.p.anotherme[ob], x: i*dx, y: i*dy,
o: idx/2, refl: idx MOD 2]];
ENDLOOP;
[max: repeat.size[0], may: repeat.size[1]] ← minmax[repeat.ptr];
repeat.size[2] ← repeat.size[0]; -- sigh!
END;

makeCell: PUBLIC PROCEDURE [
sx, sy: INTEGER, cnt: CARDINAL, ptr: LONG POINTER TO list]
RETURNS [p: LONG POINTER TO cell object] =
BEGIN
dc: LONG POINTER TO cell object;
p ← dc ← alocCellD[];
p↑.p ← @cellProcs;
dc↑.ptr ← ptr;
dc↑.size[0] ← dc↑.size[2] ← sx;
dc↑.size[1] ← sy;
dc↑.l ← cut;
dc↑.cnt ← cnt;
END;

inMeRect: inMeProc = --tells if cursor(or whatever)at x,y is inside object
BEGIN
xs, ys: INTEGER;
IF BITAND[o, 4] = 0 THEN BEGIN xs ← ob.size[0]; ys ← ob.size[1]; END
ELSE BEGIN xs ← ob.size[1]; ys ← ob.size[0]; END;
IF x IN [0..xs] AND y IN [0..ys] THEN RETURN[TRUE] ELSE RETURN[FALSE];
END;

rectIB: ibProc =
BEGIN
x, y, sx, sy: INTEGER;
x ← lp.lx;
y ← lp.ly;
IF BITAND[lp.idx, 4] = 0 THEN
BEGIN sx ← lp.ob.size[0]; sy ← lp.ob.size[1]; END
ELSE BEGIN sx ← lp.ob.size[1]; sy ← lp.ob.size[0]; END;
IF x >= x2 OR y >= y2 OR x + sx <= x1 OR y + sy <= y1 THEN RETURN[FALSE];
RETURN[TRUE];
END;

setWireParm: parmProc =
BEGIN
dp: LONG POINTER TO wire object ← LOOPHOLE[lp.ob];
nw, nl, wd, ln, mn: INTEGER;
l: level ← dp.l;
movl:BOOLEAN←FALSE;
wd ← dp.size[0];
ln ← dp.size[1];
SELECT pt FROM
width => BEGIN nl ← ln; nw ← (wd*dy) + dx; END;
length => BEGIN nl ← (ln*dy) + dx; nw ← wd; END;
default =>
BEGIN
IF NOT wireOK[l] THEN RETURN[FALSE];
nl ← ln;
nw ← minWidthAr[l];
END;
wSpace => BEGIN nl ← ln; nw ← wd + dx; END;
ENDCASE => RETURN[FALSE];
IF nw < INTEGER[lambdaGrid] THEN nw ← lambdaGrid;
IF nl<1 THEN {IF nl<0 THEN {movl←TRUE;nl←-nl} ELSE nl←Lambda;};
-- IF l=pdif THEN {IF nw<INTEGER[lambdaGrid]+2*tubMinExt THEN
--
nw←lambdaGrid+2*tubMinExt;
--
IF nl<2*tubMinExt+1 THEN nl←2*tubMinExt+1;};
IF nw = wd AND nl = ln THEN RETURN[FALSE];
mn ← 2*lambdaGrid;
IF BITAND[lp.idx, 4] = 0 THEN
BEGIN
IF cent THEN {lp.lx ← lp.lx + lambdaGrid*(wd/mn - nw/mn);
lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn);};
IF movl THEN lp.ly ← lp.ly - nl;
END
ELSE
BEGIN
IF cent THEN {lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn);
lp.ly ← lp.ly + lambdaGrid*(wd/mn - nw/mn);};
IF movl THEN lp.lx ← lp.lx - nl;
END;
RETURN[NewObject[lp, makeWire[nl, nw, l]]];
END;

NewObject: PROCEDURE [lp: listPtr, ob: obPtr] RETURNS [BOOLEAN] =
BEGIN
lp.ob.p.release[lp.ob];
lp.ob ← ob;
RETURN[TRUE];
END;

setBusParm: parmProc =
BEGIN
dp: LONG POINTER TO bus object ← LOOPHOLE[lp.ob];
nw, nl, wd, ln, mn: INTEGER;
l: level ← dp.l;
wd ← dp.wwidth;
ln ← dp.firstLength;
SELECT pt FROM
width => BEGIN nl ← ln; nw ← (wd*dy) + dx; END;
length => BEGIN nl ← (ln*dy) + dx; nw ← wd; END;
default =>
BEGIN
IF NOT (l=dif OR l=pol OR l=met OR l=met2) THEN RETURN[FALSE];
nl ← ln;
nw ← minWidthAr[l];
END;
ENDCASE =>
BEGIN
SELECT pt FROM
wSpace => BEGIN dp.wspace←dp.wspace + dx; IF dp.wspace<dp.wwidth+1 THEN dp.wspace←dp.wwidth+1; END;
count => BEGIN dp.wCnt←dp.wCnt + dx; IF dp.wCnt<1 THEN dp.wCnt←1; END;
lSpace => BEGIN dp.topIncr←dp.topIncr + dx; END;
bSpace => BEGIN dp.lenIncr←dp.lenIncr + dx; END;
ENDCASE;
setBusSizes[dp];
RETURN[TRUE];
END;
IF nw < INTEGER[lambdaGrid] THEN nw ← lambdaGrid;
IF nl < 1 THEN nl ← 1;
IF nw = wd AND nl = ln THEN RETURN[FALSE];
mn ← 2*lambdaGrid;
IF BITAND[lp.idx, 4] = 0 AND cent THEN
BEGIN
lp.lx ← lp.lx + lambdaGrid*(wd/mn - nw/mn);
lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn);
END
ELSE
IF cent THEN
BEGIN
lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn);
lp.ly ← lp.ly + lambdaGrid*(wd/mn - nw/mn);
END;
dp.size[0] ← dp.size[2] ← dp.size[0] + nw - wd;
dp.size[1] ← dp.size[1] + nl - ln;
dp.wwidth ← nw;
dp.firstLength ← nl;
RETURN[TRUE];
END;

setNullParm: parmProc = BEGIN RETURN[FALSE]; END;

setAXstrParm: parmProc =
BEGIN
dp: LONG POINTER TO xstr object ← LOOPHOLE[lp.ob];
nw, nl, wd, ln, mn,nwe,nle,nax,oax: INTEGER;
im: DepletionStrength ← dp.impl;
nw←wd ← dp.width;
nl←ln ← dp.length;
nwe←dp.wExt;
nle←dp.lExt;
oax←nax←dp.size[1]-dp.length-2*dp.lExt-dp.wExt;
SELECT pt FROM
width => BEGIN nw ← (wd*dy) + dx; END;
length => BEGIN nw ← (wd*dy) + dx; nax←nax+nw-wd;END;
default => BEGIN nl ← cLength*xRatiol; nw ← cWidth*xRatiow; nax←0;
nwe←wXExtension;nle←lXExtension;END;
wSpace => BEGIN IF -dx>dp.wExt THEN dx←-dp.wExt;nwe←dp.wExt+dx; END;
lSpace => BEGIN IF -dx>dp.lExt THEN dx←-dp.lExt;nle←dp.lExt+dx; END;
count => im ← (im+1) MOD (LAST[DepletionStrength]+1);
ENDCASE => RETURN[FALSE];
-- new parameter ranges now tested in makeAngleXstr
IF nw = wd AND nl = ln AND dp.wExt=nwe AND dp.lExt=nle
AND oax=nax AND dp.impl=im THEN RETURN[FALSE];
mn ← 2*lambdaGrid;
IF BITAND[lp.idx, 4] = 0 AND cent THEN
BEGIN
lp.lx ← lp.lx + lambdaGrid*((wd-oax)/mn - (nw-nax)/mn);
lp.ly ← lp.ly + lambdaGrid*(oax/mn - nax/mn);
END
ELSE
IF cent THEN
BEGIN
lp.lx ← lp.lx + lambdaGrid*(oax/mn - nax/mn);
lp.ly ← lp.ly + lambdaGrid*((wd-oax)/mn - (nw-nax)/mn);
END;
RETURN[NewObject[lp, makeAngleXstr[nw, nl, im,nwe,nle,nax, dp.l]]];
END;

setXstrParm: parmProc =
BEGIN
dp: LONG POINTER TO xstr object ← LOOPHOLE[lp.ob];
nw, nl, wd, ln, mn,nwe,nle: INTEGER;
im: DepletionStrength ← dp.impl;
nw←wd ← dp.width;
nl←ln ← dp.length;
nwe←dp.wExt;
nle←dp.lExt;
SELECT pt FROM
width => BEGIN nw ← (wd*dy) + dx; END;
length => BEGIN nl ← (ln*dy) + dx; END;
default => BEGIN nl ← cLength*xRatiol; nw ← cWidth*xRatiow;
nwe←wXExtension;nle←lXExtension;END;
wSpace => BEGIN IF -dx>dp.wExt THEN dx←-dp.wExt;nwe←dp.wExt+dx; END;
lSpace => BEGIN IF -dx>dp.lExt THEN dx←-dp.lExt;nle←dp.lExt+dx; END;
count => im ← (im+1) MOD (LAST[DepletionStrength]+1);
ENDCASE => RETURN[FALSE];
-- new parameter ranges now tested in makeXstr
IF nw = wd AND nl = ln AND dp.wExt=nwe AND dp.lExt=nle AND dp.impl=im THEN RETURN[FALSE];
mn ← 2*lambdaGrid;
IF BITAND[lp.idx, 4] = 0 AND cent THEN
BEGIN
lp.lx ← lp.lx + lambdaGrid*(wd/mn - nw/mn);
lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn);
END
ELSE
IF cent THEN
BEGIN
lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn);
lp.ly ← lp.ly + lambdaGrid*(wd/mn - nw/mn);
END;
RETURN[NewObject[lp, makeXstr[nw, nl, im,nwe,nle, dp.l]]];
END;

setPuParm: parmProc =
BEGIN
dp: LONG POINTER TO xstr object ← LOOPHOLE[lp.ob];
nw, nl, wd, ln, mn,nwe,nle: INTEGER;
nw←wd ← dp.width;
nl←ln ← dp.length;
nwe←dp.wExt;
nle←dp.lExt;
SELECT pt FROM
width => BEGIN nw ← (wd*dy) + dx; END;
length => BEGIN nl ← (ln*dy) + dx; END;
default => BEGIN nl ← cLength*pRatiol; nw ← cWidth*pRatiow; END;
wSpace => BEGIN IF -dx>dp.wExt THEN dx←-dp.wExt;nwe←dp.wExt+dx; END;
lSpace => BEGIN IF -dx>dp.lExt THEN dx←-dp.lExt;nle←dp.lExt+dx; END;
ENDCASE => RETURN[FALSE];
-- new parameter ranges now tested in makePu
IF nw = wd AND nl = ln AND dp.wExt=nwe AND dp.lExt=nle THEN RETURN[FALSE];
mn ← 2*lambdaGrid;
IF BITAND[lp.idx, 4] = 0 AND cent THEN
BEGIN
lp.lx ← lp.lx + lambdaGrid*(wd/mn - nw/mn);
lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn);
END
ELSE
IF cent THEN
BEGIN
lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn);
lp.ly ← lp.ly + lambdaGrid*(wd/mn - nw/mn);
END;
RETURN[NewObject[lp, makePullup[nw, nl,nwe,nle, dp.l]]];
END;

setContParm: parmProc =
BEGIN
dp: LONG POINTER TO cont object ← LOOPHOLE[lp.ob];
nl, ln, mn: INTEGER;
typ: contType ← dp.typ;
ln ← dp.size[1];
SELECT pt FROM
length => BEGIN nl ← (ln*dy) + dx; END;
default => BEGIN nl ← butconSX; END;
ENDCASE => RETURN[FALSE];
IF nl < butconSX THEN nl ← butconSX;
IF nl = ln THEN RETURN[FALSE];
mn ← 2*lambdaGrid;
IF BITAND[lp.idx, 4] = 0 AND cent THEN
BEGIN lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn); END
ELSE IF cent THEN BEGIN lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn); END;
RETURN[NewObject[lp, SELECT typ FROM
mPol => makePolycon[nl],
mDif => makeDifcon[nl, dp.l],
ENDCASE => makeMmCont[nl,0,0]]];
END;

setBuContParm: parmProc =
BEGIN
dp: LONG POINTER TO cont object ← LOOPHOLE[lp.ob];
nw, nl, wd, ln, mn,nwe,nle: INTEGER;
nw←wd ← dp.size[0];
nl←ln ← dp.size[1];
nwe←dp.wExt;
nle←dp.lExt;
SELECT pt FROM
width => BEGIN nw ← (wd*dy) + dx; END;
length => BEGIN nl ← (ln*dy) + dx; END;
default => BEGIN nl ← 8; nw ← 10;nwe←4;nle←2;END;
wSpace => BEGIN IF -dx>dp.wExt THEN dx←-dp.wExt;
nwe←dp.wExt+dx;nw←nw+dx*2; END;
lSpace => BEGIN IF -dx>dp.lExt THEN dx←-dp.lExt;
nle←dp.lExt+dx;nl←nl+dx*2; END;
ENDCASE => RETURN[FALSE];
IF nwe<0 THEN nwe←0;IF nle<0 THEN nle←0;
IF nw < 2*nwe+2 THEN nw ← 2*nwe+2;
IF nl < 2*nle+4 THEN nl ← 2*nle+4;
IF nw = wd AND nl = ln AND dp.wExt=nwe AND dp.lExt=nle THEN RETURN[FALSE];
mn ← 2*lambdaGrid;
IF BITAND[lp.idx, 4] = 0 AND cent THEN
BEGIN
lp.lx ← lp.lx + lambdaGrid*(wd/mn - nw/mn);
lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn);
END
ELSE
IF cent THEN
BEGIN
lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn);
lp.ly ← lp.ly + lambdaGrid*(wd/mn - nw/mn);
END;
RETURN[NewObject[lp, makeBuCont[nw, nl, nwe,nle, dp.l]]];
END;


END.