-- File: DJExtFlatten.mesa -- flatten hierarchy created by the disjoint circuit extractor -- Written by Martin Newell/Dan Fitzpatrick July 1981 -- Last edited: 12-Aug-81 13:49:30 DIRECTORY DisjointPropDefs: FROM "DisjointPropDefs" USING [GetLongProp], DisjointTypes: FROM "DisjointTypes" USING [Symbol, Instance, PropID], DJExtDefs: FROM "DJExtDefs", DJExtractDefs: FROM "DJExtractDefs" USING [GetNodeLocID, GetNodesID, GetNParamID, GetParamID, GetIntTransID, GetIntCapID], DJExtMergeDefs: FROM "DJExtMergeDefs" USING [InitMerge, FinishMerge, Merge, Lookup], DJExtTypes: FROM "DJExtTypes" USING [ActualParameter, NodeLocation, Node, Diffusion], DJExtUtilsDefs: FROM "DJExtUtilsDefs" USING [Create, Close, WriteCIFUnits, WriteLongDecimal, WriteFloat], IODefs: FROM "IODefs" USING [WriteString, WriteLine, GetOutputStream, SetOutputStream], Inline: FROM "Inline" USING [LowHalf], Runtime: FROM "Runtime" USING [CallDebugger], StreamDefs: FROM "StreamDefs" USING [StreamHandle]; DJExtFlatten: PROGRAM IMPORTS DisjointPropDefs, DJExtractDefs, DJExtMergeDefs, DJExtUtilsDefs, IODefs, Inline, Runtime EXPORTS DJExtDefs = BEGIN OPEN DisjointPropDefs, DisjointTypes, DJExtractDefs, DJExtMergeDefs, DJExtTypes, DJExtUtilsDefs, IODefs, Inline, Runtime, StreamDefs; Flatten: PUBLIC PROCEDURE [symbol: Symbol] = BEGIN FileName:STRING _ "file.sim"; default:StreamHandle _ GetOutputStream[]; out:StreamHandle; InitMerge[]; Offset _ 0; xOffset _ yOffset _ 0; etrans _ dtrans _ utrans _ btrans _ ctrans _ 0; out _ Create[FileName]; SetOutputStream[out]; WriteString["| Scale set at "]; WriteFloat[scale]; WriteLine[""]; TFlatten[symbol]; Close[out]; WriteLongDecimal[etrans]; WriteString[": enhancement, "]; WriteLongDecimal[dtrans]; WriteString[": depletion"]; IF utrans # 0 THEN { WriteString[", "]; 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[""]; Offset _ 0; xOffset _ yOffset _ 0; out _ Create["file.nodes"]; SetOutputStream[out]; LFlatten[symbol]; Close[out]; SetOutputStream[default]; FinishMerge[]; END; TFlatten: PROCEDURE [symbol: Symbol] = BEGIN cnt: LONG CARDINAL _ 0; n: LONG CARDINAL; param: ActualParameter; curOffset: LONG INTEGER _ Offset; xcur: REAL _ xOffset; ycur: REAL _ yOffset; -- for each transistor in symbol output it to file FOR p: Node _ GetLongProp[symbol.prop,intID],p.next UNTIL p = NIL DO WriteTransistor[p]; ENDLOOP; -- for each capacitor in symbol output it to file FOR cap:Node _ GetLongProp[symbol.prop,intCapID],cap.next UNTIL cap = NIL DO WriteCap[cap]; ENDLOOP; -- examine each of the sub-symbols Offset _ GetLongProp[symbol.prop,nNodesID] + Offset; param _ GetLongProp[symbol.prop,paramID]; FOR in: Instance _ symbol.insts,in.next UNTIL in = NIL DO xOffset _ xcur + in.xOffset; yOffset _ ycur + in.yOffset; -- set up equivelences between formal and actual parameters n _ GetLongProp[in.symbol.prop,nparamID]; FOR i: LONG CARDINAL IN [0..n) DO [] _ Merge[i+Offset+LONG[1],param.node[LowHalf[cnt]]+curOffset]; cnt _ cnt + 1; IF cnt = param.count THEN { cnt _ 0; param _ param.next; }; ENDLOOP; -- recurse TFlatten[in.symbol]; ENDLOOP; xOffset _ xcur; yOffset _ ycur; END; LFlatten: PROCEDURE [symbol: Symbol] = BEGIN cnt: LONG CARDINAL _ 0; param: ActualParameter; curOffset: LONG INTEGER _ Offset; xcur: REAL _ xOffset; ycur: REAL _ yOffset; -- for each node location in symbol output it to file FOR p: NodeLocation _ GetLongProp[symbol.prop,nodeLocID],p.next UNTIL p = NIL DO WriteLocation[p]; ENDLOOP; -- examine each of the sub-symbols Offset _ GetLongProp[symbol.prop,nNodesID] + Offset; param _ GetLongProp[symbol.prop,paramID]; FOR in: Instance _ symbol.insts,in.next UNTIL in = NIL DO xOffset _ xcur + in.xOffset; yOffset _ ycur + in.yOffset; -- recurse LFlatten[in.symbol]; ENDLOOP; xOffset _ xcur; yOffset _ ycur; END; WriteLocation: PROCEDURE [p:NodeLocation] = BEGIN WriteString["94 "]; WriteLongDecimal[Lookup[p.node+Offset]]; WriteString[" "]; WriteCIFUnits[p.x+xOffset]; WriteString[" "]; WriteCIFUnits[p.y+yOffset]; WriteLine[";"]; END; WriteCap: PROCEDURE [cap: Node] = BEGIN WriteString["N "]; WriteLongDecimal[Lookup[cap.node+Offset]]; 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; WriteTransistor: 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 { WriteString["C "]; WriteLongDecimal[Lookup[trans.poly+Offset]]; WriteString[" "]; WriteLongDecimal[Lookup[trans.diff.node+Offset]]; WriteString[" "]; 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[Lookup[trans.poly+Offset]]; WriteString[" "]; WriteLongDecimal[Lookup[trans.diff.node+Offset]]; WriteString[" "]; WriteLongDecimal[Lookup[trans.diff.next.node+Offset]]; WriteString[" "]; WriteTransRatio[trans]; WriteString[" "]; WriteTransLoc[trans]; WriteLine[";"]; }; ENDCASE => { -- bad transistor WriteString["f "]; WriteLongDecimal[Lookup[trans.node+Offset]]; WriteString[" "]; WriteLongDecimal[Lookup[trans.poly+Offset]]; FOR d:Diffusion _ trans.diff,d.next UNTIL d = NIL DO WriteString[" "]; WriteLongDecimal[Lookup[d.node+Offset]]; ENDLOOP; WriteString[" "]; WriteTransLoc[trans]; WriteLine[";"]; btrans _ btrans + 1; }; END; WriteTransLoc: PROCEDURE[trans:Node] = BEGIN WriteFloat[(trans.x+xOffset)/scale]; WriteString[" "]; WriteFloat[(trans.y+yOffset)/scale]; END; WriteTransRatio: PROCEDURE [t:Node] = BEGIN l,w: REAL; [l,w] _ FindTransRatio[t]; WriteFloat[l/scale]; WriteString[" "]; WriteFloat[w/scale]; END; FindTransRatio: PROCEDURE [t:Node] RETURNS[len,wid:REAL] = BEGIN area,p,d1,d2: REAL; area _ t.area; d1 _ t.diff.length; d2 _ t.diff.next.length; p _ (t.perim -d1 - d2)/2; IF 0.95*d1 < d2 AND 0.95*d2 < d1 THEN -- let's say d1 = d2 RETURN[p,d1]; IF d1 > d2 THEN { tmp:REAL _ d1; d1 _ d2; d2 _ tmp; }; -- make d2 > d1 len _ p - d2 + d1; IF len > d1 THEN { -- assume transistor is T shaped k:REAL _ (area - (d1 * len))/(d2 - d1); -- length of wide part of T j:REAL _ len - k; -- length of skinny part of T s:REAL _ MIN[(d2-d1)/2,k]; -- transition length r:REAL _ (j/d1) + (s*2/(d1+d2)) + ((k-s)/d2); -- resistance wid _ len/r; -- effective width } ELSE { -- can't be T shaped; use heuristic len _ (area/d2); wid _ d1; }; END; Offset: LONG CARDINAL; xOffset,yOffset: REAL; nodeLocID: PropID _ GetNodeLocID[]; nNodesID: PropID _ GetNodesID[]; paramID: PropID _ GetParamID[]; nparamID: PropID _ GetNParamID[]; intID: PropID _ GetIntTransID[]; intCapID: PropID _ GetIntCapID[]; etrans,dtrans,utrans,btrans,ctrans:LONG CARDINAL; scale: REAL _ 250; scale2: REAL _ scale*scale; END. (672)\184b10B801b12B277b8B987b9B191i47I108i46I112i31I222i56I247i7I3b1B70b9B172i50I119i31I222i7I75b13B220b9B451b16B159i34I8i29I308i17I701i14I377b13B134b15B137b14B205i17I76i12I50i29I47i24I32i26I38i17I52i10I28i15I22i32I