DIRECTORY Build, Delay, DPrint, Flow, Globals, IO, Model, Parse, Printout, Rope, StagePool; DelayImpl: CEDAR PROGRAM IMPORTS Build, DPrint, Globals, Flow, IO, Model, Parse, Printout, StagePool EXPORTS Delay = BEGIN OPEN Delay; delayCount: INT _ 0; DelayLimit: PUBLIC INT _ 200000; stageOverflowCount: INT _ 0; stageOverflowLimit: INT _ 10; Print: PUBLIC BOOLEAN _ FALSE; PrintAll: PUBLIC BOOLEAN _ FALSE; BusThreshold: PUBLIC REAL _ 2.0; chaseVGCalls: INT _ 0; chaseGatesCalls: INT _ 0; chaseLoadsCalls: INT _ 0; propagateCalls: INT _ 0; feedbacks: INT _ 0; hiTime, loTime: REAL; chaseVG: PROC[stage: Globals.Stage, globalVars: Globals.GlobalVars] RETURNS [BOOLEAN] = BEGIN p: Globals.Pointer; f: Globals.Fet; node, other: Globals.Node; size: INT; result: BOOLEAN; { chaseVGCalls _ chaseVGCalls + 1; size _ stage.piece1Size; node _ stage.piece1Node[size-1]; IF node.inPath THEN RETURN [TRUE]; node.inPath _ TRUE; IF Globals.Stop^ OR (delayCount >= DelayLimit) THEN GOTO giveUp; IF node.bus OR node.input OR node.cap >= BusThreshold THEN BEGIN IF NOT node.always0 THEN BEGIN stage.piece2Size _ 1; stage.rise _ TRUE; IF NOT chaseGates[stage, globalVars] THEN GOTO giveUp; END; IF NOT node.always1 THEN BEGIN stage.piece2Size _ 1; stage.rise _ FALSE; IF NOT chaseGates[stage, globalVars] THEN GOTO giveUp; END; GOTO done; END; FOR p _ node.firstPointer, p.next UNTIL p = NIL DO f _ p.fet; IF f.source = node THEN BEGIN other _ f.drain; IF NOT f.flowFromDrain THEN LOOP; END ELSE IF f.drain = node THEN BEGIN other _ f.source; IF NOT f.flowFromSource THEN LOOP; END ELSE LOOP; IF f.forcedOff THEN LOOP; IF f.firstFlow # NIL THEN IF NOT Flow.Lock[f, other] THEN LOOP; IF size >= Globals.pieceLimit THEN BEGIN stageOverflowCount _ stageOverflowCount + 1; IF f.firstFlow # NIL THEN Flow.Unlock[f, other]; IF stageOverflowCount > stageOverflowLimit THEN GOTO done; IO.PutF[Globals.StdOut, "More than %d transistors in series, see %s.\n", IO.int[Globals.pieceLimit], IO.rope[Printout.NodeRope[node, globalVars]]]; IF stageOverflowCount = stageOverflowLimit THEN IO.PutRope[Globals.StdOut, "No more messages of this kind will be printed....\n"]; GOTO done; END; stage.piece1Fet[size] _ f; stage.piece1Node[size] _ other; stage.piece1Size _ size + 1; IF other = globalVars.VddNode THEN BEGIN stage.piece2Size _ 1; stage.rise _ TRUE; result _ chaseGates[stage, globalVars]; END ELSE IF other = globalVars.GroundNode THEN BEGIN stage.piece2Size _ 1; stage.rise _ FALSE; result _ chaseGates[stage, globalVars]; END ELSE result _ chaseVG[stage, globalVars]; IF f.firstFlow # NIL THEN Flow.Unlock[f, other]; IF NOT result THEN GOTO giveUp; ENDLOOP; GOTO done; EXITS giveUp => BEGIN IO.PutF[Globals.StdOut, "ChaseVG giving up at %s.\n", IO.rope[Printout.NodeRope[node, globalVars]]]; node.inPath _ FALSE; RETURN [FALSE]; END; done => BEGIN node.inPath _ FALSE; RETURN [TRUE]; END } END; chaseGates: PROC[stage: Globals.Stage, globalVars: Globals.GlobalVars] RETURNS [BOOLEAN] = BEGIN p: Globals.Pointer; f: Globals.Fet; node, other: Globals.Node; size: INT; result: BOOLEAN; { chaseGatesCalls _ chaseGatesCalls + 1; size _ stage.piece2Size; stage.piece2Fet[size-1] _ NIL; -- expected by the modelling routines. node _ stage.piece2Node[size-1]; IF node.always0 OR node.always1 THEN RETURN [TRUE]; IF node.inPath THEN BEGIN feedbacks _ feedbacks + 1; IF stage.prev.time >= DPrint.Threshold[memory] THEN DPrint.Record[stage.prev, memory]; RETURN [TRUE]; END; IF node.precharged AND stage.rise THEN RETURN [TRUE]; node.inPath _ TRUE; IF Globals.Stop^ OR (delayCount >= DelayLimit) THEN GOTO giveUp; IF (stage.piece1Size # 0) OR (size # 1) THEN BEGIN IF node.input AND NOT node.output THEN GOTO done; Model.Delay[stage, globalVars]; IF stage.rise THEN BEGIN IF stage.time > node.hiTime THEN BEGIN node.hiTime _ stage.time; Propagate[stage, globalVars]; END; END ELSE IF stage.time > node.loTime THEN BEGIN node.loTime _ stage.time; Propagate[stage, globalVars]; END; IF Globals.Stop^ OR (delayCount > DelayLimit) THEN GOTO giveUp; IF node.bus OR node.cap >= BusThreshold THEN GOTO done; END; FOR p _ node.firstPointer, p.next UNTIL p = NIL DO f _ p.fet; IF f.forcedOff THEN LOOP; IF f.source = node THEN BEGIN other _ f.drain; IF NOT f.flowFromSource THEN LOOP; END ELSE IF f.drain = node THEN BEGIN other _ f.source; IF NOT f.flowFromDrain THEN LOOP; END ELSE LOOP; IF other.always1 OR other.always0 THEN LOOP; IF f.firstFlow # NIL THEN IF NOT Flow.Lock[f, node] THEN LOOP; IF size >= Globals.pieceLimit THEN BEGIN IF f.firstFlow # NIL THEN Flow.Unlock[f, node]; stageOverflowCount _ stageOverflowCount + 1; IF stageOverflowCount > stageOverflowLimit THEN GOTO done; IO.PutF[Globals.StdOut, "More than %d transistors in series, see %s.\n", IO.int[Globals.pieceLimit], IO.rope[Printout.NodeRope[node, globalVars]]]; IF stageOverflowCount = stageOverflowLimit THEN IO.PutRope[Globals.StdOut, "No more messages of this kind will be printed....\n"]; GOTO done; END; stage.piece2Fet[size-1] _ f; stage.piece2Node[size] _ other; stage.piece2Size _ size + 1; result _ chaseGates[stage, globalVars]; IF f.firstFlow # NIL THEN Flow.Unlock[f, node]; IF NOT result THEN GOTO giveUp; ENDLOOP; GOTO done; EXITS giveUp => BEGIN IO.PutF[Globals.StdOut, "ChaseGates giving up at %s.\n", IO.rope[Printout.NodeRope[node, globalVars]]]; node.inPath _ FALSE; RETURN [FALSE]; END; done => BEGIN node.inPath _ FALSE; RETURN [TRUE]; END } END; chaseLoads: PROC[node: Globals.Node, stage: Globals.Stage, globalVars: Globals.GlobalVars] = BEGIN p: Globals.Pointer; f: Globals.Fet; other: Globals.Node; chaseLoadsCalls _ chaseLoadsCalls + 1; IF node.always1 OR node.always0 THEN RETURN; IF node.inPath THEN BEGIN feedbacks _ feedbacks + 1; IF stage.prev.time >= DPrint.Threshold[memory] THEN DPrint.Record[stage.prev, memory]; RETURN; END; FOR p _ node.firstPointer, p.next UNTIL p = NIL DO f _ p.fet; IF NOT (f.forcedOn OR f.onAlways) THEN LOOP; IF f.source = node THEN BEGIN other _ f.drain; IF NOT f.flowFromDrain THEN LOOP; END ELSE IF f.drain = node THEN BEGIN other _ f.source; IF NOT f.flowFromSource THEN LOOP; END ELSE LOOP; IF other.always1 THEN stage.rise _ TRUE ELSE IF other.always0 THEN stage.rise _ FALSE ELSE LOOP; IF f.firstFlow # NIL THEN IF NOT Flow.Lock[f, other] THEN LOOP; stage.piece1Size _ 0; stage.piece2Size _ 2; stage.piece2Node[0] _ other; stage.piece2Node[1] _ node; stage.piece2Fet[0] _ f; [] _ chaseGates[stage, globalVars]; IF f.firstFlow # NIL THEN Flow.Unlock[f, other]; RETURN; ENDLOOP; node.inPath _ TRUE; FOR p _ node.firstPointer, p.next UNTIL p = NIL DO f _ p.fet; IF f.forcedOff THEN LOOP; IF f.source = node THEN BEGIN other _ f.drain; IF NOT f.flowFromSource THEN LOOP; END ELSE IF f.drain = node THEN BEGIN other _ f.source; IF NOT f.flowFromDrain THEN LOOP; END ELSE LOOP; IF f.firstFlow # NIL THEN BEGIN IF Flow.Lock[f, node] THEN BEGIN chaseLoads[other, stage, globalVars]; Flow.Unlock[f, node]; END; END ELSE chaseLoads[other, stage, globalVars]; ENDLOOP; node.inPath _ FALSE; RETURN; END; Propagate: PUBLIC PROC[prevStage: Globals.Stage, globalVars: Globals.GlobalVars] = BEGIN p: Globals.Pointer; f: Globals.Fet; node: Globals.Node; stage: Globals.Stage; result: BOOLEAN; oldInPath: BOOLEAN; propagateCalls _ propagateCalls + 1; delayCount _ delayCount + 1; IF Globals.Stop^ OR (delayCount >= DelayLimit) THEN BEGIN IF delayCount = DelayLimit THEN BEGIN IO.PutF[Globals.StdOut, "Aborting delay analysis: no solution after %d stages.\n", IO.int[DelayLimit]]; IO.PutRope[Globals.StdOut, "Perhaps you forgot to mark some of the flow in"]; IO.PutRope[Globals.StdOut, " pass transistors?\n The information below may point"]; IO.PutRope[Globals.StdOut, " out the trouble spot.\n"]; END; RETURN; END; node _ prevStage.piece2Node[prevStage.piece2Size - 1]; IF PrintAll OR Print THEN IO.PutF[Globals.StdOut, "Delay at %s set to %6.1fns up, %6.1fns down.\n", IO.rope[Printout.NodeRope[node, globalVars]], IO.real[node.hiTime], IO.real[node.loTime]]; IF prevStage.time >= DPrint.Threshold[any] THEN DPrint.Record[prevStage, any]; IF node.dynamic AND (prevStage.time >= DPrint.Threshold[memory]) THEN DPrint.Record[prevStage, memory]; IF node.watched AND (prevStage.time >= DPrint.Threshold[watched]) THEN DPrint.Record[prevStage, watched]; stage _ StagePool.New[]; stage.prev _ prevStage; IF node.input OR node.bus OR node.cap >= BusThreshold THEN BEGIN stage.piece1Size _ 0; stage.piece2Size _ 1; stage.piece2Node[0] _ node; stage.rise _ prevStage.rise; oldInPath _ node.inPath; node.inPath _ FALSE; result _ chaseGates[stage, globalVars]; node.inPath _ oldInPath; IF NOT result THEN BEGIN StagePool.Free[stage]; RETURN; END; END; FOR p _ node.firstPointer, p.next UNTIL p = NIL DO f _ p.fet; IF f.gate # node THEN LOOP; IF f.onAlways OR f.forcedOn OR f.forcedOff THEN LOOP; IF (prevStage.rise AND NOT f.on0) OR ((NOT prevStage.rise) AND NOT f.on1) THEN BEGIN IF f.flowFromSource THEN BEGIN IF f.firstFlow # NIL THEN IF NOT Flow.Lock[f, f.source] THEN GOTO skipSource; stage.piece1Size _ 1; stage.piece1Fet[0] _ f; stage.piece1Node[0] _ f.source; stage.piece2Size _ 1; stage.piece2Node[0] _ f.drain; IF f.source = globalVars.GroundNode THEN BEGIN stage.rise _ FALSE; result _ chaseGates[stage, globalVars]; END ELSE IF f.source = globalVars.VddNode THEN BEGIN stage.rise _ TRUE; result _ chaseGates[stage, globalVars]; END ELSE result _ chaseVG[stage, globalVars]; IF f.firstFlow # NIL THEN Flow.Unlock[f, f.source]; IF NOT result THEN BEGIN StagePool.Free[stage]; RETURN; END; EXITS skipSource => NULL; END; IF f.flowFromDrain THEN BEGIN IF f.firstFlow # NIL THEN IF NOT Flow.Lock[f, f.drain] THEN GOTO skipDrain; stage.piece1Size _ 1; stage.piece1Fet[0] _ f; stage.piece1Node[0] _ f.drain; stage.piece2Size _ 1; stage.piece2Node[0] _ f.source; IF f.drain = globalVars.GroundNode THEN BEGIN stage.rise _ FALSE; result _ chaseGates[stage, globalVars]; END ELSE IF f.drain = globalVars.VddNode THEN BEGIN stage.rise _ TRUE; result _ chaseGates[stage, globalVars]; END ELSE result _ chaseVG[stage, globalVars]; IF f.firstFlow # NIL THEN Flow.Unlock[f, f.drain]; IF NOT result THEN BEGIN StagePool.Free[stage]; RETURN; END; EXITS skipDrain => NULL; END; END ELSE BEGIN IF f.flowFromSource THEN BEGIN oldInPath _ f.source.inPath; f.source.inPath _ TRUE; [] _ chaseLoads[f.drain, stage, globalVars]; f.source.inPath _ oldInPath; END; IF f.flowFromDrain THEN BEGIN oldInPath _ f.drain.inPath; f.drain.inPath _ TRUE; [] _ chaseLoads[f.source, stage, globalVars]; f.drain.inPath _ oldInPath; END; END; ENDLOOP; StagePool.Free[stage]; END; DelayCmd: PUBLIC Globals.CmdProc = BEGIN DelayProc: PROC [node: Globals.Node] ~ { stage: Globals.Stage _ StagePool.New[]; stage.prev _ NIL; stage.piece1Size _ 0; stage.piece2Size _ 1; stage.piece2Node[0] _ node; stage.piece2Fet[0] _ NIL; IF hiTime >= 0 THEN BEGIN stage.time _ hiTime; stage.rise _ TRUE; IF hiTime > node.hiTime THEN node.hiTime _ hiTime; Propagate[stage, globalVars]; END; IF loTime >= 0 THEN BEGIN stage.time _ loTime; stage.rise _ FALSE; IF loTime > node.loTime THEN node.loTime _ loTime; Propagate[stage, globalVars]; END; StagePool.Free[stage]; }; nodeName: Rope.ROPE; ok: BOOLEAN; IF args = NIL THEN GOTO noArgs; nodeName _ args.rope; args _ args.next; IF args = NIL THEN GOTO noArgs; [ok, hiTime] _ Parse.Real[args]; IF NOT ok THEN GOTO noArgs; args _ args.next; IF args = NIL THEN GOTO noArgs; [ok, loTime] _ Parse.Real[args]; IF NOT ok THEN GOTO noArgs; DelayProc[Build.NodeFromRope[nodeName, globalVars]]; EXITS noArgs => BEGIN IO.PutRope[Globals.StdOut, "Delay requires three arguments:\n"]; IO.PutRope[Globals.StdOut, " node name, rise time, fall time.\n"]; END; END; Stats: PUBLIC PROC[] = BEGIN IO.PutF[Globals.StdOut, "Number of calls to chase Vdd or GND: %d.\n", IO.int[chaseVGCalls]]; IO.PutF[Globals.StdOut, "Number of calls to chase gates: %d.\n", IO.int[chaseGatesCalls]]; IO.PutF[Globals.StdOut, "Number of calls to chase loads: %d.\n", IO.int[chaseLoadsCalls]]; IO.PutF[Globals.StdOut, "Number of calls to propagate delays: %d.\n", IO.int[propagateCalls]]; IO.PutF[Globals.StdOut, "Number of delay feedback paths: %d.\n", IO.int[feedbacks]]; END; END. ÆFILE: DelayImpl.mesa Last edited by Ousterhout, October 4, 1983 4:23 pm Christian LeCocq December 30, 1986 11:38:50 am PST This file contains routines that figure out delays through the circuit network, from when one node changes until everything in the system is stable. Actually, the routines in this file just compute stages (chains of transistors) that are affected, then call routines in the model package to compute delays. The general process is as follows: When it is determined that a gate will rise or fall, and that this is the worst rise or fall time seen so far for the gate, then delay information has to be propagated. First, find all paths from the transistor to a source of Ground or Vdd (busses and inputs are also sources). Then for each source, find all paths from the other side of the transistor to gates, busses, or outputs. Compute the delay for each combination of source and target. If this results in a new worst-case settling time for the target, repeat the process recursively starting at the target. The search is depth-first, and has to be in order to handle circularities cleanly. Hash, Hash, Rope, Counter to keep us from looping infinitely during delay calculation: Counter to keep us from printing too many stage overflow messages: Flags telling what, if any, information to print out while calculating delays: Threshold capacitance (in pfs) at which a node is considered to be a bus: Counters used to gather statistics: Things that get passed between command-level routine and table searching action routines: Stage describes the part of the stage seen so far. On entry, the stage contains >= 1 entries in piece1, plus piece2Node[0] must be initialized with the correct value for the first call to chaseGates. The return value is TRUE if the procedure terminated normally, and FALSE if it gave up because too many nodes had been searched. This procedure continues searching for sources of Vdd or Ground, calling itself recursively until all possible paths have been tried. For each source of Vdd or Ground, chaseGates gets called. If we've already seen this node, return immediately. See if this node is highly capacitive (input or bus). If it is, then chaseGates immediately. Scan all of the fets whose sources or drains connect to the node, and either call chaseGates if the connect to Vdd or Ground, or call this procedure recursively. Make sure that information can flow through this transistor in the desired direction. Make sure that there's room in the delay stage for more info. If not, it's an error (too many transistors in series). Add more information to the delay stage. Stage describes a partially-complete stage up to and including the node from which this procedure is to continue chasing gates. The return value is TRUE if the procedure terminated normally, and FALSE if it gave up because too many nodes had been searched. This procedure chases out gates and outputs recursively, augmenting piece2 of the stage as it goes. When it finds gates and outputs, it calculates delays and invokes Propagate to propagate them. When this procedure is called, piece1 of the stage must be complete (meaning 0 or more entries for fets and nodes). If this node is fixed in value, then return immediately: the delay to here must be zero. If the node is already in the path we're checking, then also return to avoid circular scans. In this case, we've just discovered a static memory element (feedback). Before returning, if this is a static memory element then record the delay. All memory nodes found here are of the "OR" type. If this node is precharged, then there's no need to consider rising transitions. If the node is an input, then we can usually return right away since its delay is fixed by the outside world. There are two exceptions. If the node is also an output, then we still have to calculate delays to it. Also, if this node is absolutely the only entry in its stage so far, then this stage starts from the node; in that case we are computing delays FROM the node, so we skip the delay calculation and go on to search through transistors. If this is a bus, then Propagate did everything that needs to be done, and there's nothing left for us to do. Now go through all the fets that connect to this node. For each non-load transistor, keep chasing gates on the other side, unless the other side is an input or we're going the wrong way through a transistor. Make sure that there's enough space in the stage for more info. If not, then it's an error (too many transistors in series). This procedure is used to chase out loads that can drive a stage when a transistor turns off. Node tells where to start searching for loads, and stage is used when (if) a load is found to record stage information. This procedure searches out recursively from node to find all the loads that can legally be reached from it. For each load found, the stage is set up and chaseGates is processed to look for things the load can drive. Design note: when a given transistor turns off, we don't find every possible load that is connected to the turned-off fet though transistor channels (that might involve expensive searches through pass transistor arrays). Instead, we only look for loads that can be driven by the turned-off fet. This will handle the common case of loads that are part of gates, but might not handle other cases. Caveat emptor! Make sure that we're not looping circularly. A circularity here corresponds to an "AND" type of memory node: when this happens, call the delay recorder. See if this node has any loads attached to it. If so, then chase gates from the load and return. A load is defined as a transistor that is always on and connects to a node that is forced to a particular value. This node doesn't have any loads. In this case, continue working outwards, looking recursively for loads. Note: the inPath flag doesn't get set until here, because it must be UNSET when we call chaseGates above (chaseGates will set the flag for itself). Quit if too many delays have been calculated. This probably means that nodes aren't marked properly (user error), or else Crystal is messing up. IF PrintAll OR (Print AND ((Rope.Fetch[node.name, 0] < '0) OR Rope.Fetch[node.name, 0] > '9)) THEN IO.PutF[Globals.StdOut, "Delay at %s set to %6.1fns up, %6.1fns down.\n", IO.rope[Printout.NodeRope[node]], IO.real[node.hiTime], IO.real[node.loTime]]; Record delay information for posterity. If this node is an input or bus, then call chaseGates immediately. An empty piece1 is used to indicate the input status to the device modellers. Be sure to clear the inPath flag here. This is necessary because when this procedure is called from chaseGates with a bus, because the bus is both the destination of one stage and the trigger of another. On the other hand, be sure to restore the inPath flag before continuing in the procedure. Scan through all of the fets connecting to this node. If the signal change could potentially turn the transistor on, then look first at the source side, then at the drain side. For each side, if info could flow from that side then call chaseVG to find the source. If the side connects directly to a supply rail, then bypass the call to chaseVG and go straight to chaseGates (this is a performance optimization and isn't strictly necessary). This transition could only have turned the transistor off. In this case, we scan out on each side of the transistor looking for a load to take over now that the transistor is turned off. Be sure to mark the node on the side of the transistor that we're NOT searching as in the path. Otherwise, chaseLoads will consider pullup paths that go back through the path we just turned off! Parse the arguments. Hash.Enumerate[table: globalVars.nodeTable, pattern: nodeName, proc: delayProc, errorStream: Globals.StdOut]; Ê—˜Jšœ™šœ2™2Icode™2—J˜Jšœ×™×J˜JšœŒ™ŒJ˜šÏk ˜ J˜J˜J˜J˜J˜J™Jšœ˜J˜J˜J˜ J˜J˜ —J˜JšÏn œœ˜š˜J˜J˜J˜J˜J™Jšœ˜J˜J˜J˜ J™J˜ —Jšœ˜Jš˜Jšœ˜ J˜JšœD™DJšœ œ˜Jšœ œœ ˜ J˜JšœB™BJ˜Jšœœ˜Jšœœ˜J˜JšœN™NJ˜Jšžœœœœ˜Jšžœœœœ˜!J˜JšœI™IJ˜Jšž œœœ˜ J˜Jšœ#™#J˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœ œ˜J˜JšœY™YJ˜Jšœœ˜J˜J˜šÏbœœ7œœ˜WJšœ‰™‰J˜Jš˜Jšœ˜Jšœ˜Jšœ˜Jšœœ˜ Jšœœ˜J˜J˜J˜ J˜Jšœ4™4J˜J˜J˜ Jšœ œœœ˜"Jšœœ˜J˜Jšœœœœ˜@J˜Jšœ]™]J˜šœ œ œ˜:Jš˜šœœ˜Jš˜J˜Jšœ œ˜Jšœœœœ˜6Jšœ˜—šœœ˜Jš˜J˜Jšœ œ˜Jšœœœœ˜6Jšœ˜—Jšœ˜ Jšœ˜—J˜Jšœ¡™¡J˜šœœœ˜2J˜ J˜JšœU™U˜šœ˜Jš˜J˜Jšœœœœ˜!Jš˜—šœœ˜Jš˜J˜Jšœœœœ˜"Jš˜—Jšœœ˜ Jšœ œœ˜Jšœœœœœœœ˜?J˜Jšœ=™=Jšœ7™7J˜šœ˜"Jš˜J˜,Jšœœœ˜0Jšœ)œœ˜:JšœFœœ,˜“šœ)˜/JšœP˜R—Jšœ˜ Jšœ˜—J˜Jšœ(™(J˜J˜J˜J˜J˜šœ˜"Jš˜J˜Jšœ œ˜Jšœ'˜'Jš˜—šœœ˜*Jš˜J˜Jšœ œ˜Jšœ'˜'Jš˜—Jšœ%˜)Jšœœœ˜0Jšœœœœ˜Jšœ˜—Jšœ˜—J˜š˜Jšœ ˜Jšœ3œ,˜dJšœœ˜Jšœœ˜Jšœ˜J˜Jšœ˜ Jšœœ˜Jšœœ˜Jš˜—J˜Jšœ˜—J˜J˜šŸ œœ7œœ˜ZJšœ»™»J˜Jš˜Jšœ˜Jšœ˜Jšœ˜Jšœœ˜ Jšœœ˜J˜J˜J˜&J˜Jšœÿ™ÿJ˜J˜JšœœÏc&˜FJ˜ Jš œœœœœ˜3šœ ˜Jš˜J˜šœ-˜3J˜"—Jšœœ˜Jšœ˜—J˜JšœP™PJ˜Jš œœ œœœ˜5Jšœœ˜J˜Jšœœœœ˜@J˜JšœÀ™ÀJ˜šœœ ˜,Jš˜Jš œ œœ œœ˜1J˜šœ ˜Jš˜šœ˜ Jš˜J˜Jšœ˜Jšœ˜—Jš˜—šœœ˜%Jš˜J˜Jšœ˜Jšœ˜—Jšœœœœ˜?J˜Jšœm™mJ˜Jšœ œœœ˜7Jšœ˜—J˜JšœÐ™ÐJ˜šœœœ˜2J˜ Jšœ œœ˜šœ˜Jš˜J˜Jšœœœœ˜"Jš˜—šœœ˜Jš˜J˜Jšœœœœ˜!Jš˜—Jšœœ˜ Jšœœœœ˜,šœœœœœœœ˜>J˜—šœ~™~J˜—šœ˜"Jš˜Jšœœœ˜/J˜,Jšœ)œœ˜:JšœFœœ,˜“šœ)˜/JšœP˜R—Jšœ˜ Jšœ˜J˜—J˜J˜J˜Jšœ'˜'Jšœœœ˜/Jšœœœœ˜Jšœ˜—Jšœ˜ J˜š˜Jšœ ˜Jšœ6œ,˜gJšœœ˜Jšœœ˜Jšœ˜J˜Jšœ˜ Jšœœ˜Jšœœ˜Jš˜—J˜Jšœ˜—J˜J˜šŸ œœL˜\Jšœ±™±J˜Jšœ™J˜Jš˜Jšœ˜Jšœ˜Jšœ˜J˜J˜&J˜Jšœš™šJ˜Jšœœœœ˜,šœ ˜Jš˜J˜šœ-˜3J˜"—Jšœ˜Jšœ˜—J˜JšœÓ™ÓJ˜šœœœ˜2J˜ Jš œœ œ œœ˜,šœ˜Jš˜J˜Jšœœœœ˜!Jš˜—šœœœ˜Jš˜J˜Jšœœœœ˜"Jš˜—Jšœœ˜ Jšœœ˜'Jšœœœ˜-Jšœœ˜ Jšœœœœœœœ˜?J˜J˜J˜J˜J˜J˜Jšœ#˜#Jšœœœ˜0Jšœ˜Jšœ˜—J˜Jšœ€™€J˜Jšœœ˜šœœœ˜2J˜ Jšœ œœ˜šœ˜Jš˜J˜Jšœœœœ˜"Jš˜—šœœ˜Jš˜J˜Jšœœœœ˜!Jš˜—Jšœœ˜ šœœ˜Jš˜šœ˜Jš˜J˜%J˜Jšœ˜—Jš˜—Jšœ&˜*Jšœ˜—J˜Jšœœ˜Jšœ˜Jšœ˜J˜—J˜šž œœœ<˜SJš˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœœ˜Jšœ œ˜J˜J˜$J˜Jšœ‘™‘J˜J˜šœœ˜3Jš˜šœ˜Jš˜JšœQœ˜hJšœK˜MJšœR˜TJšœ5˜7Jšœ˜—Jšœ˜Jšœ˜—J˜J˜6šœ œ™Jšœ!œ!™HJšœGœœœ™˜—šœ œ˜JšœGœ+œœ˜¤—J˜Jšœ'™'J˜šœ)˜/J˜—šœœ.˜EJ˜!—šœœ/˜FJ˜"—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šœ5™5J˜šœœœ˜2J˜ Jšœœœ˜Jš œ œ œ œœ˜5J˜Jšœƒ™ƒJ˜šœœœ˜!Jš œœœœ˜,Jš˜šœ˜Jš˜š œœœœœ˜7Jšœœ ˜—J˜J˜J˜J˜J˜šœ"˜(Jš˜Jšœ œ˜Jšœ'˜'Jš˜—šœœ˜*Jš˜Jšœ œ˜Jšœ'˜'Jš˜—Jšœ%˜)Jšœœœ˜3šœœ˜Jš˜J˜Jšœ˜Jšœ˜—Jšœœ˜Jšœ˜—šœ˜Jš˜š œœœœœ˜6Jšœœ ˜—J˜J˜J˜J˜J˜šœ!˜'Jš˜Jšœ œ˜Jšœ'˜'Jš˜—šœœ˜)Jš˜Jšœ œ˜Jšœ'˜'Jš˜—Jšœ%˜)Jšœœœ˜2šœœ˜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š˜šÐbn œœ˜(Jšœ'˜'J˜Jšœ œ˜J˜J˜J˜Jšœœ˜šœ ˜Jš˜J˜Jšœ œ˜Jšœœ˜2Jšœ˜Jšœ˜—šœ ˜Jš˜J˜Jšœ œ˜Jšœœ˜2Jšœ˜Jšœ˜—J˜Jšœ˜J˜—Jšœœ˜Jšœœ˜ J˜Jšœ™J˜Jšœœœœ˜J˜J˜Jšœœœœ˜J˜ Jšœœœœ˜J˜Jšœœœœ˜J˜ Jšœœœœ˜J˜Jšœm™mJšœ4˜4šœ ˜Jš˜Jšœ>˜@JšœB˜DJšœ˜—Jšœ˜—J˜J˜šžœœœ˜Jš˜JšœCœ˜\Jšœ>œ˜ZJšœ>œ˜ZJšœCœ˜^Jšœ>œ˜TJšœ˜J˜—Jšœ˜—…—/Êc'