<> <> <> <> DIRECTORY Globals, IO, Model, Printout, SlopeModel; SlopeModelImpl: CEDAR PROGRAM IMPORTS Globals, IO, Model, Printout EXPORTS SlopeModel = BEGIN OPEN Globals, Model; <> maxUpRatio: ARRAY[0..maxFetTypes) OF REAL _ ALL[0]; maxDownRatio: ARRAY[0..maxFetTypes) OF REAL _ ALL[0]; SlopeDelay: PUBLIC DelayProc = BEGIN f: Fet; r, c, resVolts, rFactor, rcIntegral, tmp: REAL; rEff, ratio: REF ParmArray; thisC, thisR, tmp2: REAL; esIntegral, es: REAL; isLoad: BOOLEAN; type: TType; i: INT; <> stage.time _ -1.0; stage.edgeSpeed _ 0; IF (stage.piece1Size = 0) AND (stage.piece2Size <= 1) THEN BEGIN IO.PutRope[StdOut, "Crystal bug: nothing in stage!\n"]; RETURN; END; <> IF stage.rise THEN BEGIN resVolts _ vdd^ - vinv^; rFactor _ rUpFactor^; END ELSE BEGIN resVolts _ vinv^; rFactor _ rDownFactor^; END; <
> IF (stage.piece1Size = 0) AND (stage.piece2Node[0].always0 OR stage.piece2Node[0].always1) THEN isLoad _ TRUE ELSE isLoad _ FALSE; <> r _ 0.0; c _ 0.0; es _ 0.0; rcIntegral _ 0.0; esIntegral _ 0.0; FOR i IN [0..stage.piece1Size) DO IF i # 0 THEN BEGIN f _ stage.piece1Fet[i]; type _ TypeTable[f.type]; IF stage.rise THEN BEGIN tmp _ type.upREff[0]; es _ es + type.upOutES[0] * f.aspect; END ELSE BEGIN tmp _ type.downREff[0]; es _ es + type.downOutES[0] * f.aspect; END; IF tmp = 0 THEN RETURN; r _ r + (tmp * f.aspect); END; <> IF i # (stage.piece1Size - 1) THEN BEGIN tmp _ stage.piece1Node[i].res; r _ r + (tmp * rFactor); es _ es + tmp/(resVolts*1000); END; ENDLOOP; FOR i IN [0..stage.piece2Size) DO <> IF (i=0) AND isLoad THEN LOOP; <> IF (i # 0) OR (stage.piece1Size # 0) THEN BEGIN thisR _ stage.piece2Node[i].res; thisC _ stage.piece2Node[i].cap; r _ r + (thisR*rFactor); c _ c + thisC; rcIntegral _ rcIntegral + (r * thisC); es _ es + thisR/(resVolts*1000); esIntegral _ esIntegral + (es * thisC); END; f _ stage.piece2Fet[i]; IF f # NIL THEN BEGIN type _ TypeTable[f.type]; IF stage.rise THEN BEGIN thisR _ type.upREff[0]; es _ es + type.upOutES[0] * f.aspect; END ELSE BEGIN thisR _ type.downREff[0]; es _ es + type.downOutES[0] * f.aspect; END; IF thisR = 0 THEN RETURN; r _ r + thisR*f.aspect; thisC _ f.area * type.cPerArea; c _ c + thisC; rcIntegral _ rcIntegral + (thisC * r); esIntegral _ esIntegral + (thisC * es); END; ENDLOOP; <> IF stage.piece1Size = 0 THEN BEGIN IF NOT isLoad THEN BEGIN stage.time _ rcIntegral/1000.0 + stage.prev.time; stage.edgeSpeed _ esIntegral; RETURN; END; f _ stage.piece2Fet[0]; END ELSE f _ stage.piece1Fet[0]; <> type _ TypeTable[f.type]; IF stage.rise THEN BEGIN ratio _ type.upESRatio; rEff _ type.upREff; esIntegral _ esIntegral + (c * type.upOutES[0] * f.aspect); END ELSE BEGIN ratio _ type.downESRatio; rEff _ type.downREff; esIntegral _ esIntegral + (c * type.downOutES[0] * f.aspect); END; <> IF rEff[0] = 0 THEN RETURN; IF c = 0 THEN BEGIN IO.PutF[StdOut, "Zero capacitance in stage leading to %s!\n", IO.rope[Printout.NodeRope[stage.piece2Node[stage.piece2Size-1], globalVars]]]; stage.time _ stage.prev.time; stage.edgeSpeed _ 0; RETURN; END; tmp _ stage.prev.edgeSpeed/esIntegral; FOR i IN [0..maxSlopePoints-1) DO IF tmp < ratio[i+1] THEN EXIT; IF ratio[i+1] < ratio[i] THEN EXIT; ENDLOOP; <> IF tmp >= ratio[i+1] THEN BEGIN IF stage.rise THEN BEGIN IF tmp > maxUpRatio[f.type] THEN BEGIN maxUpRatio[f.type] _ tmp; IO.PutF[StdOut, "Warning: ran off end of %s up slope table with\n", IO.rope[type.name]]; IO.PutF[StdOut, " edge speed ratio %f. Maybe you should ", IO.real[tmp]]; IO.PutRope[StdOut, "expand\n the range of the table.\n"]; END; END ELSE BEGIN IF tmp > maxDownRatio[f.type] THEN BEGIN maxDownRatio[f.type] _ tmp; IO.PutF[StdOut, "Warning: ran off end of %s down slope table with\n", IO.rope[type.name]]; IO.PutF[StdOut, " edge speed ratio %f. Maybe you should ", IO.real[tmp]]; IO.PutRope[StdOut, "expand\n the range of the table.\n"]; END; END; i _ i-1; END; tmp _ (tmp - ratio[i])/(ratio[i+1] - ratio[i]); tmp2 _ f.aspect * (rEff[i] + (tmp * (rEff[i+1] - rEff[i]))); rcIntegral _ rcIntegral + tmp2*c; stage.time _ rcIntegral/1000.0 + stage.prev.time; stage.edgeSpeed _ esIntegral; END; END.