DIRECTORY Basics, CD, CDBasics, CDCellsInteractions, CDDirectory, CDIO, CDOps, CDViewer, CedarProcess, CMosB, Commander, CommandTool, Core, CoreClasses, CoreGeometry, CoreFlat, CoreOps, CoreProperties, DAUser, DraculaOps, IO, Mint, Nodeness, PW, PWCore, PWCoreLichen, Real, RealFns, RefTab, Rope, RosemaryUser, RoutingCheck, Sinix, SinixOps, Sisyph, Static, SymTab, TerminalIO, ViewerClasses, ViewerOps, WriteCapa; CheckDesign: CEDAR PROGRAM IMPORTS Basics, CD, CDBasics, CDCellsInteractions, CDDirectory, CDIO, CDOps, CDViewer, CedarProcess, CMosB, Commander, CommandTool, CoreOps, CoreProperties, DAUser, DraculaOps, IO, Mint, Nodeness, PW, PWCore, PWCoreLichen, Real, RealFns, RefTab, Rope, RosemaryUser, RoutingCheck, SinixOps, Sisyph, Static, SymTab, TerminalIO, ViewerOps, WriteCapa = BEGIN Handle: TYPE = REF HandleRec; HandleRec: TYPE = RECORD [ designNm: IO.ROPE _ NIL, schNm: IO.ROPE _ NIL, schDesign: CD.Design _ NIL, layDesign: CD.Design _ NIL, cells: Cells _ NIL, fromFile: BOOL _ FALSE, lichen: BOOL _ TRUE, static: BOOL _ TRUE, mint: BOOL _ TRUE, rose: BOOL _ TRUE, conn: BOOL _ TRUE, drc: BOOL _ TRUE ]; Cells: TYPE = LIST OF Core.CellType; log: IO.STREAM _ TerminalIO.TOS[]; layMode: Sinix.Mode = PWCore.extractMode; schMode: Sinix.Mode = Sisyph.mode; mintSchNodeCapa: REAL _ 0.5; doc: IO.ROPE _ "CheckDesign designName -f read cell from file (designName used as deviceName) -l skip lichen check -s skip static check -m skip mint check -r skip rose simulation check -c skip connectivity check -d skip drc check "; CheckDesignCmdProc: Commander.CommandProc = { Log: PROC[r: IO.ROPE] = {cmd.out.PutRope[r]; log.PutRope[r]}; LogDone: PROC = {Log[IO.PutFR["done %g\n", IO.time[]]]}; h: Handle _ InitHandle[cmd]; initialPriority: CedarProcess.Priority _ CedarProcess.GetPriority[]; designPrintNm: IO.ROPE; cellPrintNm: IO.ROPE; IF h=NIL THEN {cmd.out.PutRope[doc]; RETURN[$Failure]}; designPrintNm _ IF h.designNm=NIL THEN "(from file)" ELSE h.designNm; cellPrintNm _ IF h.schNm=NIL THEN "--ALL--" ELSE h.schNm; CedarProcess.SetPriority[background]; Log[IO.PutFR["%l\n", IO.rope["f"]]]; Log[IO.PutFR["Check Design: %g\n", IO.rope[designPrintNm]]]; Log[IO.PutFR[" Cell: %g\n", IO.rope[cellPrintNm]]]; Log[IO.PutFR[" start %g\n", IO.time[]]]; IF ~h.fromFile THEN {Log[" Extract Src ... "]; ExtractSrc [h]; LogDone[]}; IF h.fromFile THEN {Log[" Read Src ... "]; ReadSrc [h]; LogDone[]}; IF TRUE THEN {Log[" Gen Lay ... "]; GenLayout [h]; LogDone[]}; IF TRUE THEN {Log[" Extract Lay ... "]; ExtractLay [h]; LogDone[]}; IF h.lichen THEN {Log[" Lichen Ck ... "]; LichenCk [h]; LogDone[]}; IF h.static THEN {Log[" Static Ck ... "]; StaticCk [h]; LogDone[]}; IF h.mint THEN {Log[" Mint Ck ... "]; MintCk [h]; LogDone[]}; IF h.rose THEN {Log[" Rose Ck ... "]; SimCk [h]; LogDone[]}; IF h.conn THEN {Log[" Conn Ck ... "]; ConnectCk [h]; LogDone[]}; IF h.drc THEN {Log[" DRC Ck ... "]; DRCDesign [h]; LogDone[]}; CedarProcess.SetPriority[initialPriority]}; InitHandle: PROC[cmd: Commander.Handle] RETURNS[h: Handle] = { list: LIST OF IO.ROPE _ CommandTool.ParseToList[cmd].list; schNm: IO.ROPE _ NIL; designNm: IO.ROPE _ NIL; h _ NEW[HandleRec _ []]; FOR list _ list, list.rest WHILE list#NIL DO SELECT list.first.Fetch[] FROM '- => SELECT list.first.Fetch[1] FROM 'f, 'F => {h.lichen _ FALSE; h.rose _ FALSE; h.fromFile _ TRUE}; 'l, 'L => h.lichen _ FALSE; 's, 'S => h.static _ FALSE; 'm,'M => h.mint _ FALSE; 'r, 'R => h.rose _ FALSE; 'c, 'C => h.conn _ FALSE; 'd, 'D => h.drc _ FALSE; ENDCASE => {cmd.out.PutRope["\nUnknown switch\n"]; RETURN[NIL]}; ENDCASE => { IF h.designNm=NIL THEN h.designNm _ list.first ELSE IF schNm=NIL THEN schNm _ list.first ELSE {cmd.out.PutRope["\nMore than 2 arguments\n"]; RETURN[NIL]}}; ENDLOOP; IF h.fromFile THEN {h.schNm _ h.designNm; h.designNm _ NIL; RETURN[h]}; h.schDesign _ GetDesign[h.designNm]; IF h.schDesign=NIL THEN {cmd.out.PutF["\nCan't find design %g\n", IO.rope[h.designNm]]; RETURN[NIL]}; CDCellsInteractions.PopToTopLevel[h.schDesign]; IF schNm#NIL THEN { h.schNm _ schNm; IF CDDirectory.Fetch[h.schDesign, h.schNm]#NIL THEN RETURN[h]; h.schNm _ schNm.Cat[".icon"]; IF CDDirectory.Fetch[h.schDesign, h.schNm]#NIL THEN RETURN[h]; h.schNm _ schNm.Cat[".sch"]; IF CDDirectory.Fetch[h.schDesign, h.schNm]#NIL THEN RETURN[h]; cmd.out.PutF["\nCan't find cell %g\n", IO.rope[schNm]]; RETURN[NIL]}}; ExtractSrc: PROC[h: Handle] = { cx: Sisyph.Context _ Sisyph.Create[h.schDesign]; IF h.schNm#NIL THEN h.cells _ LIST[Sisyph.ES[h.schNm, cx]] ELSE { list: Cells; SelectObjectsForExtraction[h.schDesign]; list _ SinixOps.SelectedCellTypes[h.schDesign, schMode]; IF list = NIL THEN ERROR; FOR list _ list, list.rest WHILE list#NIL DO h.cells _ CONS[list.first, h.cells] ENDLOOP} }; ReadSrc: PROC[h: Handle] = {ct: Core.CellType _ PWCore.Retrieve[h.schNm]; h.cells _ LIST[ct]}; GenLayout: PROC[h: Handle] = { FOR list: Cells _ h.cells, list.rest WHILE list#NIL DO IF HasLayout[list.first] THEN []_PWCore.Layout[list.first] ENDLOOP}; ExtractLay: PROC[h: Handle] = { FOR list: Cells _ h.cells, list.rest WHILE list #NIL DO ect: Core.CellType; IF ~HasLayout[list.first] THEN LOOP; log.PutF["\nLayout Extraction of %g.\n",IO.rope[CoreOps.GetCellTypeName[list.first]]]; ect _ PWCore.LayoutInfo[list.first].extractedCT ENDLOOP}; SimCk: PROC[h: Handle] = { FOR list: Cells _ h.cells, list.rest WHILE list #NIL DO IF CoreProperties.GetCellTypeProp[list.first, $Tests]#NIL THEN { tester: RosemaryUser.Tester _ DAUser.RunRosemary[list.first, h.schDesign]; log.PutF["\nSimulation Check of %g.\n",IO.rope[CoreOps.GetCellTypeName[list.first]]]; RosemaryUser.StartTest[tester]} ENDLOOP}; MintCk: PROC[h: Handle] = { FOR list: Cells _ h.cells, list.rest WHILE list #NIL DO MintCheck[list.first] ENDLOOP}; MintCheck: PROC[cell: Core.CellType, useLayoutIfPresent: BOOL _ TRUE] = { GetNode: PROC[name: IO.ROPE] RETURNS[node: Mint.Node _ NIL] = { IF CoreOps.FindWire[ct.public, name]#NIL THEN node _ Mint.NodeFromRope[Rope.Cat["public.", name], circuit]}; GenClkNodeList: PROC[names: LIST OF IO.ROPE] RETURNS[list: Mint.NodeList] = { IF names=NIL THEN RETURN[NIL] ELSE { hiNm: IO.ROPE _ names.first; loNm: IO.ROPE _ Rope.Cat["n", names.first]; node: Mint.Node; list _ GenClkNodeList[names.rest]; IF (node _ GetNode[hiNm])#NIL THEN { Mint.SetNode[node, TRUE]; log.PutF["Mint Clock: %g\n", IO.rope[hiNm]]; list _ CONS[node, list]}; IF (node _ GetNode[loNm])#NIL THEN { Mint.SetNode[node, FALSE]; log.PutF["Mint Clock: %g\n", IO.rope[loNm]]; list _ CONS[node, list]} }}; InitCT: PROC RETURNS[Core.CellType] = { ct: Core.CellType _ IF layout THEN PWCore.LayoutInfo[cell].extractedCT ELSE cell; IF layout THEN { WriteCapa.WriteWireCapa[ct, $cmosB]}; RETURN[ct]}; name: IO.ROPE _ CoreOps.GetCellTypeName[cell]; layout: BOOL _ useLayoutIfPresent AND HasLayout[cell]; ct: Core.CellType _ InitCT[]; defaultCapa: REAL _ IF layout THEN 0.0 ELSE mintSchNodeCapa; circuit: Mint.Circuit _ Mint.CreateCircuit[ct, layout, defaultCapa]; clockNames: LIST OF IO.ROPE _ LIST["Clock","Clk","Ck","CK","PhA","PhB","phA","phB"]; clocks: Mint.NodeList _ GenClkNodeList[clockNames]; vddNode: Mint.Node _ GetNode["Vdd"]; gndNode: Mint.Node _ GetNode["Gnd"]; slowNodes: Mint.PathArray; lastTime: Mint.ps; veryLastTime: Mint.ps; log.PutF["\nMint Check of %g %g.\n", IO.rope[CoreOps.GetCellTypeName[cell]], IO.rope[IF layout THEN "layout" ELSE "source"]]; IF vddNode=NIL THEN {log.PutF["*** Cell: %g does not have a Vdd connection.\n", IO.rope[name]]; RETURN}; IF gndNode=NIL THEN {log.PutF["*** Cell: %g does not have a Gnd connection.\n", IO.rope[name]]; RETURN}; Mint.SetNode[vddNode, TRUE]; Mint.SetNode[gndNode, FALSE]; Mint.InputData[circuit, LIST[gndNode, vddNode], layout, defaultCapa]; Mint.CheckLibrary[circuit]; Mint.OutputResults[circuit]; lastTime _ Mint.RecordPaths[circuit, clocks]; log.PutF["Longest time: %4.1fns\n", IO.real[lastTime/1000.0]]; [veryLastTime, slowNodes] _ Mint.FindSlowestPaths[circuit, 8, TRUE]; Mint.PrintPathArray[slowNodes, circuit]; Mint.KillCircuit[circuit]}; LichenCk: PROC[h: Handle] = { PWCoreLichen.SetAutomorphismHack[TRUE]; FOR list: Cells _ h.cells, list.rest WHILE list #NIL DO IF ~HasLayout[list.first] THEN LOOP; log.PutF["\nLichen Check of %g.\n", IO.rope[CoreOps.GetCellTypeName[list.first]] ]; [] _ PWCoreLichen.CompareForTheRestOfUs[list.first, h.schDesign, 1.0] ENDLOOP}; StaticCk: PROC[h: Handle] = { FOR list: Cells _ h.cells, list.rest WHILE list #NIL DO StaticCheck[list.first] ENDLOOP}; StaticCheck: PROC[ref: Core.CellType, useLayoutIfPresent: BOOL _ TRUE] = { layout: BOOL _ useLayoutIfPresent AND HasLayout[ref]; cell: Core.CellType _ IF layout THEN PWCore.LayoutInfo[ref].extractedCT ELSE ref; log.PutF["\nStatic Check of %g %g.\n", IO.rope[CoreOps.GetCellTypeName[ref]], IO.rope[IF layout THEN "layout" ELSE "source"]]; Static.CountLeafConnections[cell, Static.CheckCount]}; ConnectCk: PROC[h: Handle] = { FOR list: Cells _ h.cells, list.rest WHILE list #NIL DO ConnectCheck[list.first] ENDLOOP}; ConnectCheck: PROC[source: Core.CellType] = { IF HasLayout[source] THEN { name: IO.ROPE _ CoreOps.GetCellTypeName[source]; obj: CD.Object _ PWCore.LayoutInfo[source].layout; ect: Core.CellType _ PWCore.LayoutInfo[source].extractedCT; log.PutF["\nCheck Routing Objects of %g.\n",IO.rope[name]]; RoutingCheck.CheckObject[obj]; log.PutF["\nCheck Connectivity of %g.\n",IO.rope[name]]; [] _ Nodeness.GetNodeness[layMode.decoration, layMode.touchProc, ect] }}; enableDRC: BOOL _ TRUE; DRCDesign: PROC[h: Handle] = { rules: IO.ROPE _ "VTI"; inst: CD.Instance; reportMsg: IO.ROPE _ NIL; hasErrors: BOOL _ TRUE; IF ~enableDRC THEN RETURN; [h.layDesign, inst] _ MakeDRCTestObject[h]; IF h.layDesign=NIL THEN {log.PutRope["No layout to DRC\n"]; RETURN}; [reportMsg, hasErrors] _ DraculaOps.DRCInstance[inst, h.layDesign, rules]; IF hasErrors THEN log.PutF["*** DRC Errors\n %g\n", IO.rope[reportMsg]] ELSE log.PutF["No DRC Errors\n %g\n", IO.rope[reportMsg]]}; DRCDesignFile: PROC[file: IO.ROPE] = { design: CD.Design _ GetDesign[file]; inst: CD.Instance _ CDOps.InstList[design].first; rules: IO.ROPE _ "VTI"; reportMsg: IO.ROPE _ NIL; hasErrors: BOOL _ TRUE; [reportMsg, hasErrors] _ DraculaOps.DRCInstance[inst, design, rules]; IF hasErrors THEN log.PutF["*** DRC Errors\n %g\n", IO.rope[reportMsg]] ELSE log.PutF["No DRC Errors\n %g\n", IO.rope[reportMsg]]}; MakeDRCTestObject: PROC[h: Handle] RETURNS[design: CD.Design, inst: CD.Instance] = { TwoObjects: TYPE = RECORD[o0, o1: CD.Object, b: BOOL]; viewer: ViewerClasses.Viewer; area: REAL _ 0.0; tech: CD.Technology _ CMosB.cmosB; sep: INT _ tech.lambda*16; maxX: INT _ 0; pos: CD.Position _ [0, 0]; height: INT; insts: CD.InstanceList; object: CD.Object; objs: LIST OF CD.Object; design _ CDOps.CreateDesign[tech]; CDOps.SetMutability[design]; viewer _ CDViewer.CreateViewer[design, FALSE]; FOR list: Cells _ h.cells, list.rest WHILE list #NIL DO IF ~HasLayout[list.first] THEN LOOP; objs _ CONS[PWCore.LayoutInfo[list.first].layout, objs] ENDLOOP; IF objs=NIL THEN RETURN[NIL, NIL]; DO chngd: BOOL _ FALSE; FOR list: LIST OF CD.Object _ objs, list.rest WHILE list.rest#NIL DO size1: CD.Position _ CD.InterestSize[list.first]; size2: CD.Position _ CD.InterestSize[list.rest.first]; SELECT Basics.CompareInt[ size1.x, size2.x] FROM less => LOOP; greater => [list.first, list.rest.first, chngd] _ TwoObjects[list.rest.first, list.first, TRUE]; ENDCASE => SELECT Basics.CompareInt[ size1.y, size2.y] FROM less => LOOP; greater => [list.first, list.rest.first, chngd]_TwoObjects[list.rest.first, list.first, TRUE]; ENDCASE ENDLOOP; IF ~chngd THEN EXIT ENDLOOP; FOR list: LIST OF CD.Object _ objs, list.rest WHILE list#NIL DO size1: CD.Position _ CD.InterestSize[list.first]; area _ area + (size1.x+sep) * (size1.y+sep) ENDLOOP; height _ Real.Fix[RealFns.SqRt[area]]; FOR list: LIST OF CD.Object _ objs, list.rest WHILE list#NIL DO size: CD.Position _ CD.InterestSize[list.first]; off: CD.Position _ CDBasics.SubPoints[pos, CDBasics.BaseOfRect[CD.InterestRect[list.first]]]; insts _ CONS[NEW[CD.InstanceRep _ [list.first, [off]]], insts]; pos _ [pos.x, pos.y+size.y+sep]; maxX _ MAX[maxX, size.x]; IF pos.y>height THEN {pos.x _ pos.x + maxX + sep; pos.y _ 0; maxX _ 0}; ENDLOOP; object _ PW.CreateCell[insts, , "DRCCheck"]; IF ~CDDirectory.Include[design, object, "DRCCheck"] THEN ERROR; inst _ CDOps.IncludeObject[design, object]; inst.selected _ TRUE}; MarkMintOneWayTransistors: PROC[cell: Core.CellType] = { Mark: PROC[ct: Core.CellType] = { IF ~RefTab.Fetch[tab, ct].found THEN { WITH ct.data SELECT FROM sct: Core.CellType => {Mark[sct] }; trans: CoreClasses.Transistor => { }; seq: CoreClasses.SequenceCellType => {Mark[seq.base]}; rct: CoreClasses.RecordCellType => { cnt: INT _ 0; FOR in: NAT IN [0..rct.size) DO nm: IO.ROPE _ CoreOps.GetCellTypeName[rct[in].type]; IF nm.Equal["MintOneWay"] THEN { cnt _ cnt+1; CoreProperties.PutCellInstanceProp[rct[in], $MintOneWay, $TRUE]} ELSE Mark[rct[in].type] ENDLOOP; count _ count + cnt; IF cnt > 0 THEN log.PutF["%g has %g Mint OneWay transistors\n", IO.rope[CoreOps.GetCellTypeName[ct]], IO.int[cnt]]}; ENDCASE; []_RefTab.Store[tab, ct, ct]}}; tab: RefTab.Ref _ RefTab.Create[]; count: INT _ 0; log.PutRope["\n"]; Mark[cell]; log.PutF["%g Mint OneWay transistors were found.\n", IO.int[count]]; RefTab.Erase[tab]}; GetDesign: PUBLIC PROC [name: IO.ROPE] RETURNS [design: CD.Design] = { viewer: ViewerClasses.Viewer; design _ CDViewer.FindDesign[name]; IF design#NIL THEN RETURN[design]; IF name.Length[]=0 THEN RETURN[NIL]; design _ CDIO.ReadDesign[name]; CDOps.SetMutability[design]; viewer_CDViewer.CreateViewer[design, FALSE]; ViewerOps.CloseViewer[viewer]}; SelectObjectsForExtraction: PROC[design: CD.Design] = { IsIcon: PROC[nm: IO.ROPE] RETURNS[BOOL] = {RETURN[ (nm.Index[0, ".icon", FALSE]+5) = nm.Length[] ]}; IsSch: PROC[nm: IO.ROPE] RETURNS[BOOL] = {RETURN[ (nm.Index[0, ".sch", FALSE]+4) = nm.Length[] ]}; Root: PROC[nm: IO.ROPE] RETURNS[IO.ROPE] = {RETURN[ nm.Substr[0, nm.Index[0, "."]] ]}; iconReg: SymTab.Ref _ SymTab.Create[]; FOR list: CD.InstanceList _ CDOps.InstList[design], list.rest WHILE list#NIL DO name: IO.ROPE _ CDDirectory.Name[list.first.ob, design]; IF IsIcon[name] THEN []_SymTab.Store[iconReg, Root[name], name] ENDLOOP; FOR list: CD.InstanceList _ CDOps.InstList[design], list.rest WHILE list#NIL DO name: IO.ROPE _ CDDirectory.Name[list.first.ob, design]; list.first.selected _ IsIcon[name] OR IsSch[name] AND ~SymTab.Fetch[iconReg, Root[name]].found; IF list.first.selected THEN log.PutF["Selecting: %g\n", IO.rope[name]] ENDLOOP}; HasLayout: PROC[cell: Core.CellType] RETURNS[BOOL] = {RETURN[PWCore.GetLayoutAtom[cell]#NIL]}; Commander.Register["CheckDesign", CheckDesignCmdProc] END. ΦCheckDesign.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Don Curry September 8, 1988 8:12:45 pm PDT Types CheckDesign Command Proc Individual Operations MarkMintOneWayTransistors[ct]; this doen't work The transistor celltype (and therefore the name) gets shared Utilities All icons and all schematics (which don't have icons with the same name) SelectObjectsForExtraction: PROC[design: CD.Design, marked: RefTab.Ref, key: IO.ROPE] = { FOR list: CD.InstanceList _ CDOps.InstList[design], list.rest WHILE list#NIL DO name: IO.ROPE _ CDDirectory.Name[list.first.ob, design]; list.first.selected _ name.Find[key, 0, FALSE]#-1 AND name.Find[key, 0, FALSE] + key.Length[] = name.Length ENDLOOP}; Runtime Κ˜™Jšœ Οmœ1™Jš ‘ %‘  ˜7Jš‘  ‘ 7˜JJš‘  ‘ 5˜GJš‘ ‘ ‘ 6˜DJš‘ ‘ ‘ 7˜EJš‘  ‘ 5˜EJš‘  ‘ 4˜EJš‘  ‘ 4˜CJš‘  ‘ 3˜BJš‘  ‘ 6˜EJš‘  ‘ 6˜EJšœ+˜+——™šŸ œžœžœ˜>Jš œžœžœžœžœ%˜Jšœ˜Jšžœ)žœžœžœ˜>Jšœ˜Jšžœ)žœžœžœ˜>Jšœ'žœžœžœ˜F——J˜—šŸ œžœ˜Jšœ0˜0šžœ ž˜Jšžœ žœžœ˜+šžœ˜Jšœ ˜ Jšœ(˜(Jšœ8˜8Jšžœžœžœžœ˜Jš žœžœžœžœ žœžœ˜\——J˜—šŸœžœ ˜Jšœ9žœ˜CJ˜—šŸ œžœ˜šžœ"žœžœž˜6Jšžœžœžœ˜D—J˜—šŸ œžœ˜šžœ"žœžœž˜7Jšœ˜Jšžœžœžœ˜$Jšœ  œžœ,˜VJšœ0žœ˜9—J˜—šŸœžœ˜šžœ"žœžœž˜7šžœ4žœžœ˜@JšœJ˜JJšœ   œžœ,˜UJšœ žœ˜)——J˜—šŸœžœ˜šžœ"žœžœž˜7Jšœžœ˜—J˜—J˜šŸ œžœ*žœžœ˜Iš Ÿœžœžœžœžœžœ˜?šžœ#žœž˜-Jšœ>˜>——šŸœžœžœžœžœžœžœ˜Mš žœžœžœžœžœžœ˜$Jšœžœžœ˜Jšœžœžœ˜+Jšœ˜Jšœ"˜"šžœžœžœ˜$Jšœžœ˜Jšœžœžœ˜F—šžœžœžœ˜$Jšœžœ˜Jšœžœžœ˜I———šŸœžœžœ˜'Jšœžœžœ%žœ˜Qšžœžœ˜šœ/™/Jšœ<™<—Jšœ%˜%—Jšžœ˜ —Jšœ žœžœ#˜3Jšœ žœžœ˜;Jšœ!˜!Jš œžœžœžœžœ˜@JšœG˜GJš œ žœžœžœžœžœ2˜UJšœ5˜5Jšœ'˜'Jšœ'˜'Jšœ˜Jšœ˜Jšœ˜šœ%˜%Jšžœ%˜'Jšžœžœžœ žœ ˜0—šžœ žœž˜Jšœ<žœžœ˜T—šžœ žœž˜Jšœ<žœžœ˜T—Jšœžœ˜Jšœžœ˜Jšœžœ)˜EJšœ˜Jšœ˜Jšœ-˜-Jšœ$žœ˜>Jšœ>žœ˜DJšœ(˜(Jšœ˜J˜—šŸœžœ˜Jšœ!žœ˜'šžœ"žœžœž˜7Jšžœžœžœ˜$Jšœ%žœ-˜TJšœFžœ˜O—J˜—šŸœžœ˜šžœ"žœžœž˜7Jšœžœ˜!J˜——šŸ œžœ)žœžœ˜JJšœžœžœ˜5šœžœ˜ Jšžœ#˜'Jšžœ˜ —šœ'˜'Jšžœ$˜&Jšžœžœžœ žœ ˜0—šœ6˜6J˜——šŸ œžœ˜šžœ"žœžœž˜7JšŸ œ žœ˜"—J˜—šŸ œžœ˜-šžœžœ˜Jšœžœžœ%˜2Jšœžœ-˜4Jšœ;˜;Jšœ,žœ ˜;Jšœ˜Jšœ)žœ ˜8JšœI˜I—J˜—Jšœ žœžœ˜J˜šŸ œžœ˜Jšœ žœžœ ˜Jšœžœ ˜Jšœ žœžœžœ˜Jšœ žœžœ˜Jšžœ žœžœ˜Jšœ,˜,Jšžœ žœžœ%žœ˜DJšœJ˜Jšžœ ˜ Jšžœ$žœ˜;Jšžœ#žœ˜