-- File: DJExtCount.mesa
-- flatten hierarchy created by the disjoint circuit extractor
-- Written by Martin Newell/Dan Fitzpatrick July 1981
-- Last edited: August 28, 1981 2:58 PM

DIRECTORY

DisjointAllocDefs: FROM "DisjointAllocDefs" USING [EnumerateSymbols],
DisjointPropDefs: FROM "DisjointPropDefs" USING [GetLongProp, PutProp, GetProp, AllocPropID],
DisjointTypes: FROM "DisjointTypes" USING [Symbol, Instance, PropID, Geometry,Rectangle],
DJExtDefs: FROM "DJExtDefs",
DJExtractDefs: FROM "DJExtractDefs" USING [GetIntTransID, GetIntCapID],
DJExtTypes: FROM "DJExtTypes" USING [Node, Diffusion],
DJExtUtilsDefs: FROM "DJExtUtilsDefs" USING [WriteLongDecimal,WriteFloat],
IODefs: FROM "IODefs" USING [WriteString, WriteLine],
Runtime: FROM "Runtime" USING [CallDebugger];

DJExtCount: PROGRAM
IMPORTS DisjointAllocDefs, DisjointPropDefs, DJExtractDefs, DJExtUtilsDefs, IODefs, Runtime
EXPORTS DJExtDefs =
BEGIN
OPEN DisjointAllocDefs, DisjointPropDefs, DisjointTypes, DJExtractDefs, DJExtTypes, DJExtUtilsDefs, IODefs, Runtime;

ExtCount: PUBLIC PROCEDURE [symbol: Symbol] =
BEGIN
InitCount[];
CountAll[symbol];
WriteLine["fully instanciated"];
PrintCount[];
fitrans ← etrans+dtrans+utrans;
firec ← nRec;
InitCount[];
CountOnce[symbol];
WriteLine["Once"];
PrintCount[];
oncetrans ← etrans+dtrans+utrans;
oncerec ← nRec;
WriteString["transistor regularity = "];
IF oncetrans = 0 THEN WriteString["????"]
ELSE WriteFloat[fitrans/oncetrans];
WriteString[", rectangle regularity = "];
IF oncerec = 0 THEN WriteString["????"]
ELSE WriteFloat[firec/oncerec];
WriteLine[""];
END;

CountOnce: PROCEDURE [symbol: Symbol] =
BEGIN
[] ← EnumerateSymbols[Mark];
RCountOnce[symbol];
END;

RCountOnce: PROCEDURE [symbol: Symbol] =
BEGIN
PutProp[@symbol.prop,markID,0];
Count[symbol];
-- examine each of the sub-symbols
FOR in: Instance ← symbol.insts,in.next UNTIL in = NIL DO
-- recurse
IF GetProp[in.symbol.prop,markID] = 1 THEN RCountOnce[in.symbol];
ENDLOOP;
END;

Mark: PROCEDURE[s: Symbol] RETURNS[BOOLEAN] =
BEGIN
-- mark = 1 means symbol has not yet been output
PutProp[@s.prop,markID,1];
RETURN[FALSE];
END;

CountAll: PROCEDURE [symbol: Symbol] =
BEGIN
Count[symbol];
-- examine each of the sub-symbols
FOR in: Instance ← symbol.insts,in.next UNTIL in = NIL DO
-- recurse
CountAll[in.symbol];
ENDLOOP;
END;

Count: PROCEDURE [symbol: Symbol] =
BEGIN
nSymbol ← nSymbol + 1;
-- count each transistor
FOR p: Node ← GetLongProp[symbol.prop,intID],p.next UNTIL p = NIL DO
CountTransistor[p];
ENDLOOP;
-- count each capacitor
FOR cap:Node ← GetLongProp[symbol.prop,intCapID],cap.next UNTIL cap = NIL DO
nodeCnt ← nodeCnt + 1;
ENDLOOP;
FOR in: Instance ← symbol.insts,in.next UNTIL in = NIL DO
nCalls ← nCalls + 1;
ENDLOOP;
FOR geom: Geometry ← symbol.geom,geom.next UNTIL geom = NIL DO
nRec ← nRec + 1;
ENDLOOP;
FOR in: Instance ← symbol.insts,in.next UNTIL in = NIL DO
IncP[in.symbol];
ENDLOOP;
END;

InitCount: PROCEDURE =
BEGIN
nodeCnt ← etrans ← dtrans ← utrans ← btrans ← ctrans ← 0;
nSymbol ← 0;
nRec ← 0;
nCalls ← 0;
P ← 0;
END;

PrintCount: PROCEDURE =
BEGIN
WriteLongDecimal[etrans]; WriteString[":enhancement, "];
WriteLongDecimal[dtrans]; WriteString[":depletion, "];
IF utrans # 0 THEN {
WriteLongDecimal[utrans]; WriteString[":unusual implants, "];
};
IF ctrans # 0 THEN {
WriteLongDecimal[ctrans]; WriteString[":poly/diff capacitors, "];
};
IF btrans # 0 THEN {
WriteLongDecimal[btrans]; WriteString[":malformed transistors, "];
};
WriteLine[""];
WriteLongDecimal[nodeCnt]; WriteString[":nodes, "];
WriteLongDecimal[etrans+dtrans+utrans]; WriteString[":transistors, "];
WriteLongDecimal[nSymbol]; WriteString[":symbols, "];
WriteLongDecimal[nCalls]; WriteString[":calls, "];
WriteLongDecimal[nRec]; WriteString[":rectangles, "];
WriteFloat[P/50000]; WriteString["mm:P "];
WriteLine[""];
END;

IncP: PROCEDURE [symbol: Symbol] =
BEGIN
FOR w:Rectangle ← symbol.windows,w.next UNTIL w = NIL DO
P ← P + (w.t-w.b)+(w.r-w.l);
ENDLOOP;
END;



CountTransistor: PROCEDURE [trans: Node] =
BEGIN
cnt: CARDINAL ← 0;
FOR d:Diffusion ← trans.diff,d.next UNTIL d = NIL DO cnt ← cnt+1 ENDLOOP;
SELECT cnt FROM
1 => {-- transistor with only one diffusion
-- See if it’s a butting contact
IF trans.poly # trans.diff.node THEN {
ctrans ← ctrans + 1;
};
};
2 => {-- normal transistor
IF NOT trans.ion AND trans.nion THEN {
etrans ← etrans + 1;
}
ELSE IF trans.ion AND NOT trans.nion THEN {
dtrans ← dtrans + 1;
}
ELSE IF trans.ion AND trans.nion THEN {
utrans ← utrans + 1;
}
ELSE CallDebugger["bug in transistor type checker"];
};
ENDCASE => { -- bad transistor
btrans ← btrans + 1;
};
END;



intID: PropID ← GetIntTransID[];
intCapID: PropID ← GetIntCapID[];
markID: PropID ← AllocPropID[];

nCalls,nRec,nSymbol,nodeCnt,etrans,dtrans,utrans,btrans,ctrans:LONG CARDINAL;
fitrans,oncetrans:REAL;
firec,oncerec:REAL;
P:REAL;

END.