DIRECTORY Globals, IO, Model, Parse, RealFns, Rope, SlopeModel; ModelImpl: CEDAR PROGRAM IMPORTS Globals, IO, Parse, RealFns, Rope, SlopeModel EXPORTS Model = BEGIN OPEN Model, Globals; diffCPerArea: PUBLIC REF REAL _ NEW[REAL _ .00029]; polyCPerArea: PUBLIC REF REAL _ NEW[REAL _ .00004]; metalCPerArea: PUBLIC REF REAL _ NEW[REAL _ .000026]; diffCPerPerim: PUBLIC REF REAL _ NEW[REAL _ .00023]; diffR: PUBLIC REF REAL _ NEW[REAL _ 60]; polyR: PUBLIC REF REAL _ NEW[REAL _ 3]; metalR: PUBLIC REF REAL _ NEW[REAL _ .04]; vdd: PUBLIC REF REAL _ NEW[REAL _ 5.0]; vinv: PUBLIC REF REAL _ NEW[REAL _ 2.5]; rUpFactor: PUBLIC REF REAL _ NEW[REAL _ 1.0]; rDownFactor: PUBLIC REF REAL _ NEW[REAL _ 1.0]; parmNames: ARRAY[0..9) OF Rope.ROPE _ [ "diffcperarea", "diffcperperim", "diffresistance", "metalcperarea", "metalresistance", "polycperarea", "polyresistance", "vdd", "vinv" ]; parmUnits: ARRAY[0..9) OF Rope.ROPE _ [ "pf/sq. micron", "pf/micron", "ohms/square", "pf/sq. micron", "ohms/square", "pf/sq. micron", "ohms/square", "volts", "volts" ]; parmLocs: ARRAY[0..9) OF REF REAL _ [ diffCPerArea, diffCPerPerim, diffR, metalCPerArea, metalR, polyCPerArea, polyR, vdd, vinv ]; nModels: INT = 2; curModel: INT _ 1; modelNames: ARRAY[0..nModels) OF Rope.ROPE _ [ "rc (simple lumped RC approximation)", "slope" ]; modelDelayProcs: ARRAY[0..nModels) OF DelayProc _ [ RCDelay, SlopeModel.SlopeDelay ]; TypeTable: PUBLIC ARRAY[0..maxFetTypes) OF TType; fieldNames: ARRAY[0..9) OF Rope.ROPE _ [ "cperarea", "cperwidth", "histrength", "lowstrength", "on", "rdown", "rup", "slopeparmsdown", "slopeparmsup" ]; ModelCmd: PUBLIC CmdProc = BEGIN index: INT; IF args = NIL THEN BEGIN FOR i:INT IN [0..nModels) DO IF i = curModel THEN IO.PutF[StdOut, "**** %s\n", IO.rope[modelNames[i]]] ELSE IO.PutF[StdOut, " %s\n", IO.rope[modelNames[i]]]; ENDLOOP; RETURN; END; TRUSTED {index _ Parse.Lookup[args.rope, DESCRIPTOR[modelNames]]}; IF index = -1 THEN BEGIN IO.PutF[StdOut, "%s isn't a model name.\n", IO.rope[args.rope]]; RETURN; END ELSE IF index = -2 THEN BEGIN IO.PutF[StdOut, "%s is an ambiguous model abbreviation.\n", IO.rope[args.rope]]; RETURN; END; curModel _ index; END; ParmCmd: PUBLIC CmdProc = BEGIN name: Rope.ROPE; valueArg: Arg; value: REAL; index: INT; ok: BOOLEAN; IF args = NIL THEN BEGIN FOR i:INTEGER IN [0..LENGTH[parmNames]) DO IO.PutF[StdOut, "%s = %f %s\n", IO.rope[parmNames[i]], IO.real[parmLocs[i]^], IO.rope[parmUnits[i]]]; ENDLOOP; RETURN; END; WHILE args # NIL DO name _ args.rope; args _ args.next; IF args = NIL THEN BEGIN IO.PutF[StdOut, "No value given for %s.\n", IO.rope[name]]; EXIT; END; valueArg _ args; args _ args.next; TRUSTED {index _ Parse.Lookup[name, DESCRIPTOR[parmNames]]}; IF index = -2 THEN BEGIN IO.PutF[StdOut, "%s isn't a model parameter.\n", IO.rope[name]]; LOOP; END; IF index = -1 THEN BEGIN IO.PutF[StdOut, "%s is an ambiguous abbreviation.\n", IO.rope[name]]; LOOP; END; [ok, value] _ Parse.Real[valueArg]; IF (value <= 0.0) OR (NOT ok) THEN BEGIN IO.PutF[StdOut, "Bad value given for %s.\n", IO.rope[name]]; LOOP; END; parmLocs[index]^ _ value; ENDLOOP; END; getSlope: PROC[args: Arg, ratio, rEff, outES: REF ParmArray] RETURNS [Arg] = BEGIN ok: BOOLEAN; val: REAL; i: INT; FOR i IN [0..maxSlopePoints) DO [ok, val] _ Parse.Real[args]; IF NOT ok THEN EXIT; args _ args.next; IF val < 0.0 THEN BEGIN IO.PutF[StdOut, "Can't have negative value %f in slope table.\n", IO.real[val]]; EXIT; END; ratio[i] _ val; [ok, val] _ Parse.Real[args]; IF NOT ok THEN BEGIN IO.PutRope[StdOut, "Only one number supplied for last slope table entry.\n"]; EXIT; END; args _ args.next; rEff[i] _ val; [ok, val] _ Parse.Real[args]; IF NOT ok THEN BEGIN IO.PutRope[StdOut, "Only two numbers supplied for last slope table entry.\n"]; EXIT; END; args _ args.next; outES[i] _ val; IF i > 0 THEN BEGIN IF ratio[i] < ratio[i-1] THEN BEGIN IO.PutF[StdOut, "Warning: edge speed ratio %f", IO.real[ratio[i]]]; IO.PutRope[StdOut, " isn't monotonically increasing.\n"]; IO.PutRope[StdOut, " Interpolation table truncated.\n"]; EXIT; END; END; ENDLOOP; IF i = 0 THEN BEGIN ratio[0] _ 0; rEff[0] _ 1000; outES[0] _ 0; i _ 1; END; IF i = 1 THEN BEGIN ratio[1] _ ratio[0] + 1000; rEff[1] _ rEff[0]; outES[1] _ outES[0]; ratio[2] _ -1; END ELSE IF i < maxSlopePoints THEN ratio[i] _ -1; RETURN [args]; END; printType: PROC[index: INTEGER] = BEGIN IO.PutF[StdOut, "%s: ", IO.rope[TypeTable[index].name]]; IF TypeTable[index].on0 THEN IO.PutRope[StdOut, "on gate0"]; IF TypeTable[index].on1 THEN IO.PutRope[StdOut, "on gate1"]; IF TypeTable[index].onAlways THEN IO.PutRope[StdOut, "on always"]; IO.PutF[StdOut, " histrength %d", IO.int[TypeTable[index].strengthHi]]; IO.PutF[StdOut, " lowstrength %d", IO.int[TypeTable[index].strengthLo]]; IO.PutF[StdOut, "\n cperarea %.3f cperwidth %.3f", IO.real[TypeTable[index].cPerArea], IO.real[TypeTable[index].cPerWidth]]; IO.PutF[StdOut, " rup %.1f rdown %.1f\n", IO.real[TypeTable[index].rUp], IO.real[TypeTable[index].rDown]]; IO.PutRope[StdOut, " Slope parameters up (ratio, rEff, outES) =\n"]; printSlope[TypeTable[index].upESRatio, TypeTable[index].upREff, TypeTable[index].upOutES, maxSlopePoints]; IO.PutRope[StdOut, " Slope parameters down (ratio, rEff, outES) =\n"]; printSlope[TypeTable[index].downESRatio, TypeTable[index].downREff, TypeTable[index].downOutES, maxSlopePoints]; END; printSlope: PROC[esRatio, rEff, outES: REF ParmArray, maxPoints: INT] = BEGIN lineHasStuff: BOOLEAN _ FALSE; FOR i:INT IN [0..maxPoints) DO IF esRatio[i] < 0 THEN EXIT; IO.PutF[StdOut, " %8.3f, %8.1f, %8.3f;", IO.real[esRatio[i]], IO.real[rEff[i]], IO.real[outES[i]]]; IF lineHasStuff THEN BEGIN lineHasStuff _ FALSE; IO.PutRope[StdOut, "\n"]; END ELSE lineHasStuff _ TRUE; ENDLOOP; IF lineHasStuff THEN IO.PutRope[StdOut, "\n"]; END; TransistorCmd: PUBLIC CmdProc = BEGIN type: INT; field: Rope.ROPE; valueArg: Arg; index, intVal: INT; realVal: REAL; ok: BOOLEAN; IF args = NIL THEN BEGIN FOR i:INTEGER IN [0..maxFetTypes) DO IF TypeTable[i] = NIL THEN RETURN; printType[i]; ENDLOOP; RETURN; END ELSE IF args.next = NIL THEN BEGIN FOR i: INTEGER IN [0..maxFetTypes) DO IF TypeTable[i] = NIL THEN EXIT; IF Rope.Equal[args.rope, TypeTable[i].name, FALSE] THEN BEGIN printType[i]; RETURN; END; ENDLOOP; IO.PutF[StdOut, "Transistor type %s doesn't exist.\n", IO.rope[args.rope]]; RETURN; END; type _ -1; FOR i: INTEGER IN [0..maxFetTypes) DO IF TypeTable[i] = NIL THEN BEGIN type _ i; TypeTable[type] _ NEW[TTypeRec _ [name: args.rope, strengthHi: 0, strengthLo: 0, cPerArea: 0, cPerWidth: 0, rUp: 0, rDown: 0, on0: FALSE, on1: TRUE, onAlways: FALSE, upESRatio: NEW[ParmArray _ [0, 1000, -1, 0, 0, 0, 0, 0, 0, 0]], upREff: NEW[ParmArray _ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], upOutES: NEW[ParmArray _ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], downESRatio: NEW[ParmArray _ [0, 1000, -1, 0, 0, 0, 0, 0, 0, 0]], downREff: NEW[ParmArray _ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], downOutES: NEW[ParmArray _ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]]; EXIT; END; IF Rope.Equal[args.rope, TypeTable[i].name, FALSE] THEN BEGIN type _ i; EXIT; END; ENDLOOP; args _ args.next; WHILE args # NIL DO field _ args.rope; args _ args.next; IF args = NIL THEN BEGIN IO.PutF[StdOut, "No value given for %s.\n", IO.rope[field]]; EXIT; END; valueArg _ args; args _ args.next; TRUSTED {index _ Parse.Lookup[field, DESCRIPTOR[fieldNames]]}; IF index = -2 THEN BEGIN IO.PutF[StdOut, "%s isn't a field name.\n", IO.rope[field]]; LOOP; END; IF index = -1 THEN BEGIN IO.PutF[StdOut, "%s is an ambiguous abbreviation.\n", IO.rope[field]]; LOOP; END; SELECT index FROM 0 => -- cperarea BEGIN [ok, realVal] _ Parse.Real[valueArg]; IF (NOT ok) OR (realVal < 0) THEN IO.PutRope[StdOut, "Bad capacitance value for cperarea.\n"] ELSE TypeTable[type].cPerArea _ realVal; END; 1 => -- cperwidth BEGIN [ok, realVal] _ Parse.Real[valueArg]; IF (NOT ok) OR (realVal < 0) THEN IO.PutRope[StdOut, "Bad capacitance value for cperwidth.\n"] ELSE TypeTable[type].cPerWidth _ realVal; END; 2 => -- histrength BEGIN [ok, intVal] _ Parse.Int[valueArg]; IF (NOT ok) OR (intVal < 0) THEN IO.PutRope[StdOut, "Bad value for histrength.\n"] ELSE TypeTable[type].strengthHi _ intVal; END; 3 => -- lowstrength BEGIN [ok, intVal] _ Parse.Int[valueArg]; IF (NOT ok) OR (intVal < 0) THEN BEGIN IO.PutRope[StdOut, "Bad value for lowstrength.\n"]; EXIT; END; TypeTable[type].strengthLo _ intVal; END; 4 => -- on BEGIN IF Rope.Equal[valueArg.rope, "gate1", TRUE] THEN BEGIN TypeTable[type].on1 _ TRUE; TypeTable[type].on0 _ FALSE; TypeTable[type].onAlways _ FALSE; END ELSE IF Rope.Equal[valueArg.rope, "gate0", TRUE] THEN BEGIN TypeTable[type].on0 _ TRUE; TypeTable[type].on1 _ FALSE; TypeTable[type].onAlways _ FALSE; END ELSE IF Rope.Equal[valueArg.rope, "always", TRUE] THEN BEGIN TypeTable[type].on0 _ FALSE; TypeTable[type].on1 _ FALSE; TypeTable[type].onAlways _ TRUE; END ELSE IO.PutF[StdOut, "Unknown \"on\" condition: %s\n", IO.rope[valueArg.rope]]; END; 5 => -- rdown BEGIN [ok, realVal] _ Parse.Real[valueArg]; IF (NOT ok) OR (realVal < 0) THEN IO.PutRope[StdOut, "Bad value for rdown.\n"] ELSE TypeTable[type].rDown _ realVal; END; 6 => -- rup BEGIN [ok, intVal] _ Parse.Int[valueArg]; IF (NOT ok) OR (realVal < 0) THEN IO.PutRope[StdOut, "Bad value for rup.\n"] ELSE TypeTable[type].rUp _ intVal; END; 7 => -- slopeparmsdown BEGIN args _ getSlope[valueArg, TypeTable[type].downESRatio, TypeTable[type].downREff, TypeTable[type].downOutES]; END; 8 => -- slopeparmsup BEGIN args _ getSlope[valueArg, TypeTable[type].upESRatio, TypeTable[type].upREff, TypeTable[type].upOutES]; END; ENDCASE; ENDLOOP; rUpFactor^ _ - RealFns.Ln[(vdd^ - vinv^)/vdd^]; rDownFactor^ _ - RealFns.Ln[vinv^/vdd^]; END; NameToIndex: PUBLIC PROC[name: Rope.ROPE] RETURNS [index: INT] = BEGIN FOR i:INTEGER IN [0..maxFetTypes) DO IF TypeTable[i] = NIL THEN RETURN [-1]; IF Rope.Equal[TypeTable[i].name, name, FALSE] THEN RETURN [i]; ENDLOOP; RETURN [-1]; END; Delay: PUBLIC DelayProc = BEGIN (modelDelayProcs[curModel])[stage, globalVars]; END; RCDelay: PUBLIC DelayProc = BEGIN f: Fet; r, c, tmp, rFactor: REAL; i: INT; stage.time _ -1.0; IF (stage.piece1Size = 0) AND (stage.piece2Size = 0) THEN BEGIN IO.PutRope[StdOut, "Crystal bug: nothing in stage!"]; RETURN; END; r _ 0.0; c _ 0.0; IF stage.rise THEN rFactor _ rUpFactor^ ELSE rFactor _ rDownFactor^; FOR i IN [0..stage.piece1Size) DO f _ stage.piece1Fet[i]; IF stage.rise THEN tmp _ TypeTable[f.type].rUp ELSE tmp _ TypeTable[f.type].rDown; IF tmp = 0 THEN RETURN; r _ r + tmp*f.aspect + (stage.piece1Node[i].res*rFactor); ENDLOOP; FOR i IN [0..stage.piece2Size) DO f _ stage.piece2Fet[i]; IF f # NIL THEN BEGIN IF stage.rise THEN tmp _ TypeTable[f.type].rUp ELSE tmp _ TypeTable[f.type].rDown; IF tmp = 0 THEN RETURN; r _ r + tmp*f.aspect; c _ c + f.area*TypeTable[f.type].cPerArea; END; r _ r + (stage.piece2Node[i].res*rFactor); c _ c + stage.piece2Node[i].cap; ENDLOOP; IF stage.piece1Size # 0 THEN r _ r - (stage.piece1Node[stage.piece1Size-1].res*rFactor) ELSE BEGIN r _ r - (stage.piece2Node[0].res*rFactor); c _ c - stage.piece2Node[0].cap; END; stage.time _ (r*c)/1000.0 + stage.prev.time; END; TypeTable[fetNEnh] _ NEW[TTypeRec _ [name: "NETran", strengthHi: 2, strengthLo: 3, cPerArea: .0004, cPerWidth: .00025, rUp: 24800, rDown: 9720, on0: FALSE, on1: TRUE, onAlways: FALSE, upESRatio: NEW[ParmArray _ [0, .0014, .0026, .017, .16, 1.6, 16, -1, 0, 0]], upREff: NEW[ParmArray _ [24800, 24800, 24600, 25800, 38400, 153000, 1070000, 0, 0, 0]], upOutES: NEW[ParmArray _ [37.2, 37.2, 37.5, 38, 42, 162, 1340, 0, 0, 0]], downESRatio: NEW[ParmArray _ [0, .018, .086, .74, 7.3, 73, -1, 0, 0, 0]], downREff: NEW[ParmArray _ [9720, 9720, 10100, 14000, 36300, 164000, 0, 0, 0, 0]], downOutES: NEW[ParmArray _ [4.0, 4.0, 4.0, 4.3, 10.2, 41.0, 0, 0, 0, 0]]]]; TypeTable[fetNEnhP] _ NEW[TTypeRec _ [name: "nenhp", strengthHi: 2, strengthLo: 3, cPerArea: .0004, cPerWidth: .00025, rUp: 200000, rDown: 200000, on0: FALSE, on1: TRUE, onAlways: FALSE, upESRatio: NEW[ParmArray _ [0, 1000, -1, 0, 0, 0, 0, 0, 0, 0]], upREff: NEW[ParmArray _ [200000, 200000, 0, 0, 0, 0, 0, 0, 0, 0]], upOutES: NEW[ParmArray _ [100, 100, 0, 0, 0, 0, 0, 0, 0, 0]], downESRatio: NEW[ParmArray _ [0, 1000, -1, 0, 0, 0, 0, 0, 0, 0]], downREff: NEW[ParmArray _ [200000, 200000, 0, 0, 0, 0, 0, 0, 0, 0]], downOutES: NEW[ParmArray _ [100, 100, 0, 0, 0, 0, 0, 0, 0, 0]]]]; TypeTable[fetNDep] _ NEW[TTypeRec _ [name: "NDTran", strengthHi: 2, strengthLo: 3, cPerArea: .0004, cPerWidth: .00025, rUp: 50000, rDown: 23000, on0: FALSE, on1: FALSE, onAlways: TRUE, upESRatio: NEW[ParmArray _ [0, 1000, -1, 0, 0, 0, 0, 0, 0, 0]], upREff: NEW[ParmArray _ [50000, 50000, 0, 0, 0, 0, 0, 0, 0, 0]], upOutES: NEW[ParmArray _ [75, 75, 0, 0, 0, 0, 0, 0, 0, 0]], downESRatio: NEW[ParmArray _ [0, 1000, -1, 0, 0, 0, 0, 0, 0, 0]], downREff: NEW[ParmArray _ [23000, 23000, 0, 0, 0, 0, 0, 0, 0, 0]], downOutES: NEW[ParmArray _ [9.5, 9.5, 0, 0, 0, 0, 0, 0, 0, 0]]]]; TypeTable[fetNLoad] _ NEW[TTypeRec _ [name: "nload", strengthHi: 2, strengthLo: 0, cPerArea: 0, cPerWidth: .00025, rUp: 21900, rDown: 0, on0: FALSE, on1: FALSE, onAlways: TRUE, upESRatio: NEW[ParmArray _ [0, .406, 1.344, 4.027, 13.4, 40.3, -1, 0, 0, 0]], upREff: NEW[ParmArray _ [21900, 21000, 23800, 31400, 43300, 57800, 0, 0, 0, 0]], upOutES: NEW[ParmArray _ [13.3, 13.3, 13.0, 21, 44.7, 107, 0, 0, 0, 0]], downESRatio: NEW[ParmArray _ [0, 1000, -1, 0, 0, 0, 0, 0, 0, 0]], downREff: NEW[ParmArray _ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], downOutES: NEW[ParmArray _ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]]; TypeTable[fetNSuper] _ NEW[TTypeRec _ [name: "nsuper", strengthHi: 2, strengthLo: 0, cPerArea: .0004, cPerWidth: .00025, rUp: 4800, rDown: 5100, on0: FALSE, on1: FALSE, onAlways: TRUE, upESRatio: NEW[ParmArray _ [0, .214, .464, 1.139, 3.58, 10.96, 36.2, 108, -1, 0]], upREff: NEW[ParmArray _ [4800, 4700, 5400, 6800, 8500, 8200, 1900, -17600, 0, 0]], upOutES: NEW[ParmArray _ [3.5, 3.5, 4.2, 6.7, 15.8, 42.9, 140, 413, 0, 0]], downESRatio: NEW[ParmArray _ [0, 1000, -1, 0, 0, 0, 0, 0, 0, 0]], downREff: NEW[ParmArray _ [5100, 5100, 0, 0, 0, 0, 0, 0, 0, 0]], downOutES: NEW[ParmArray _ [2.5, 2.5, 0, 0, 0, 0, 0, 0, 0, 0]]]]; TypeTable[fetNChan] _ NEW[TTypeRec _ [name: "nchan", strengthHi: 2, strengthLo: 3, cPerArea: .0004, cPerWidth: .00025, rUp: 24800, rDown: 9720, on0: FALSE, on1: TRUE, onAlways: FALSE, upESRatio: NEW[ParmArray _ [0, .0014, .0026, .017, .16, 1.6, 16, -1, 0, 0]], upREff: NEW[ParmArray _ [24800, 24800, 24600, 25800, 38400, 153000, 1070000, 0, 0, 0]], upOutES: NEW[ParmArray _ [37.2, 37.2, 37.5, 38, 42, 162, 1340, 0, 0, 0]], downESRatio: NEW[ParmArray _ [0, .018, .086, .74, 7.3, 73, -1, 0, 0, 0]], downREff: NEW[ParmArray _ [9720, 9720, 10100, 14000, 36300, 164000, 0, 0, 0, 0]], downOutES: NEW[ParmArray _ [4.0, 4.0, 4.0, 4.3, 10.2, 41.0, 0, 0, 0, 0]]]]; TypeTable[fetPChan] _ NEW[TTypeRec _ [name: "PETran", strengthHi: 2, strengthLo: 2, cPerArea: .0004, cPerWidth: .00025, rUp: 19050, rDown: 200000, on0: TRUE, on1: FALSE, onAlways: FALSE, upESRatio: NEW[ParmArray _ [0, .017, .028, .118, 1.05, 10.3, 31, 103, -1, 0]], upREff: NEW[ParmArray _ [19050, 19050, 19100, 20100, 27900, 42400, 23400, -114000, 0, 0]], upOutES: NEW[ParmArray _ [8.9, 8.9, 8.9, 8.9, 10.0, 25, 46.3, 97, 0, 0]], downESRatio: NEW[ParmArray _ [0, 1000, -1, 0, 0, 0, 0, 0, 0, 0]], downREff: NEW[ParmArray _ [200000, 200000, 0, 0, 0, 0, 0, 0, 0, 0]], downOutES: NEW[ParmArray _ [100, 100, 0, 0, 0, 0, 0, 0, 0, 0]]]]; rUpFactor^ _ - RealFns.Ln[(vdd^ - vinv^)/vdd^]; rDownFactor^ _ - RealFns.Ln[vinv^/vdd^]; END. hFILE: ModelImpl.mesa Last edited by Ousterhout, November 22, 1983 3:32 pm Christian LeCocq April 11, 1986 2:19:41 pm PST This file contains the implementation of various routines and constants for dealing with technology-specific electrical information. The model-independent parameters, and tables used to access them. Gives names of various parasitic parameters. Gives units for various parmaters (used in printing them out). Information about different models: Names of type table fields: If no arguments, just print out information about the available models. If no arguments, then just print out all current values. Arguments must come in pairs. This is a utility routine used to read in slope table information. The arguments are processed in batches of three, filling up the tables. The return result is the next argument after the last one used. Watch out for decreasing ratio values. Mark the end of the table with a negative ratio. If there's only a single entry, add a second one so that interpolation and extrapolation will work. This is a utility routine used to print out all the information for a transistor of a given type. This is a utility routine used to print out the values in slope tables. The values in the tables are printed in a reasonably pretty fashion, two entries from each table per line. If there are no arguments, print out all fields of all transistor types. If there is only one argument print out all fields for that transistor type. Make sure that the type name exists. Create a new one if necessary. Process pairs. This procedure updates the time value in the given stage by computing the delay in the stage and combining that with the time from the previous stage. A simple RC model is used to compute the delay. Make sure that there is stuff in the path. Go through the two pieces of the path, summing all the resistances in both pieces and the capacitances in piece2 (this code assumes that the capacitance in piece1 has already been drained away before the driving transistor turns on). If a zero FET resistance is found, it means that the transistor can't drive in the given direction, so quit. Throw out the capacitance and resistance from the node that is supplying the signal (either the first node in piece1, or the first node in piece2 if there isn't a piece1). This node is treated here as an infinite source of charge. Κž˜Jšœ™šœ4™4Icode™.—J˜Jšœ„™„J˜šΟk ˜ J˜Jšœ˜J˜J˜J˜J˜J˜ —J˜JšΟn œœ˜š˜J˜Jšœ˜J˜J˜J˜J˜ —Jšœ˜Jšœœ˜J˜JšœA™AJ˜Jš œœœœœœ ˜3Jš œœœœœœ ˜3Jš œœœœœœ ˜5Jš œœœœœœ ˜4Jš œœœœœœ˜(Jš œœœœœœ˜'Jš œœœœœœ˜*J˜Jš œœœœœœ˜'Jš œœœœœœ˜(J˜Jš œ œœœœœ˜-Jš œ œœœœœ˜/J˜Jšœ,™,J˜šœ œœœ˜%J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜—J˜Jšœ>™>J˜šœ œœœ˜%J˜J˜J˜ J˜J˜J˜J˜J˜J˜J˜J˜—J˜š œ œœœœ˜$J˜J˜ J˜J˜J˜J˜J˜ J˜J˜J˜J˜—J˜Jšœ#™#J˜Jšœ œ˜Jšœ œ˜J˜šœ œ œœ˜,J˜J˜&J˜J˜—J˜šœœ œ ˜1J˜J˜J˜J˜—J˜Jšž œœœœ˜1J˜Jšœ™J˜šœ œœœ˜&J˜J˜ J˜ J˜ J˜J˜J˜J˜J˜J˜J˜—J˜J˜šžœœ ˜Jš˜Jšœœ˜ J˜JšœG™GJ˜šœœ˜Jš˜šœœœ˜šœ˜Jšœœ˜4—Jšœœœ˜9Jšœ˜Jšœ˜Jšœ˜—J˜Jšœ" œ˜Bšœ ˜Jš˜Jšœ*œ˜@Jšœ˜Jš˜—šœœ ˜Jš˜Jšœ9œ˜PJšœ˜Jšœ˜—J˜Jšœ˜——J˜J˜šžœœ ˜Jš˜Jšœ œ˜J˜Jšœœ˜ Jšœœ˜ Jšœœ˜ J˜Jšœ8™8J˜šœœ˜Jš˜š œœœœ ˜*Jšœœœœ˜eJšœ˜—Jšœ˜Jšœ˜—J˜Jšœ*™*J˜šœœ˜J˜J˜šœœ˜Jš˜Jšœ)œ ˜;Jšœ˜Jšœ˜—J˜J˜J˜Jšœ œ˜<šœ ˜Jš˜Jšœ.œ ˜@Jšœ˜Jšœ˜—šœ ˜Jš˜Jšœ3œ ˜EJšœ˜Jšœ˜—J˜#šœœœ˜"Jš˜Jšœ*œ ˜šœ ˜Jš˜Jšœ)œ˜Jšœ˜—Jšœ˜ Jšœ˜—J˜J˜šžœœ ˜Jš˜J˜/Jšœ˜J˜—šžœœ ˜JšœΗ™ΗJ˜Jš˜J˜Jšœœ˜Jšœœ˜J˜Jšœ*™*J˜J˜šœœ˜9Jš˜Jšœ4˜6Jšœ˜Jšœ˜J˜—JšœΦ™ΦJ˜J˜J˜Jšœ œ˜'Jšœ˜šœœ˜!J˜Jšœ œ˜.Jšœ˜#Jšœ œœ˜J˜9Jšœ˜—šœœ˜!J˜šœœ˜Jš˜Jšœ œ˜.Jšœ˜#Jšœ œœ˜J˜J˜*Jšœ˜—J˜*J˜ Jšœ˜—J˜Jšœη™ηJ˜šœ˜J˜:—š˜Jš˜J˜*J˜ Jšœ˜—J˜J˜,Jšœ˜—J˜J˜šœœ ˜#˜?Jšœ1œ˜7Jšœœ œ˜šœ œ ˜J˜1—šœœ ˜J˜?—šœ œ ˜J˜0—šœ œ ˜J˜,—šœ œ ˜J˜7—šœ œ ˜J˜0———šœœ ˜$˜>Jšœ4œ˜:Jšœœ œ˜šœ œ ˜J˜$—šœœ ˜J˜*—šœ œ ˜J˜$—šœ œ ˜J˜$—šœ œ ˜J˜*—šœ œ ˜J˜&———šœœ ˜#˜?Jšœ2œ˜8Jšœœ œ˜šœ œ ˜J˜$—šœœ ˜J˜(—šœ œ ˜J˜"—šœ œ ˜J˜$—šœ œ ˜J˜(—šœ œ ˜J˜&———šœœ ˜$˜:Jšœ.œ˜4Jšœœ œ˜šœ œ ˜J˜2—šœœ ˜J˜8—šœ œ ˜J˜/—šœ œ ˜J˜$—šœ œ ˜J˜ —šœ œ ˜J˜"———šœœ ˜%˜?Jšœ0œ˜6Jšœœ œ˜šœ œ ˜J˜7—šœœ ˜J˜:—šœ œ ˜J˜2—šœ œ ˜J˜$—šœ œ ˜J˜&—šœ œ ˜J˜&———šœœ ˜$˜>Jšœ1œ˜7Jšœœ œ˜šœ œ ˜J˜1—šœœ ˜J˜?—šœ œ ˜J˜0—šœ œ ˜J˜,—šœ œ ˜J˜7—šœ œ ˜J˜0———šœœ ˜$˜?Jšœ3œ˜8Jšœœ œ˜šœ œ ˜J˜3—šœœ ˜J˜B—šœ œ ˜J˜0—šœ œ ˜J˜$—šœ œ ˜J˜*—šœ œ ˜J˜&———J˜J˜/˜(J˜—Jšœ˜—…—=J]P