DIRECTORY Build, Check, Delay, DPrint, Flow, FS, Globals, HashTable, IO, Mark, Model, Parse, Printout, Rope, TerminalIO; Main: CEDAR PROGRAM IMPORTS Build, Check, Delay, DPrint, Flow, FS, HashTable, IO, Mark, Model, Parse, Printout, TerminalIO EXPORTS Globals = BEGIN OPEN Globals; StdOut: PUBLIC IO.STREAM _ TerminalIO.TOS[]; DupsOK: PUBLIC BOOLEAN _ FALSE; Stop: PUBLIC REF BOOLEAN _ NEW[BOOLEAN _ FALSE]; notQuit: BOOLEAN _ TRUE; -- FALSE means ending Crystal. ivalue: INT; CmdTable: ARRAY[0..30) OF Rope.ROPE _ [ "quit", "bus node node ...", "capacitance pfs node node ...", "check", "clear", "critical [file] [index{m}]", "delay", "dump file", "flow in/out/off/ignore/normal flow flow ...", "help", "input node node ...", "markdynamic node value node value ...", "model [name]", "options [name value] [name value] ...", "output node node ...", "parameter", "prcapacitance [-t pfs] [node node ...]", "precharged node node ...", "prfets [node node ...]", "prnodes [node node ...]", "prresistance [-t ohms] [node node ...]", "ratio [limit value] [limit value] ...", "recompute", "resistance ohms node node ...", "set 0/1 node node ...", "source file", "statistics", "transistor", "undump file", "watch node node ..." ]; CmdProcs: ARRAY[0..30) OF Globals.CmdProc _ [ QuitCmd, Mark.BusCmd, Mark.CapCmd, Check.CheckCmd, ClearCmd, DPrint.CriticalCmd, Delay.DelayCmd, DPrint.DumpCmd, Flow.FlowCmd, HelpCmd, Mark.InputCmd, MarkDynamicCmd, Model.ModelCmd, OptionsCmd, Mark.OutputCmd, Model.ParmCmd, Printout.PrintCap, Mark.PrechargedCmd, Printout.PrintFets, Printout.PrintNodes, Printout.PrintRes, DummyCmd, DPrint.RecomputeCmd, Mark.ResCmd, Mark.SetCmd, SourceCmd, StatsCmd, Model.TransistorCmd, DummyCmd, Mark.WatchCmd ]; CmdClass: TYPE = {model, afterClear, circuit, dynamic, check, setup, delay, clear, anytime}; curClass: CmdClass _ model; marked: BOOLEAN; classNames: ARRAY CmdClass OF Rope.ROPE _ [ "model", "clear", "circuit", "markdynamic", "check", "setup", "delay", "clear", "miscellaneous" ]; classes: ARRAY[0..30) OF CmdClass _ [ circuit, -- build circuit, -- bus circuit, -- capacitance check, -- check clear, -- clear anytime, -- critical delay, -- delay anytime, -- dump circuit, -- flow anytime, -- help circuit, -- input dynamic, -- markdynamic model, -- model anytime, -- options circuit, -- output model, -- parameter anytime, -- prcapacitance setup, -- precharged anytime, -- prfets anytime, -- prnodes anytime, -- prresistance check, -- ratio anytime, -- recompute circuit, -- resistance setup, -- set anytime, -- source anytime, -- stats model, -- transistor anytime, -- undump anytime -- watch ]; DummyCmd: Globals.CmdProc = BEGIN IO.PutRope[StdOut, "this command is no longer supported\n"]; END; HelpCmd: Globals.CmdProc = BEGIN FOR i: INTEGER IN [0..LENGTH[CmdTable]) DO IO.PutF[StdOut, "%s\n", IO.rope[CmdTable[i]]]; ENDLOOP; END; QuitCmd: Globals.CmdProc = BEGIN notQuit _ FALSE; END; SourceCmd: Globals.CmdProc = BEGIN stream: IO.STREAM; msg: Rope.ROPE; IF args = NIL THEN BEGIN IO.PutRope[StdOut, "No file name given.\n"]; RETURN; END; stream _ FS.StreamOpen[args.rope ! FS.Error => IF error.group # bug THEN {msg _ error.explanation; CONTINUE}]; IF msg # NIL THEN BEGIN IO.PutF[StdOut, "Couldn't open %s: %s.\n", IO.rope[args.rope], IO.rope[msg]]; RETURN; END; IntrpCmds[stream, FALSE, globalVars]; IO.Close[stream]; END; StatsCmd: Globals.CmdProc = BEGIN Build.Stats[]; Flow.Stats[]; Mark.Stats[]; Delay.Stats[]; DPrint.Stats[]; END; OptionsCmd: Globals.CmdProc = BEGIN optionTable: ARRAY[0..19) OF Rope.ROPE _ [ "bus", "graphics", "limit", "mempaths", "noprintedgespeeds", "noseedelays", "noseedynamic", "noseesettings", "paths", "printedgespeeds", "ratiodups", "ratiolimit", "seealldelays", "seeallsettings", "seedelays", "seedynamic", "seesettings", "units", "watchpaths" ]; index, i: INT; r: REAL; ok: BOOLEAN; anyOptions: BOOLEAN _ FALSE; WHILE args # NIL DO anyOptions _ TRUE; TRUSTED {index _ Parse.Lookup[rope: args.rope, table: DESCRIPTOR[optionTable]]}; IF index = -1 THEN IO.PutF[StdOut, "Ambiguous option name: %s.\n", IO.rope[args.rope]] ELSE IF index = -2 THEN IO.PutF[StdOut, "Unknown option name: %s.\n", IO.rope[args.rope]] ELSE SELECT index FROM 0 => BEGIN args _ args.next; [ok, r] _ Parse.Real[args]; IF NOT ok THEN IO.PutRope[StdOut, "No bus threshold given.\n"] ELSE Delay.BusThreshold _ r; END; 1 => BEGIN args _ args.next; IF args = NIL THEN IO.PutRope[StdOut, "No graphical style given.\n"] ELSE IO.PutRope[StdOut, "Sorry, \"graphics\" isn't implemented yet.\n"]; END; 2 => BEGIN args _ args.next; [ok, i] _ Parse.Int[args]; IF NOT ok THEN IO.PutRope[StdOut, "No delay limit value given.\n"] ELSE Delay.DelayLimit _ i; END; 3 => BEGIN args _ args.next; [ok, i] _ Parse.Int[args]; IF NOT ok THEN IO.PutRope[StdOut, "No memory path count given.\n"] ELSE IF i > DPrint.MaxPaths THEN IO.PutF[StdOut, "Can't record more than %d paths.\n", IO.int[DPrint.MaxPaths]] ELSE DPrint.NumPaths[memory] _ i; END; 4 => BEGIN DPrint.PrintEdgeSpeeds _ FALSE; END; 5 => BEGIN Delay.Print _ FALSE; Delay.PrintAll _ FALSE; END; 6=> Mark.SeeDynamic _ FALSE; 7 => BEGIN Mark.SeeSettings _ FALSE; Mark.SeeAllSettings _ FALSE; END; 8 => BEGIN args _ args.next; [ok, i] _ Parse.Int[args]; IF NOT ok THEN IO.PutRope[StdOut, "No path count given.\n"] ELSE IF i > DPrint.MaxPaths THEN IO.PutF[StdOut, "Can't record more than %d paths.\n", IO.int[DPrint.MaxPaths]] ELSE DPrint.NumPaths[any] _ i; END; 9 => BEGIN DPrint.PrintEdgeSpeeds _ TRUE; END; 10 => BEGIN END; 11 => BEGIN END; 12 => Delay.PrintAll _ TRUE; 13 => Mark.SeeAllSettings _ TRUE; 14 => BEGIN Delay.PrintAll _ FALSE; Delay.Print _ TRUE; END; 15 => Mark.SeeDynamic _ TRUE; 16 => BEGIN Mark.SeeAllSettings _ FALSE; Mark.SeeSettings _ TRUE; END; 17 => BEGIN args _ args.next; [ok, r] _ Parse.Real[args]; IF NOT ok THEN IO.PutRope[StdOut, "No units value given.\n"] ELSE BEGIN Build.Units _ r; Printout.Units _ r; END; END; 18 => BEGIN args _ args.next; [ok, i] _ Parse.Int[args]; IF NOT ok THEN IO.PutRope[StdOut, "No watched path count given.\n"] ELSE IF i > DPrint.MaxPaths THEN IO.PutF[StdOut, "Can't record more than %d paths.\n", IO.int[DPrint.MaxPaths]] ELSE DPrint.NumPaths[watched] _ i; END; ENDCASE; IF args # NIL THEN args _ args.next; ENDLOOP; IF NOT anyOptions THEN BEGIN IO.PutF[StdOut, "Bus threshold is %.1f pf\n", IO.real[Delay.BusThreshold]]; IO.PutF[StdOut, "Delay limit is %d stages\n", IO.int[Delay.DelayLimit]]; IO.PutF[StdOut, "Print units are %.1f microns per lambda\n", IO.real[Printout.Units]]; IO.PutF[StdOut, "Recording %d memory paths, %d arbitrary paths", IO.int[DPrint.NumPaths[memory]], IO.int[DPrint.NumPaths[any]]]; IO.PutF[StdOut, ", %d watched paths\n", IO.int[DPrint.NumPaths[watched]]]; IF Delay.PrintAll THEN IO.PutRope[StdOut, "Printing all new delays to nodes\n"] ELSE IF Delay.Print THEN IO.PutRope[StdOut, "Printing new delays to named nodes\n"] ELSE IO.PutRope[StdOut, "Not printing new delays\n"]; IF Mark.SeeDynamic THEN IO.PutRope[StdOut, "Printing out dynamic node settings\n"] ELSE IO.PutRope[StdOut, "Not printing dynamic nodes\n"]; IF Mark.SeeAllSettings THEN IO.PutRope[StdOut, "Printing all node settings\n"] ELSE IF Mark.SeeSettings THEN IO.PutRope[StdOut, "Printing named node settings\n"] ELSE IO.PutRope[StdOut, "Not printing node settings\n"]; IF DPrint.PrintEdgeSpeeds THEN IO.PutRope[StdOut, "Printing edge speeds\n"] ELSE IO.PutRope[StdOut, "Not printing edge speeds\n"]; END; END; ClearCmd: Globals.CmdProc = { ClearProc: HashTable.EachPairAction = BEGIN p: Globals.Pointer; f: Globals.Fet; node: Globals.Node _ NARROW[value]; IF node.inPath THEN BEGIN IO.PutF[StdOut, "Crystal bug: inPath left set at %s.\n", IO.rope[Printout.NodeRope[node, globalVars]]]; node.inPath _ FALSE; END; node.always0 _ FALSE; node.always1 _ FALSE; node.precharged _ FALSE; node.ratioError _ FALSE; node.watched _ FALSE; node.hiTime _ -1; node.loTime _ -1; p _ node.firstPointer; WHILE p # NIL DO f _ p.fet; p _ p.next; IF f.gate # node THEN LOOP; f.flowFromSource _ FALSE; f.flowFromDrain _ FALSE; f.forcedOn _ FALSE; f.forcedOff _ FALSE; ENDLOOP; END; [] _ HashTable.Pairs[globalVars.nodeTable, ClearProc]; IF globalVars.GroundNode # NIL THEN BEGIN globalVars.GroundNode.input _ TRUE; globalVars.GroundNode.always0 _ TRUE; END; IF globalVars.VddNode # NIL THEN BEGIN globalVars.VddNode.input _ TRUE; globalVars.VddNode.always1 _ TRUE; END; DPrint.Clear[]; }; IntrpCmds: PROC[stream: IO.STREAM, interactive: BOOLEAN, globalVars: Globals.GlobalVars] = BEGIN line: Rope.ROPE; args: Arg; index: INT; class: CmdClass; {ENABLE IO.Error => CONTINUE; WHILE notQuit DO IF ~interactive AND IO.EndOf[stream] THEN RETURN; IF Stop^ THEN BEGIN IF interactive THEN IO.PutRope [StdOut, "[Interrupted]\n"] ELSE RETURN; END; IF interactive THEN line _ TerminalIO.RequestRope[": "] ELSE line _ IO.GetLineRope[stream]; args _ Parse.Args[line]; IF interactive THEN Stop^ _ FALSE; IF args = NIL THEN LOOP; IF NOT interactive THEN IO.PutF[StdOut, ": %s\n", IO.rope[line]]; TRUSTED {index _ Parse.Lookup[args.rope, DESCRIPTOR[CmdTable]]}; IF index = -1 THEN IO.PutF[StdOut, "Ambiguous command: %s\n", IO.rope[args.rope]] ELSE IF index = -2 THEN IO.PutF[StdOut, "Unknown command: %s\n", IO.rope[args.rope]] ELSE BEGIN class _ classes[index]; IF class < curClass THEN BEGIN IO.PutF[StdOut, "The %s command shouldn't be", IO.rope[args.rope]]; IO.PutF[StdOut, " invoked after a %s command.\n", IO.rope[classNames[curClass]]]; END; SELECT class FROM anytime => NULL; model, circuit => IF class > curClass THEN curClass _ class; dynamic, check, setup, delay => BEGIN IF NOT marked THEN BEGIN IO.PutRope[StdOut, "Marking transistor flow...\n"]; Flow.Mark[NIL, globalVars]; IO.PutRope[StdOut, "Setting Vdd to 1...\n"]; Mark.SetNodeValue[node: globalVars.VddNode, value: 1, propAnyway: TRUE, globalVars: globalVars]; IO.PutRope[StdOut, "Setting GND to 0...\n"]; Mark.SetNodeValue[node: globalVars.GroundNode, value: 0, propAnyway: TRUE, globalVars: globalVars]; marked _ TRUE; END; IF curClass < class THEN curClass _ class; END; clear => BEGIN marked _ FALSE; curClass _ afterClear; END; ENDCASE; (CmdProcs[index])[args.next, globalVars]; END; ENDLOOP; }; END; MarkDynamicCmd: Globals.CmdProc = BEGIN ok: BOOLEAN; name: Rope.ROPE; 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; [ok, ivalue] _ Parse.Int[args]; IF ivalue < 0 OR ivalue > 1 OR NOT ok THEN BEGIN IO.PutF[StdOut, "Bad value given for %s: %s. Try 0 or 1.\n", IO.rope[name], IO.rope[args.rope]]; args _ args.next; LOOP; END; Mark.SetNodeValue[Build.NodeFromRope[name, globalVars], ivalue, TRUE, globalVars]; args _ args.next; ENDLOOP; Mark.MarkDynamic[globalVars]; ClearCmd[NIL, globalVars]; marked _ FALSE; END; RunCrystal: PUBLIC PROC [globalVars: Globals.GlobalVars] ~ { IntrpCmds[NIL, TRUE, globalVars]; notQuit _ TRUE; }; END. °FILE: Main.mesa Last edited by Ousterhout, April 16, 1985 11:36:38 am PST Christian LeCocq December 19, 1986 2:15:37 pm PST Atom, CommandTool, Icons, Menus, Process, ProcessProps, TypeScript, ViewerIO, ViewerOps, ViewerTools; Atom, CommandTool, Icons, Menus, Process, ProcessProps, TypeScript, ViewerIO, ViewerOps, ViewerTools quitButton, stopButton, resetButton, checkButton, clearButton, critButton, helpButton, statButton: Menus.MenuEntry; The following variables hold information passed between high-level procedures and hash table enumeration procedures. This page defines the Crystal commands. Check.RatioCmd, DPrint.UndumpCmd, The stuff on this page defines the class of each command, so that we can make sure that comands are issued in the right order. Marked is TRUE if flow and power rails have been marked, FALSE means we still have to do it at some point. template forc suppressed cmds Prints out a synopsis of the commands. Reads in more commands from a command file. Calls various routines to print out statistics about what Crystal has done. This command procedure reads "name value" argument pairs and sets internal options. Some of the options require no values. If no names or values are given, then the current option settings are printed. bus: set bus threshold. graphics: set graphical output format. limit: set maximum number of delay calculations before despair. mempaths: set count of how many memory paths to record. noprintedgespeeds: set boolean not to print out edge speeds in "critical" command. noseedelays: set flag not to print out delays as they are computed. noseedynamic: set flag not to print out dynamic nodes as they are found. noseesettings: set flag not to print out node settings when they are made. paths: set count of how many paths to record. printedgespeeds: set boolean to print out edge speeds. ratiodups: set count of how ratio messages per ratio type. args _args.next; [ok, i] _ Parse.Int[args]; IF NOT ok THEN IO.PutRope[StdOut, "No duplicate ratio limit given.\n"] ELSE Check.ratioLimit _ i; ratiolimit: set count of maximum allowabl ratio error messages. args _ args.next; [ok, i] _ Parse.Int[args]; IF NOT ok THEN IO.PutRope[StdOut, "No ratio error limit given.\n"] ELSE Check.totalRatioLimit _ i; seealldelays: set flag to print out all delays as they are computed. seeallsettings: set flag to print out all node settings as they are made. seedelays: set flag to print out delays for named nodes only. seedynamic: set flag to print out dynamic nodes as they are found. seesettings: see settings of named nodes only. units: set units for printout and read-in. watchpaths: set count of how many watched paths to record. IO.PutF[StdOut, "Ratio limits are %d errors per ratio, %d total\n", IO.int[Check.ratioLimit], IO.int[Check.totalRatioLimit]]; This command procedure reinitializes timing and flag information in all of the nodes and transistors. Any information set by "set", "flow", and "delay" commands is cleared. The procedure also checks to be sure that certain flags, like inPath, haven't accidentally been left set. Hash.Enumerate[table: globalVars.nodeTable, pattern: "*", proc: clearProc, errorStream: StdOut]; It is crucial that Vdd and Ground get left marked as inputs and as fixed in value. Otherwise the marking routines will misbehave a most horrendous manner. This procedure reads command lines from stream, parses them up, looks up the commands in CmdTable, and invokes command routines. This routine returns only upon receiving an end of file or a "quit" command. Interactive specifies whether or not this is an interactive interpreter. If it is TRUE, then prompts are output on StdOut before each command. Make sure that the command is being given in the right order. Also take care of automatic flow and Vdd/Ground marking. Actually execute the command. TypeScript.Destroy[typeScript]; Hash.Enumerate[table: globalVars.nodeTable, pattern: name, proc: mdProc, errorStream: StdOut]; mdProc: Hash.EnumProc = BEGIN node: Node _ NARROW[entry.clientData]; Mark.SetNodeValue[node, ivalue, TRUE]; END; CheckProc: Menus.ClickProc = BEGIN IO.PutRope[StdOut, "check\n"]; Check.CheckCmd[NIL]; IO.PutRope[StdOut, ": "]; END; ClearProc: Menus.ClickProc = BEGIN IO.PutRope[StdOut, "clear\n"]; marked _ FALSE; curClass _ afterClear; ClearCmd[NIL]; IO.PutRope[StdOut, ": "]; END; CritProc: Menus.ClickProc = BEGIN IO.PutRope[StdOut, "crit\n"]; DPrint.CriticalCmd[NIL]; IO.PutRope[StdOut, ": "]; END; DelayProc: Menus.ClickProc = BEGIN IO.PutRope[StdOut, "delay\n"]; Delay.DelayCmd[NIL]; IO.PutRope[StdOut, ": "]; END; HelpProc: Menus.ClickProc = BEGIN IO.PutRope[StdOut, "help\n"]; HelpCmd[NIL]; IO.PutRope[StdOut, ": "]; END; StatProc: Menus.ClickProc = BEGIN IO.PutRope[StdOut, "stat\n"]; Stats2Cmd[NIL]; IO.PutRope[StdOut, ": "]; END; StopProc: Menus.ClickProc = BEGIN Stop^ _ TRUE; END; QuitProc: Menus.ClickProc = BEGIN notQuit _ FALSE; IO.Close[self: inStream,abort: TRUE]; END; ResetProc: Menus.ClickProc = BEGIN TypeScript.Reset[typeScript]; Init[]; IO.PutRope[StdOut, ": "]; END; Init: PROC = BEGIN Menus.ChangeNumberOfLines [menu: typeScript.menu, newLines: 2]; statButton _ Menus.CreateEntry[name: "stat", proc: StatProc, fork: FALSE]; Menus.InsertMenuEntry[menu: typeScript.menu, entry: statButton, line: 1]; helpButton _ Menus.CreateEntry[name: "help", proc: HelpProc, fork: FALSE]; Menus.InsertMenuEntry[menu: typeScript.menu, entry: helpButton, line: 1]; delayButton _ Menus.CreateEntry[name: "delay", proc: DelayProc, fork: FALSE]; Menus.InsertMenuEntry[menu: typeScript.menu, entry: delayButton, line: 1]; critButton _ Menus.CreateEntry[name: "crit", proc: CritProc, fork: FALSE]; Menus.InsertMenuEntry[menu: typeScript.menu, entry: critButton, line: 1]; clearButton _ Menus.CreateEntry[name: "clear", proc: ClearProc, fork: FALSE]; Menus.InsertMenuEntry[menu: typeScript.menu, entry: clearButton, line: 1]; checkButton _ Menus.CreateEntry[name: "check", proc: CheckProc, fork: FALSE]; Menus.InsertMenuEntry[menu: typeScript.menu, entry: checkButton, line: 1]; resetButton _ Menus.CreateEntry[name: "Reset", proc: ResetProc, fork: FALSE]; Menus.SetGuarded[resetButton, TRUE]; Menus.InsertMenuEntry[menu: typeScript.menu, entry: resetButton]; stopButton _ Menus.CreateEntry[name: "STOP!", proc: StopProc, fork: FALSE]; Menus.InsertMenuEntry[menu: typeScript.menu, entry: stopButton]; quitButton _ Menus.CreateEntry[name: "Quit", proc: QuitProc, fork: FALSE]; Menus.SetGuarded[quitButton, TRUE]; Menus.InsertMenuEntry[menu: typeScript.menu, entry: quitButton]; ViewerOps.PaintViewer[viewer: typeScript, hint: all]; ViewerTools.SetSelection[viewer: typeScript]; NodeTable _ Hash.NewTable[]; VddNode _ Build.BuildNode["Vdd"]; GroundNode _ Build.BuildNode["GND"]; END; Initialization and startup: TopLevelProc: PROC[stream: IO.STREAM, interactive: BOOLEAN, wd: Rope.ROPE] = BEGIN inner: PROC[] = BEGIN IntrpCmds[stream, interactive]; END; ProcessProps.AddPropList[Atom.PutPropOnList[NIL, $WorkingDirectory, wd], inner]; END; typeScript _ TypeScript.Create[info: [name: "Crystal2", iconic: TRUE, icon: Icons.NewIconFromFile["Crystal.icons", 2 !ANY => BEGIN IO.PutRope[StdOut, "Couldn't find Crystal.icons.\n I hope you're satisfied with the normal boring icon.\n"]; CONTINUE; END]]]; Init[]; [in: inStream, out: StdOut] _ ViewerIO.CreateViewerStreams[name: "Crystal2",viewer: typeScript]; IO.PutRope[StdOut, "Crystal2, version 0.1\n"]; TRUSTED {crystalProcess _ FORK TopLevelProc[inStream,TRUE,CommandTool.CurrentWorkingDirectory[]]}; TRUSTED {Process.Detach[crystalProcess]}; Κ’˜IcodešΟkœ ™Kšœ6™9Kšœ.™1K˜š ˜ K™K˜K˜K™ K˜K˜K˜Kšœ˜K˜K˜ K™Kšœ˜K˜K™K˜K˜K˜ K™K™ K˜K˜ K™ K™ K™ K™ K˜—KšΠbnœœ˜š˜K™K˜K˜K™ K˜K˜K˜Kšœ˜K˜ K™Kšœ˜K˜K™K˜K˜K˜ K™K™ K˜ K™ K™ K™ K™ —š˜K˜ —K˜Kš˜Kšœ ˜ K˜Kš Οnœœœœœ˜,KšŸœœœœ˜KšŸœœœœœœœ˜0Kšœ œœΟc˜7Kšœ ™ K™ K™ K™ K™ K™ K™ K™K˜Kšœt™tK˜Kšœœ˜ K˜K˜Kšœ'™'K˜šŸœœœœ˜%K˜K˜K˜K˜ K˜K˜K˜K˜K˜ K˜.K˜K˜K˜(K˜K˜(K˜K˜ K˜)K˜K˜K˜K˜)K˜(K˜ K˜ K˜K˜K˜ K˜ K˜K˜K˜K˜—šŸœœœ˜+K˜K˜K˜ K˜ K˜K˜ K˜K˜K˜K˜ K˜K˜K˜K˜K˜ K˜K˜K˜K˜K˜K˜K˜K™K˜ K˜K˜ K˜ K˜ K˜ K˜K™K˜ K˜ K˜K˜—K˜Kšœ~™~K˜Kšœ œN˜\K˜K˜šœœ˜Kšœ œ*™8Kšœ,™1—K˜šœ œ œœ˜)K˜K˜K˜K˜ K˜K˜K˜K˜K˜K˜K˜—K˜šœ œœ ˜$K˜Kšœ  ˜Kšœ  ˜Kšœ  ˜Kšœ  ˜Kšœ  ˜Kšœ   ˜Kšœ  ˜Kšœ  ˜Kšœ  ˜Kšœ  ˜Kšœ  ˜Kšœ  ˜Kšœ  ˜Kšœ   ˜Kšœ   ˜Kšœ   ˜Kšœ  ˜Kšœ   ˜Kšœ   ˜Kšœ   ˜Kšœ  ˜Kšœ  ˜Kšœ   ˜Kšœ   ˜Kšœ  ˜Kšœ   ˜Kšœ  ˜Kšœ   ˜Kšœ   ˜Kšœ  ˜K˜K˜—K˜šŸœ˜J™K˜š˜Kšœ:˜Kšœ˜Kšœ˜—K˜Kšœ&™&K˜˜Kš˜K˜Kšœœœ/˜DKšœœA˜HKšœ˜—K˜Kšœ?™?K˜˜Kš˜K˜K˜Kšœœœ1˜BKšœ˜Kšœ˜—K˜Kšœ7™7K˜˜Kš˜K˜K˜Kšœœœ1˜BKšœœœ4œ˜oKšœ˜!Kšœ˜—K˜KšœS™SK˜˜Kš˜Kšœœ˜Kšœ˜—K˜KšœC™CK˜˜Kš˜Kšœœ˜Kšœœ˜Kšœ˜—K˜KšœH™HK˜˜Kšœœ˜—K˜KšœJ™JK˜˜Kš˜Kšœœ˜Kšœœ˜Kšœ˜—K˜Kšœ-™-K˜˜Kš˜K˜K˜Kšœœœ*˜;Kšœœœ4œ˜oKšœ˜Kšœ˜—K˜Kšœ6™6K˜˜Kš˜Kšœœ˜Kšœ˜—K˜Kšœ:™:K˜˜Kš˜K™K™Kšœœœ5™FKšœ™Kšœ˜—K˜Kšœ?™?K˜˜Kš˜K™K™Kšœœœ1™BKšœ™Kšœ˜—K˜KšœE™EK˜˜Kšœœ˜—K˜KšœJ™JK˜˜Kšœœ˜—K˜Kšœ=™=K˜˜Kš˜Kšœœ˜Kšœœ˜Kšœ˜—K˜KšœB™BK˜˜Kšœœ˜—K˜Kšœ/™/K˜˜Kš˜Kšœœ˜Kšœœ˜Kšœ˜—K˜Kšœ+™+K˜˜Kš˜K˜K˜Kšœœœ+˜<š˜Kš˜K˜K˜Kšœ˜—Kšœ˜—K˜Kšœ:™:K˜˜Kš˜K˜K˜Kšœœœ2˜CKšœœœ4œ˜oKšœ˜"Kšœ˜——˜Kšœ˜——K˜Kšœœœ˜$Kšœ˜K˜šœœ ˜Kš˜Kšœ,œ˜KKšœ,œ˜HKšœ;œ˜VKšœ?œœ˜€Kšœ&œ ˜JKšœBœœ™}šœ˜Kšœ6˜8—šœœ ˜Kšœ8˜:—Kšœœ.˜5šœ˜Kšœ8˜:—Kšœœ1˜8šœ˜Kšœ0˜2—šœœ˜Kšœ2˜4—Kšœœ1˜8šœ˜Kšœ*˜,—Kšœœ/˜6Kšœ˜—Kšœ˜—K˜K˜šŸœ˜Kšœ˜™˜šŸ œ˜%Kš˜K˜K˜Kšœœ˜#K˜šœ ˜Kš˜Kšœ7œ,˜gKšœœ˜Kšœ˜—Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜K˜K˜K˜K˜šœœ˜K˜ K˜ Kšœœœ˜Kšœœ˜Kšœœ˜Kšœ œ˜Kšœœ˜Kšœ˜—Kšœ˜K˜—Kšœ`™`Kšœ6˜6Kšœ›™›K˜šœœœ˜$Kš˜Kšœœ˜#Kšœ œ˜%Kšœ˜—šœœ˜ Kš˜Kšœœ˜ Kšœœ˜"Kšœ˜—K˜Kšœ˜—K˜K˜š Ÿ œœ œœœ#˜ZKšœ’œ8™ήK˜Kš˜Kšœ œ˜K˜ Kšœœ˜ K˜K˜Kšœœœ œ˜šœ ˜Kš œœœœœ˜1šœ˜ Kš˜Kšœ œœ$˜:Kšœœ˜ Kšœ˜—Kšœ œ$˜7Kšœœ˜#K˜Kšœ œ œ˜"Kšœœœœ˜Kš œœ œœœ ˜AKšœ" œ ˜@šœ ˜Kšœ)œ˜>—šœœ ˜Kšœ'œ˜<—š˜Kšœ˜K˜Kšœ=™=Kšœ8™8K˜K˜šœ˜Kš˜Kšœ-œ˜CKšœ0œ˜QKšœ˜—Kšœ˜˜Kšœ œ˜K˜Kšœœœ˜