-- File: DJExtOutput.mesa
-- output structures created by the disjoint circuit extractor
-- Written by Martin Newell/Dan Fitzpatrick July 1981
-- Last edited: 12-Aug-81 13:51:44
DIRECTORY
DisjointAllocDefs: FROM "DisjointAllocDefs" USING [EnumerateSymbols],
DisjointPropDefs: FROM "DisjointPropDefs" USING [GetLongProp,PutProp, GetProp, AllocPropID],
DisjointTypes: FROM "DisjointTypes" USING [Symbol, Instance, PropID],
DJExtDefs: FROM "DJExtDefs",
DJExtractDefs: FROM "DJExtractDefs" USING [GetNodeLocID, GetNodesID, GetParamID, GetNParamID, GetIntTransID, GetExtTransID, GetSegmentID, GetIntCapID, GetExtCapID],
DJExtTypes: FROM "DJExtTypes" USING [ActualParameter, NodeLocation, Node, Diffusion, Segment],
DJExtUtilsDefs: FROM "DJExtUtilsDefs" USING [Create, Close, WriteCIFUnits, WriteLongDecimal,WriteFloat],
IODefs: FROM "IODefs" USING [WriteString, WriteLine, WriteDecimal, GetOutputStream, SetOutputStream],
Inline: FROM "Inline" USING [LowHalf],
Runtime: FROM "Runtime" USING [CallDebugger],
StreamDefs: FROM "StreamDefs" USING [StreamHandle];
DJExtOutput: PROGRAM
IMPORTS DisjointAllocDefs, DisjointPropDefs, DJExtractDefs, DJExtUtilsDefs, IODefs, Inline, Runtime
EXPORTS DJExtDefs =
BEGIN
OPEN DisjointAllocDefs, DisjointPropDefs, DisjointTypes, DJExtractDefs, DJExtTypes, DJExtUtilsDefs, IODefs, Inline, Runtime, StreamDefs;
ExtOutput: PUBLIC PROCEDURE [symbol: Symbol] =
BEGIN
fileName:STRING ← "file.ext";
default: StreamHandle ← GetOutputStream[];
cifFile: StreamHandle ← Create[fileName];
SetOutputStream[cifFile];
count ← 0;
etrans ← dtrans ← utrans ← btrans ← ctrans ← 0;
WriteString["| Scale set at "]; WriteFloat[scale]; WriteLine[""];
[] ← EnumerateSymbols[Mark];
[] ← Out[symbol];
SetOutputStream[default];
Close[cifFile];
WriteLongDecimal[etrans]; WriteString[": enhancement, "];
WriteLongDecimal[dtrans]; WriteString[": depletion"];
IF utrans # 0 THEN {
WriteString[", "]; WriteLongDecimal[utrans]; WriteString[": unusual implants "];
};
IF ctrans # 0 THEN {
WriteString[", "]; WriteLongDecimal[ctrans]; WriteString[": poly/diff capacitors "];
};
IF btrans # 0 THEN {
WriteString[", "]; WriteLongDecimal[btrans]; WriteString[": malformed transistors "];
};
WriteLine[""];
END;
Mark: PROCEDURE[s: Symbol] RETURNS[BOOLEAN] =
BEGIN
-- mark = 1 means symbol has not yet been output
-- count#0 means symbol can still be called
count ← count + 1;
PutProp[@s.prop,markID,1];
PutProp[@s.prop,countID,count];
RETURN[FALSE];
END;
Out: PROCEDURE[s: Symbol] RETURNS[BOOLEAN] =
BEGIN
param: ActualParameter;
cnt,n: LONG CARDINAL;
PutProp[@s.prop,markID,0];
FOR in: Instance ← s.insts,in.next UNTIL in = NIL DO
IF GetProp[in.symbol.prop,markID] = 1 THEN [] ← Out[in.symbol];
ENDLOOP;
WriteLine[""]; WriteString["SH "]; WriteSymbolNumber[s]; WriteString[" "];
WriteLongDecimal[GetLongProp[s.prop,nparamID]]; WriteString[" "];
WriteLongDecimal[GetLongProp[s.prop,nodeID]]; WriteLine[";"];
-- write geometry
FOR loc:NodeLocation ← GetLongProp[s.prop,locID],loc.next UNTIL loc = NIL DO
WriteLocation[loc];
ENDLOOP;
FOR trans:Node ← GetLongProp[s.prop,intID],trans.next UNTIL trans = NIL DO
WriteTransistor[trans];
ENDLOOP;
FOR cap:Node ← GetLongProp[s.prop,intCapID],cap.next UNTIL cap = NIL DO
WriteCap[cap];
ENDLOOP;
param ← GetLongProp[s.prop,paramID];
cnt ← 0;
FOR in: Instance ← s.insts,in.next UNTIL in = NIL DO
WriteString["C "]; WriteSymbolNumber[in.symbol]; WriteString[" ["];
n ← GetLongProp[in.symbol.prop,nparamID];
FOR i: LONG CARDINAL IN [0..n) DO
WriteString[" "]; WriteLongDecimal[param.node[LowHalf[cnt]]];
cnt ← cnt + 1;
IF cnt = param.count THEN { param ← param.next; cnt ← 0; };
ENDLOOP;
WriteString[" ] T "]; WriteCIFUnits[in.xOffset];
WriteString[" "]; WriteCIFUnits[in.yOffset]; WriteLine[""];
ENDLOOP;
WriteLine["SE;"];
RETURN[FALSE];
END;
WriteCap: PROCEDURE [cap: Node] =
BEGIN
WriteString["N "]; WriteLongDecimal[cap.node];
WriteString[" "]; WriteFloat[cap.carea[Diff]/scale2];
WriteString[" "]; WriteFloat[cap.cperim[Diff]/scale];
WriteString[" "]; WriteFloat[cap.carea[Poly]/scale2];
WriteString[" "]; WriteFloat[cap.cperim[Poly]/scale];
WriteString[" "]; WriteFloat[cap.carea[Metal]/scale2];
WriteString[" "]; WriteFloat[cap.cperim[Metal]/scale];
WriteLine[";"];
END;
WriteLocation: PROCEDURE [loc: NodeLocation] =
BEGIN
WriteString["PL "]; WriteLongDecimal[loc.node];
WriteString[" "]; WriteCIFUnits[loc.x];
WriteString[" "]; WriteCIFUnits[loc.y]; WriteLine[";"];
END;
WriteSegment: PROCEDURE [seg: Segment] =
BEGIN
WriteString["Seg "]; WriteLongDecimal[seg.node];
WriteString[" "]; WriteDecimal[seg.layer];
WriteString[" "]; WriteCIFUnits[seg.bx];
WriteString[" "]; WriteCIFUnits[seg.by];
WriteString[" "]; WriteCIFUnits[seg.tx];
WriteString[" "]; WriteCIFUnits[seg.ty]; WriteLine[";"];
END;
WriteTransistor: PROCEDURE [trans: Node] =
BEGIN
cnt: CARDINAL ← 0;
diffLen: REAL ← 0;
FOR d:Diffusion ← trans.diff,d.next UNTIL d = NIL DO
cnt ← cnt+1;
diffLen ← diffLen + d.length;
ENDLOOP;
SELECT cnt FROM
1 => {-- transistor with only one diffusion
-- See if it’s a butting contact
IF trans.poly # trans.diff.node THEN {
WriteString["Cap "]; WriteLongDecimal[trans.node];
WriteString[" "]; WriteLongDecimal[trans.poly];
WriteString[" "]; WriteLongDecimal[trans.diff.node];
WriteString[" loc="]; WriteTransLoc[trans];
WriteLine[";"];
ctrans ← ctrans + 1;
};
};
2 => {-- normal transistor
IF NOT trans.ion AND trans.nion THEN {
WriteString["e "];
etrans ← etrans + 1;
}
ELSE IF trans.ion AND NOT trans.nion THEN {
WriteString["d "];
dtrans ← dtrans + 1;
}
ELSE IF trans.ion AND trans.nion THEN {
WriteString["u "];
utrans ← utrans + 1;
}
ELSE CallDebugger["bug in transistor type checker"];
WriteLongDecimal[trans.poly];
WriteString["/"]; WriteFloat[(trans.perim-diffLen)/scale];
WriteString[" "]; WriteDiffusion[trans.diff];
WriteString[" "]; WriteDiffusion[trans.diff.next];
WriteString[" a="]; WriteFloat[trans.area/scale2];
WriteString[" loc="]; WriteTransLoc[trans];
WriteLine[";"];
};
ENDCASE => { -- bad transistor
WriteString["f "]; WriteLongDecimal[trans.node];
WriteString[" "]; WriteLongDecimal[trans.poly];
WriteString["/"]; WriteFloat[(trans.perim-diffLen)/scale];
FOR d:Diffusion ← trans.diff,d.next UNTIL d = NIL DO
WriteString[" "]; WriteDiffusion[d];
ENDLOOP;
WriteString[" loc="]; WriteTransLoc[trans];
WriteLine[";"];
btrans ← btrans + 1;
};
END;
WriteTransLoc: PROCEDURE[trans:Node] =
BEGIN
WriteFloat[trans.x/scale];WriteString[" "];WriteFloat[trans.y/scale];
END;
WriteDiffusion: PROCEDURE[d:Diffusion] =
BEGIN
WriteLongDecimal[d.node];WriteString["/"];WriteFloat[d.length/scale];
END;
WriteSymbolNumber: PROCEDURE[s: Symbol] =
BEGIN
WriteDecimal[GetProp[s.prop,countID]];
END;
locID: PropID ← GetNodeLocID[];
nodeID: PropID ← GetNodesID[];
nparamID: PropID ← GetNParamID[];
paramID: PropID ← GetParamID[];
intID: PropID ← GetIntTransID[];
extID: PropID ← GetExtTransID[];
intCapID: PropID ← GetIntCapID[];
extCapID: PropID ← GetExtCapID[];
segID: PropID ← GetSegmentID[];
countID: PropID ← AllocPropID[];
markID: PropID ← AllocPropID[];
count:CARDINAL;
etrans,dtrans,utrans,btrans,ctrans:LONG CARDINAL;
scale: REAL ← 250;
scale2: REAL ← scale*scale;
END.