DIRECTORY CD USING [CreateDrawRef, DrawRectProc, DrawRef, Error, FetchObjectClass, Instance, lambda, Layer, Number, ObjectClass, Object, Orientation, Position, Rect, Technology], CDBasics USING [Extend, NonEmpty, universe], CDObjectProcs USING [RegisterFurther, StoreFurther], CDProperties USING [PutPropOnTechnology], CornerStitching USING [Area, ChangeRect, EastEdge, ENorthNeighbour, EnumerateArea, InlineChangeTile, NEastNeighbour, NewTesselation, NorthEdge, PerTileProc, Region, SouthEdge, SWestNeighbour, Tesselation, TilePtr, Value, WestEdge, WSouthNeighbour], SX, SXAccessInternal, SXAtoms USING [coreOut, fini, init, rosePrint, spinifex, thymePrint], SXOutput USING [LinkageHousekeeper, LinkagePrintProc], SXTechnology; SXTechnologyImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDObjectProcs, CDProperties, CornerStitching, SX, SXAccessInternal, SXAtoms EXPORTS SXTechnology SHARES CornerStitching = BEGIN polPtr: REF INT _ NEW[INT]; difPtr: REF INT _ NEW[INT]; chanPtr: REF INT _ NEW[INT]; Post: TYPE ~ RECORD [ r: CD.Rect, l: CD.Layer ]; AddRectParameters: TYPE ~ RECORD [ tes: REF CornerStitching.Tesselation, cir: REF SX.Circuit, PerDrawRect: SXTechnology.PerDrawRectProc, gateNode: REF SX.CircuitNode, postRectList: LIST OF REF Post, clientData: REF ANY ]; AddRectangle: CD.DrawRectProc -- [r: Rect, l: Layer, pr: DrawRef] -- ~ { data: REF AddRectParameters ~ NARROW[ pr.devicePrivate]; level: SXTechnology.TransistorMaterial ~ data.PerDrawRect[r, l, data.clientData]; IF ~CDBasics.NonEmpty[r] THEN RETURN; SELECT level FROM nothing => NULL; diffusion => { occupants: LIST OF REF CornerStitching.Region _ NARROW[data.tes.EnumerateArea[r]]; data.tes.ChangeRect[ r, difPtr]; WHILE occupants # NIL DO SELECT occupants.first.value FROM polPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr]; chanPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr]; ENDCASE; occupants _ occupants.rest ENDLOOP }; polysilicon => { occupants: LIST OF REF CornerStitching.Region _ NARROW[data.tes.EnumerateArea[r]]; data.tes.ChangeRect[ r, polPtr]; WHILE occupants # NIL DO SELECT occupants.first.value FROM difPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr]; chanPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr]; ENDCASE; occupants _ occupants.rest ENDLOOP; IF data.gateNode = NIL THEN data.gateNode _ data.cir.AddRect[lev~l, dim~r] ELSE [] _ data.cir.AddRect[lev~l, dim~r, value~data.gateNode]; }; postProcess => { data.postRectList _ CONS[ NEW[Post _ [r~ r, l~ l]], data.postRectList]; }; ENDCASE; -- I guess the end case is implant, well let me tell you one thing I don't deal with implant OK. }; ProcessMosTransistor: PUBLIC PROCEDURE [ appl: CD.Instance, pos: CD.Position, orient: CD.Orientation, cir: REF SX.Circuit, difSpinifex, polSpinifex: SX.SpinifexLayerIndex, difChannel, channelEdge: REF SX.Constraint, difChanSep, difToPolSep: CD.Number, PerDrawRect: SXTechnology.PerDrawRectProc, data: REF ANY _ NIL, PostProcessor: SXTechnology.ReportDifProc _ NIL] RETURNS [gateNode: REF SX.CircuitNode, sourceDrainNodes: LIST OF REF SX.CircuitNode, sourceDrainCount: INTEGER] ~ { FindChannelEdge: CornerStitching.PerTileProc -- [tile: TilePtr, data: REF ANY] RETURNS [REF ANY] -- ~{ occupants, tmp: LIST OF REF CornerStitching.Region; tes: REF CornerStitching.Tesselation ~ NARROW[data]; IF tile.Value = chanPtr THEN { occupants _ NARROW[tes.EnumerateArea[CDBasics.Extend[tile.Area, difToPolSep]]]; WHILE occupants # NIL DO tmp _ occupants.rest; IF occupants.first.value = difPtr THEN { occupants.rest _ chEdge; chEdge _ occupants }; occupants _ tmp ENDLOOP } }; ConvertMaskGeom: CornerStitching.PerTileProc -- [tile: TilePtr, data: REF ANY] RETURNS [REF ANY] -- ~{ SELECT tile.Value FROM difPtr => { CheckChangeAndAdd: PROCEDURE [t: CornerStitching.TilePtr] ~ { IF t.Value = difPtr THEN { tranGeom.InlineChangeTile[ t, node]; [] _ cir.AddRect[ lev~appl.ob.layer, dim~t.Area, value~node] } ELSE WITH t.Value SELECT FROM cn: REF SX.CircuitNode => SX.LookupNode[cn].superceded _ node; ENDCASE; }; node: REF SX.CircuitNode _ cir.AddRect[lev~appl.ob.layer, dim~tile.Area]; sdList _ CONS[ node, sdList]; tranGeom.InlineChangeTile[ tile, node]; FOR st: CornerStitching.TilePtr _ tile.WSouthNeighbour, st.NEastNeighbour WHILE st.WestEdge < tile.EastEdge DO CheckChangeAndAdd[ st]; ENDLOOP; FOR wt: CornerStitching.TilePtr _ tile.SWestNeighbour, wt.ENorthNeighbour WHILE wt.SouthEdge < tile.NorthEdge DO CheckChangeAndAdd[ wt]; ENDLOOP; FOR nt: CornerStitching.TilePtr _ tile.ENorthNeighbour, nt.SWestNeighbour WHILE nt.EastEdge > tile.WestEdge DO CheckChangeAndAdd[ nt]; ENDLOOP; FOR et: CornerStitching.TilePtr _ tile.NEastNeighbour, et.WSouthNeighbour WHILE et.NorthEdge > tile.SouthEdge DO CheckChangeAndAdd[ et]; ENDLOOP; }; chanPtr => { [] _ cir.AddBox[ spinifexLayer~difSpinifex, dim~tile.Area, interestBloat~ [difChanSep, difChanSep, difChanSep, difChanSep], value~difChannel]; }; polPtr => NULL; ENDCASE }; AddParm: REF AddRectParameters ~ NEW[AddRectParameters]; tranGeom: REF CornerStitching.Tesselation ~ CornerStitching.NewTesselation[]; sdList: LIST OF REF SX.CircuitNode _ NIL; dr: CD.DrawRef ~ CD.CreateDrawRef[NIL]; chEdge: LIST OF REF CornerStitching.Region _ NIL; AddParm.tes _ tranGeom; AddParm.cir _ cir; AddParm.PerDrawRect _ PerDrawRect; AddParm.gateNode _ NIL; AddParm.postRectList _ NIL; AddParm.clientData _ data; dr.drawRect _ AddRectangle; dr.devicePrivate _ AddParm; appl.ob.class.drawMe[appl, pos, orient, dr]; IF (gateNode _ AddParm.gateNode) = NIL THEN ERROR; [] _ tranGeom.EnumerateArea[ rect~CDBasics.universe, perTile~FindChannelEdge, data~tranGeom]; [] _ tranGeom.EnumerateArea[ rect~CDBasics.universe, perTile~ConvertMaskGeom]; IF PostProcessor # NIL THEN FOR pL: LIST OF REF Post _ AddParm.postRectList, pL.rest WHILE pL # NIL DO FindNodes: CornerStitching.PerTileProc -- [tile: TilePtr, data: REF ANY] RETURNS [REF ANY] -- ~{ WITH tile.Value SELECT FROM cn: REF SX.CircuitNode => PostProcessor[cn, pL.first.r, pL.first.l]; ENDCASE }; [] _ tranGeom.EnumerateArea[ rect~pL.first.r, perTile~FindNodes]; ENDLOOP; WHILE chEdge # NIL DO [] _ cir.AddBox[ spinifexLayer~polSpinifex, dim~chEdge.first.rect, value~channelEdge]; chEdge _ chEdge.rest ENDLOOP; sourceDrainNodes _ NIL; sourceDrainCount _ 0; WHILE sdList # NIL DO sdfirst: LIST OF REF SX.CircuitNode ~ sdList; sdList _ sdList.rest; IF sdfirst.first.superceded # NIL THEN LOOP; FOR alreadySeen: LIST OF REF SX.CircuitNode _ sourceDrainNodes, alreadySeen.rest WHILE alreadySeen # NIL DO IF alreadySeen.first = sdfirst.first THEN EXIT; REPEAT FINISHED => { sdfirst.rest _ sourceDrainNodes; sourceDrainNodes _ sdfirst; sourceDrainCount _ sourceDrainCount.SUCC; } ENDLOOP; ENDLOOP; }; SetUpResolution: PUBLIC PROCEDURE [constrArray: REF SX.ConstraintArray, res: SXTechnology.ResolutionTable] RETURNS [REF SX.ConstraintResolution] ~ { Index: TYPE ~ SX.ConstraintIndex; CoreIndex: TYPE ~ [1 .. Index.LAST]; cnsRes: REF SX.ConstraintResolution ~ NEW [SX.ConstraintResolution _ ALL[ALL[NIL]]]; RowUsed, ColumnUsed: ARRAY CoreIndex OF BOOLEAN _ ALL[FALSE]; excl: Index ~ SX.excludeIndex; --2 viol: Index ~ SX.violateIndex; --3 exclusionConstraint: REF SX.Constraint ~ NEW[ SX.Constraint _ [ $ExcludeByOpaqueCell, SX.excludeIndex]]; violationConstraint: REF SX.Constraint ~ NEW[ SX.Constraint _ [ $OpaqueCellViolation, SX.violateIndex]]; RowUsed[excl] _ ColumnUsed[excl] _ RowUsed[viol] _ ColumnUsed[viol] _ TRUE; cnsRes[0][excl] _ cnsRes[excl][0] _ exclusionConstraint; cnsRes[0][viol] _ cnsRes[viol][0] _ violationConstraint; FOR i: Index IN [1 .. Index.LAST] DO cnsRes[excl][i] _ cnsRes[i][excl] _ exclusionConstraint; cnsRes[viol][i] _ cnsRes[i][viol] _ violationConstraint; ENDLOOP; cnsRes[excl][excl] _ violationConstraint; FOR i: Index IN [0..Index.LAST] DO xi: Index ~ res[i][0]; xj: Index ~ res[0][i]; cnsRes[0][i] _ cnsRes[i][0] _ constrArray[i]; IF constrArray[i] # NIL AND i # constrArray[i].index THEN CD.Error[ec~ other, explanation~ "constrArray entry position, index mismatch"]; IF xi # 0 THEN { IF ColumnUsed[xi] THEN CD.Error[ec~ other, explanation~ "Duplicate column key in Constraint Resolution Table"]; ColumnUsed[xi] _ TRUE }; IF xj # 0 THEN { IF RowUsed[xj] THEN CD.Error[ec~ other, explanation~ "Duplicate row key in Constraint Resolution Table"]; RowUsed[xj] _ TRUE }; ENDLOOP; FOR i: CoreIndex IN CoreIndex DO IF RowUsed[i] # ColumnUsed[i] THEN CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table between row & column keys"]; ENDLOOP; FOR i: CoreIndex IN CoreIndex DO xi: Index ~ res[i][0]; IF xi = 0 THEN FOR j: CoreIndex IN CoreIndex DO IF res[i][j] # 0 THEN CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table entries"]; ENDLOOP ELSE FOR j: CoreIndex IN CoreIndex DO xj: Index ~ res[0][j]; IF xj = 0 THEN FOR k: CoreIndex IN CoreIndex DO IF res[k][j] # 0 THEN CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table entries"]; ENDLOOP ELSE { result: Index ~ res[i][j]; IF result = 0 THEN CD.Error[ec~ other, explanation~ "Missing entry in Constraint Resolution Table"]; cnsRes[xi][xj] _ constrArray[ result ] } ENDLOOP ENDLOOP; FOR i: CoreIndex IN CoreIndex DO FOR j: CoreIndex IN CoreIndex DO IF cnsRes[i][j] # cnsRes[j][i] THEN CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table entries"]; ENDLOOP ENDLOOP; RETURN [cnsRes] }; RegisterTechnologyHandle: PUBLIC PROCEDURE [cdTech: CD.Technology, technologyHandle: REF SX.TechHandle] ~ { FOR i: SX.SpinifexLayerIndex IN [SX.SpinifexLayerIndex.FIRST .. technologyHandle.numSpinifexLayers) DO IF technologyHandle.constraintResolutions[i] = NIL THEN technologyHandle.constraintResolutions[i] _ defaultResolution; IF technologyHandle.rules[i] = NIL THEN technologyHandle.rules[i] _ technologyIndependentRules ELSE { FOR lastRule: LIST OF REF SX.GeometricRule _ technologyHandle.rules[i], lastRule.rest WHILE lastRule.rest # NIL DO NULL; REPEAT FINISHED => { IF lastRule.rest # NIL THEN ERROR; lastRule.rest _ technologyIndependentRules } ENDLOOP } ENDLOOP; CDProperties.PutPropOnTechnology[onto~ cdTech, prop~ SXAtoms.spinifex, val~ technologyHandle]; CDObjectProcs.RegisterFurther[key~ SXAtoms.spinifex, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; CDObjectProcs.RegisterFurther[key~ SXAtoms.thymePrint, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; CDObjectProcs.RegisterFurther[key~ SXAtoms.rosePrint, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; CDObjectProcs.RegisterFurther[key~ SXAtoms.coreOut, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; CDObjectProcs.RegisterFurther[key~ SXAtoms.init, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; CDObjectProcs.RegisterFurther[key~ SXAtoms.fini, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE]; }; RegisterSpinifexObjectProcs: PUBLIC PROCEDURE [cdTech: CD.Technology, objectType: ATOM, conv: SX.ConversionProc, thyme, rose, core: SXOutput.LinkagePrintProc _ NIL, fini: SXOutput.LinkageHousekeeper _ NIL] ~ { op: REF CD.ObjectClass; IF (op_CD.FetchObjectClass[ objectType~objectType, technology~cdTech]) = NIL THEN CD.Error[explanation: "Version mismatch among ChipNDale and Spinifex"]; CDObjectProcs.StoreFurther[ p~op, key~SXAtoms.spinifex, value~ NEW[SX.ConversionProc_conv]]; IF thyme # NIL THEN CDObjectProcs.StoreFurther[ p~op, key~SXAtoms.thymePrint, value~ NEW[SXOutput.LinkagePrintProc_thyme]]; IF rose # NIL THEN CDObjectProcs.StoreFurther[ p~op, key~SXAtoms.rosePrint, value~ NEW[SXOutput.LinkagePrintProc_rose]]; IF core # NIL THEN CDObjectProcs.StoreFurther[ p~op, key~SXAtoms.coreOut, value~ NEW[SXOutput.LinkagePrintProc_core]]; IF fini # NIL THEN CDObjectProcs.StoreFurther[ p~op, key~SXAtoms.fini, value~ NEW[SXOutput.LinkageHousekeeper_fini]]; }; technologyIndependentRules: LIST OF REF SX.GeometricRule; InitTechnologyIndependentRules: PROCEDURE ~ { detectOpaqueViolation: REF SX.GeometricRule ~ NEW[ SX.GeometricRule _ [ extent~ CD.lambda, message~ "Opaque cell boundary violated", trigger1~ ALL[TRUE], trigger2~ ALL[TRUE]]]; detectOpaqueViolation.trigger1[SX.violateIndex] _ FALSE; technologyIndependentRules _ LIST[detectOpaqueViolation]; }; defaultResolution: REF SX.ConstraintResolution; InitDefaultResolution: PROCEDURE ~ { Index: TYPE ~ SX.ConstraintIndex; CoreIndex: TYPE ~ [1 .. Index.LAST]; excl: Index ~ SX.excludeIndex; viol: Index ~ SX.violateIndex; res: REF SX.ConstraintResolution; exclusionConstraint: REF SX.Constraint ~ NEW[ SX.Constraint _ [ $ExcludeByOpaqueCell, SX.excludeIndex]]; violationConstraint: REF SX.Constraint ~ NEW[ SX.Constraint _ [ $OpaqueCellViolation, SX.violateIndex]]; defaultResolution _ NEW[SX.ConstraintResolution]; res _ defaultResolution; res[0][excl] _ res[excl][0] _ exclusionConstraint; res[0][viol] _ res[viol][0] _ violationConstraint; FOR i: CoreIndex IN CoreIndex DO res[excl][i] _ res[i][excl] _ exclusionConstraint; res[viol][i] _ res[i][viol] _ violationConstraint; ENDLOOP; res[excl][excl] _ violationConstraint; }; GetCircuitFromCDObject: PUBLIC PROCEDURE [cdOb: CD.Object] RETURNS [c: REF SX.Circuit_NIL] = BEGIN sx: REF SX.LogicalCell = SXAccessInternal.GetSXData[cdOb]; IF sx#NIL THEN { IF sx.analysisState#useCircuit THEN ERROR; c _ sx.circuit } END; -- Module Initialization. InitTechnologyIndependentRules[]; InitDefaultResolution[]; END. ภSXTechnologyImpl.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Written by Shand, June 12, 1984 3:11:49 pm PDT Last Edited by: Shand, March 12, 1985 3:04:13 pm PST Last Edited by: Jacobi, July 17, 1985 7:57:30 pm PDT Last edited by: gbb August 9, 1985 4:26:09 pm PDT -- I don't care about efficiency here I'm afraid -- Save on list and process and enumerate Diffusion nodes in this region later. -- When we get these crazy bent guys well I tell you we just don't know what to do, so we grab ourselves a tile world and plunk it down in that, then maybe we can start to make sense of it. -- We are fairly liberal with interest boundaries here, its could be made a lot tighter as is done in the processing of normal Xstrs. All this means is that bent Xstrs will be instantiated for analysis even when they appear in isolation. Acutally this may be what we want since bent transistors are not so constrained that errors are totally precluded in an isolated object (they are for straight Xstrs). Also we let the other code calculate areas and perims, it is likely to be inaccurate. --Ch. J., Jan 30, 1985 included LookupNode without further thinking -- Called for pullups where we can make a sensible decision on which node is the source. -- First set up technology independent Opaque cell constraints. -- Now copy the elements of constrArray to the first row and column of cnsRes. -- Debugging aid for technology writer. -- Debugging aid for technology writer. NULL; -- We set violateIndex = FALSE, ALL else TRUE so that corner checks face inward, which should result in more logically pleasing error reports. -- Set up default technology independent Opaque cell constraints. Edited on January 30, 1985 8:09:05 pm PST, by jacobi in CheckChangeAndAdd: "cn.superceded _ node" replaced by "SX.LookupNode[cn].superceded _ node" Edited on March 7, 1985 1:43:51 am PST, by Shand Add interest bound to difChannel to detect interatcions between channel and dif changes to: ProcessMosTransistor new parameter to pass bloat distance, ConvertMaskGeom (local of ProcessMosTransistor) interestBloat parameter passed to AddBox. Edited on March 9, 1985 5:33:13 pm PST, by Shand Changed name of CircuitConstraint in SX to Constraint Added new procedure SetUpResolution to aid technology dependent clients in the construction of ConstraintResolution ARRAYs. changes to: DIRECTORY, ProcessMosTransistor, SetUpResolution, SetUpResolution Edited on March 12, 1985 3:04:13 pm PST, by Shand Technology Independent constraints added for ensuring the integrity of Opaque cells. New procedure GetCircuitFromCDObject to allow SXAtoms to be confined to Technology Independent part. changes to: DIRECTORY, ProcessMosTransistor, SetUpResolution, SXExtrasImpl, RegisterTechnologyHandle, RegisterSpinifexObjectClass, technologyIndependentRules, InitTechnologyIndependentRules, defaultResolution, InitDefaultResolution, GetCircuitFromCDObject, SetUpResolution Edited on March 27, 1985 6:39:31 pm PST, by Beretta changes to: SetUpResolution: debugging. Edited on May 6, 1985 11:26:55 am PDT, by Beretta Converted to ChipNDale CD20 gbb August 9, 1985 2:36:53 pm PDT Implementation of Core output. changes to: RegisterSpinifexObjectProcs: added parameter for core. สส˜code™Kšœ ฯmœ7™BK™.K™4J™4K™1—unitšฯk ˜ Kšžœžœ ˜จKšœ žœ˜,Kšœžœ!˜4Kšœ žœ˜)Kšœžœใ˜๘Kšžœ˜Kšœ˜Kšœžœ8˜EKšœ žœ(˜6Kšœ ˜ —šัaoxœžœž˜KšžœžœW˜aKšžœ ˜Kšžœ˜—Kšž˜Lš œžœžœžœžœ˜Kš œžœžœžœžœ˜Kš œ žœžœžœžœ˜šœžœžœ˜Kšœžœ˜ Kšœžœ˜ K˜—šœžœžœ˜"Kšœžœ˜%Kšœžœ ˜Kšœ*˜*Kšœ žœ˜Kšœžœžœžœ˜Kšœ žœž˜K˜—šฯb œžœะcs&œ˜HKšœ0™0Kšœžœžœ˜8KšœQ˜QLšžœžœžœ˜%šžœž˜Kšœ žœ˜šœ˜Kš œ žœžœžœžœ˜RKšœ ˜ šžœ žœž˜šžœž˜!KšœL˜LKšœM˜MKšžœ˜—K˜Kšž˜—Kšœ˜—šœ˜Kš œ žœžœžœžœ˜RKšœ ˜ šžœ žœž˜šžœž˜!KšœL˜LKšœM˜MKšžœ˜—K˜Kšžœ˜—šžœžœž˜Kšœ.˜.—šž˜Kšœ9˜9—Kšœ˜—šœ˜K™OKšœžœžœ*˜GK˜—Kšžœฯc`˜j—K˜—š&ฯnœžœž œ žœžœžœžœWžœ)žœ:žœžœžœ.žœžœ žœ#žœžœžœ#žœ˜เK™ฝšฃœข6œ˜fKšœžœžœžœ˜3Kšœžœžœ˜4šžœžœ˜Kšœ žœ=˜Ošžœ žœž˜Kšœ˜šžœ žœ˜(Kšœ˜Kšœ˜K˜—Kšœ˜Kšž˜—K˜—K˜—šฃœข6œ˜fK™ํšžœ ž˜šœ ˜ šฃœž œ!˜=šžœžœ˜Kšœ$˜$Kšœ<˜˜>—šžœžœž˜'Kšœ6˜6—šžœ˜š žœ žœžœžœ=žœžœž˜rKšžœ˜šžœžœ˜Kšžœžœžœžœ˜"Kšœ*˜*K˜—Kšž˜—K˜—Kšžœ˜—Lšœ^˜^Lš œJžœ žœžœžœ˜€Kš œLžœ žœžœžœ˜‚Kš œKžœ žœžœžœ˜Kš œIžœ žœžœžœ˜Kš œFžœ žœžœžœ˜|Kš œFžœ žœžœžœ˜|K˜—šฃœžœž œ žœžœJžœ&žœ˜ัKšœžœžœ ˜L–B[ec: CD.ErrorCode _ programmingError, explanation: ROPE _ NIL]š žœžœ@žœžœžœE˜™Kšœ?žœ˜\šžœ žœž˜KšœAžœ#˜g—šžœžœž˜Kšœ@žœ"˜e—šžœžœž˜Kšœ>žœ"˜c—šžœžœž˜Kšœ;žœ$˜b—K˜—Lšœžœžœžœ˜9šฃœž œ˜-Kšœžœžœžœ=žœžœ žœžœ˜ฐKšœŽ™ŽKšœ2žœ˜8Kšœžœ˜9K˜—Lšœžœ˜/šฃœž œ˜$Kšœžœ˜!Kšœ žœžœ˜$Kšœ˜Kšœ˜Kšœžœ˜!Lšœžœžœ<˜hKšœžœžœ<˜hL™AKšœžœ˜1Kšœ˜Kšœ2˜2Kšœ2˜2šžœžœ ž˜ Kšœ2˜2Kšœ2˜2Kšžœ˜—Kšœ&˜&K˜—L˜šฃœžœž œžœ žœžœžœ žœ˜\Lšž˜Kšœžœžœ0˜:šžœžœžœ˜Kšžœžœžœ˜*Kšœ˜Kšœ˜—Kšžœ˜—head˜Kšœ!˜!Kšœ˜—Kšžœ˜K™™4Kšœ^™^—™0K™OKšœ ฯrœ%ฅœJ™ —™0Kšœ5™5KšœฅœX™{Kšœ ฅA™M—™1Kšœdฃœ@™บKšœ ฅ„™—™3Kšœ คœ ™'—™1K™—™!K™Kšœ ฅœ™B——…—4ฎQ8