DIRECTORY CD, CDCells, CDRects, DABasics, GC, GCPrivate, GCCIG, IP, IPCoTab, IPCTG, IPTop, RefTab, RTBasic, CoreRouteFlat, Graphs0, Graphs0Path; GCCIGImpl: CEDAR PROGRAM IMPORTS CDCells, CDRects, GC, GCPrivate, IPCoTab, IPCTG, RefTab, RTBasic, CoreRouteFlat, Graphs0, Graphs0Path EXPORTS GCCIG = BEGIN RefINT: TYPE = REF INT; IntersectionInfo: TYPE = REF IntersectionInfoRec; IntersectionInfoRec: TYPE = RECORD[ -- Info for intersection nodes hCh: IPCTG.Channel _ NIL, -- Channels for this node vCh: IPCTG.Channel _ NIL, -- Channels for this node intersection: IPCTG.Intersection _ NIL]; -- Intersection for this node PinInfo: TYPE = REF PinInfoRec; PinInfoRec: TYPE = RECORD[ -- Info for pin nodes instance: CoreRouteFlat.Instance _ NIL, oNode: CoreRouteFlat.ONode _ NIL, pPin: CoreRouteFlat.Pin _ [ ], removedArc: Graphs0.Arc _ NIL]; ArcInfo: TYPE = REF ArcInfoRec; ArcInfoRec: TYPE = RECORD[ -- Info for pin nodes cost: INT _ 0, ch: IPCTG.Channel _ NIL]; Create: PUBLIC PROC[context: GC.Context] RETURNS[cig: GCCIG.Graph]={ ConnectHorizontalChannel: IPCTG.EachChannelAction ={ EachIntersection: IPCTG.EachIntersectionAction = {lastNode _ NewArc[cig, ch, i, lastNode]}; lastInt: IPCTG.Intersection _ IPCTG.End[ch, neg]; lastNode: Graphs0.Node _ Graphs0.AddNewNode[cig.graph, NEW [IntersectionInfoRec _ [hCh: ch, vCh: lastInt.ch, intersection: lastInt]]]; lastInt.any _ lastNode; [] _ AllIntersections[ch, EachIntersection]; [] _ NewArc[cig, ch, IPCTG.End[ch, pos], lastNode]}; ConnectVerticalChannel: IPCTG.EachChannelAction ={ EachIntersection: IPCTG.EachIntersectionAction = { currentNode: Graphs0.Node _ NARROW[OppsiteInt[ch, i].any]; [] _ Graphs0.AddNewArc[cig.graph, ArcWeight[lastNode, currentNode, ch], lastNode, currentNode]; lastNode _ currentNode}; lastNode: Graphs0.Node _ NARROW[OppsiteInt[ch, IPCTG.End[ch, neg]].any]; posNode: Graphs0.Node _ NARROW[OppsiteInt[ch, IPCTG.End[ch, pos]].any]; [] _ AllIntersections[ch, EachIntersection]; [] _ Graphs0.AddNewArc [cig.graph, ArcWeight[lastNode, posNode, ch], lastNode, posNode]}; graph: Graphs0.Graph _ Graphs0.Create[]; ctg: IPCTG.Ref _ NARROW[context.topology, IPTop.Ref].ctg; cig _ NEW[GCCIG.GraphRec _ [context: context, graph: graph]]; [] _ IPCTG.DirectedChannels[ctg, ConnectHorizontalChannel, hor]; [] _ IPCTG.DirectedChannels[ctg, ConnectVerticalChannel, ver]}; Destroy: PUBLIC PROC [cig: GCCIG.Graph] = {Graphs0.Destroy[cig.graph]}; InsertNet: PUBLIC PROC [cig: GCCIG.Graph, net: CoreRouteFlat.Net, connectionStrength: GCCIG.ConnectionStrength] RETURNS [nodeSetList: GCCIG.NodeSetList _ NIL] ~ { FOR ins: LIST OF CoreRouteFlat.InstONode _ net.instONodes, ins.rest WHILE ins#NIL DO pinNodes: GCCIG.NodeList _ InsertPin[cig, net, ins.first]; IF pinNodes # NIL THEN { SELECT connectionStrength FROM goodInternal => { FOR list: GCCIG.NodeList _ pinNodes, list.rest WHILE list # NIL DO firstNode: Graphs0.Node _ list.first; IF list.rest # NIL THEN { secondNode: Graphs0.Node _ list.rest.first; [] _ Graphs0.AddNewArc [cig.graph, NEW[ArcInfoRec _ [cost: 0, ch: NIL]], firstNode, secondNode]}; ENDLOOP; nodeSetList _ CONS[pinNodes, nodeSetList]}; power => { FOR list: GCCIG.NodeList _ pinNodes, list.rest WHILE list # NIL DO nodes: GCCIG.NodeList _NIL; nodeSetList _ CONS[CONS[list.first, nodes], nodeSetList] ENDLOOP}; highImpedance => nodeSetList _ CONS[pinNodes, nodeSetList]; ENDCASE => GC.Error[programmingError, "Not suppose to happen"]} ENDLOOP}; RemoveNodes: PUBLIC PROC[cig: GCCIG.Graph, nodeSetList: GCCIG.NodeSetList] ~ { FOR nodeSets: GCCIG.NodeSetList _ nodeSetList, nodeSets.rest WHILE nodeSets # NIL DO FOR nodes: GCCIG.NodeList _ nodeSets.first, nodes.rest WHILE nodes # NIL DO node: Graphs0.Node _ nodes.first; WITH node.nodeInfo SELECT FROM int: IntersectionInfo => NULL; pin: PinInfo => { arcs: Graphs0.ArcList _ Graphs0.RemoveNode[cig.graph, node]; oldArc: Graphs0.Arc _ NARROW[node.nodeInfo, PinInfo].removedArc; FOR list: Graphs0.ArcList _ arcs, list.rest WHILE list # NIL DO IF list.first.node1 # node AND list.first.node2 # node THEN GC.Error[programmingError, "Not suppose to happen."]; ENDLOOP; [] _ Graphs0.AddNewArc[cig.graph, oldArc.arcInfo, oldArc.node1, oldArc.node2]}; ENDCASE => GC.Error[callingError, "Invalid nodeInfo type."]; ENDLOOP; ENDLOOP; }; -- RemoveNodes -- ShortestPath: PUBLIC PROC[cig: GCCIG.Graph, nodeSetList: GCCIG.NodeSetList, net: CoreRouteFlat.Net] ~ { arcCost: Graphs0Path.ArcCostProc ~ {cost _ NARROW[arc.arcInfo, ArcInfo].cost}; arcTraversed: Graphs0Path.EnumArcProc ~ { arcInfo: ArcInfo _ NARROW[arc.arcInfo]; ch: IPCTG.Channel _ NARROW[arcInfo.ch]; IF ch # NIL THEN { DoNode: PROC [node: GCCIG.Node] ~ { WITH node.nodeInfo SELECT FROM int: IntersectionInfo => { IF EndOfCh[ch, int, neg] THEN netDesc.bottomOrLeftExit _ TRUE; IF EndOfCh[ch, int, pos] THEN netDesc.topOrRightExit _ TRUE}; pin: PinInfo => { phyPin: GCPrivate.PhyPinDesc _ NEW[GCPrivate.PhyPinDescRec _ [pin.instance, pin.oNode, pin.pPin]]; IF ~GCPrivate.PinOnList[netDesc, phyPin] THEN netDesc.pinList _ CONS[phyPin, netDesc.pinList]}; ENDCASE => GC.Error[callingError, "Invalid nodeInfo type."]}; channel: GCPrivate.Channel _ NARROW[ch.any]; val: REF ANY _ RefTab.Fetch[channel.connections, net].val; netDesc: GCPrivate.NetDesc _ IF val = NIL THEN NEW[GCPrivate.NetDescRec] ELSE NARROW[val]; DoNode[arc.node1]; DoNode[arc.node2]; [] _ RefTab.Store[channel.connections, net, netDesc]}}; [] _ Graphs0Path.FindPath [graph:cig.graph, nodeSets:nodeSetList, arcCostProc: arcCost, arcDeliverProc: arcTraversed]}; Check: PUBLIC PROC [cig: GCCIG.Graph] ={Graphs0.Check[cig.graph]}; -- Check-- PaintShortestPath: PUBLIC PROC[cig: GCCIG.Graph, nodeSetList: GCCIG.NodeSetList] RETURNS [object: CD.Object] ~ { arcCost: Graphs0Path.ArcCostProc ~ {cost _ NARROW[arc.arcInfo, ArcInfo].cost}; arcTraversed: Graphs0Path.EnumArcProc ~ { layer: CD.Layer _ cig.context.rules.vertRules.branchLayer; MakeCDArc[arc, object, layer]}; object _ PaintGraph[cig]; [] _ Graphs0Path.FindPath [graph: cig.graph, nodeSets: nodeSetList, arcCostProc:arcCost, arcDeliverProc:arcTraversed]}; PaintGraph: PUBLIC PROC [cig: GCCIG.Graph] RETURNS [object: CD.Object _ CDCells.CreateEmptyCell[]] ~ { EachNode: Graphs0.EnumNodeProc ~ { layer: CD.Layer _ cig.context.rules.horizRules.trunkLayer; MakeCDNode[node, object, layer]}; EachArc: Graphs0.EnumArcProc ~ { layer: CD.Layer _ cig.context.rules.vertRules.trunkLayer; MakeCDArc[arc, object, layer]}; [] _ Graphs0.EnumNodes[cig.graph, EachNode]; [] _ Graphs0.EnumArcs[cig.graph, EachArc]; RTBasic.RepositionCell[object]}; InsertPin: PROC[cig: GCCIG.Graph, net: CoreRouteFlat.Net, instONode: CoreRouteFlat.InstONode] RETURNS [pinNodes: GCCIG.NodeList _ NIL] ~ { IF instONode.oNode.public THEN { -- this is a public object node EachNode: Graphs0.EnumNodeProc ~ { WITH node.nodeInfo SELECT FROM int: IntersectionInfo => { useThisOne: BOOLEAN _ SELECT side FROM bottom => int.hCh = bottomChannel, right => int.vCh = rightChannel, top => int.hCh = topChannel, left => int.vCh = leftChannel, ENDCASE => FALSE; IF useThisOne AND ~MemberNode[node, pinNodes] THEN pinNodes _ CONS[node, pinNodes]}; pin: PinInfo => NULL; ENDCASE => GC.Error[callingError, "Invalid nodeInfo type."]}; side: DABasics.Side; bottomChannel, rightChannel, topChannel, leftChannel: IPCTG.Channel; FOR side IN DABasics.Side DO topology: IPTop.Ref _ NARROW[cig.context.topology]; IF ~ParentFacesSide[net, side] THEN LOOP; [bottomChannel, rightChannel, topChannel, leftChannel] _ IPCTG.GetBoundingChannels[topology.ctg]; IF ~ChildrenFaceSide[cig, net, side] THEN [] _ Graphs0.EnumNodes[cig.graph, EachNode]; ENDLOOP} ELSE FOR pins: LIST OF CoreRouteFlat.Pin _ instONode.oNode.pins, pins.rest WHILE pins#NIL DO oldArc: Graphs0.Arc _ FindArcForPin[cig, instONode.instance, pins.first]; arcInfo: ArcInfo _ NARROW[oldArc.arcInfo]; newNode: Graphs0.Node _ Graphs0.AddNewNode[cig.graph, NEW[PinInfoRec _ [ instance: instONode.instance, oNode: instONode.oNode, pPin: pins.first, removedArc: oldArc] ] ]; pinNodes _ CONS[newNode, pinNodes]; [] _ Graphs0.AddNewArc [cig.graph, ArcWeight[oldArc.node1, newNode, arcInfo.ch], oldArc.node1, newNode]; [] _ Graphs0.AddNewArc [cig.graph, ArcWeight[newNode, oldArc.node2, arcInfo.ch], newNode, oldArc.node2]; Graphs0.RemoveArc[cig.graph, oldArc] ENDLOOP}; -- InsertPin -- ParentFacesSide: PROC [net: CoreRouteFlat.Net, side: DABasics.Side] RETURNS [faces: BOOLEAN _ FALSE] ~ { FOR ins: LIST OF CoreRouteFlat.InstONode _ net.instONodes, ins.rest WHILE ins#NIL DO IF ~ins.first.oNode.public THEN LOOP; FOR pins: LIST OF CoreRouteFlat.Pin _ ins.first.oNode.pins, pins.rest WHILE pins#NIL DO IF pins.first.side = side THEN RETURN[TRUE] ENDLOOP ENDLOOP}; ChildrenFaceSide: PROC [cig: GCCIG.Graph, net: CoreRouteFlat.Net, side: DABasics.Side] RETURNS [faces: BOOLEAN _ FALSE] ~ { topology: IPTop.Ref _ NARROW[cig.context.topology]; FOR ins: LIST OF CoreRouteFlat.InstONode _ net.instONodes, ins.rest WHILE ins#NIL DO IF ins.first.oNode.public THEN LOOP; FOR pins: LIST OF CoreRouteFlat.Pin _ ins.first.oNode.pins, pins.rest WHILE pins#NIL DO ch: IPCTG.Channel _ IPCoTab.GetPrinCh [NARROW[ins.first.instance.any], SideToEdgeType[pins.first.side]]; IF IPCTG.IsBoundingChannel[topology.ctg, ch] THEN IF pins.first.side = side THEN RETURN[TRUE] ENDLOOP ENDLOOP}; ArcWeight: PROC [node1, node2: Graphs0.Node, ch: IPCTG.Channel] RETURNS [arcInfo: ArcInfo] ~ { arcInfo _ NEW[ArcInfoRec _ [cost: ABS[PQPosOfNode[node1, ch.type].p - PQPosOfNode[node2, ch.type].p], ch: ch]]}; NewArc: PROC [cig: GCCIG.Graph, hCh: IPCTG.Channel, int: IPCTG.Intersection, lastNode: Graphs0.Node] RETURNS [currentNode: Graphs0.Node]~ { currentNode _ Graphs0.AddNewNode[cig.graph, NEW[IntersectionInfoRec _ [hCh: hCh, vCh: int.ch, intersection: int]]]; int.any _ currentNode; [] _ Graphs0.AddNewArc [cig.graph, ArcWeight[lastNode, currentNode, hCh], lastNode, currentNode]}; AllIntersections: PROC [ch: IPCTG.Channel, p: IPCTG.EachIntersectionAction] RETURNS [quit: BOOL] ~ { Wrap: IPCTG.EachIntersectionAction ~ {IF i.type = 1 THEN quit _ p[i]}; quit _ IPCTG.Intersections[ch, neg, p]; -- enumerate all below and crossing intersections IF ~quit THEN quit _ IPCTG.Intersections[ch, pos, Wrap]}; -- enumerate above intersections FindArcForPin: PROC [cig: GCCIG.Graph, instance: CoreRouteFlat.Instance, pin: CoreRouteFlat.Pin] RETURNS [foundArc: Graphs0.Arc _ NIL] ~ { ArcProc: Graphs0.EnumArcProc ~ { arcCh: IPCTG.Channel _ NARROW[arc.arcInfo, ArcInfo].ch; node1: Graphs0.Node _ NARROW[arc.node1]; node2: Graphs0.Node _ NARROW[arc.node2]; posNode1: INT _ PQPosOfNode[node1, ch.type].p; posNode2: INT _ PQPosOfNode[node2, ch.type].p; norm: BOOLEAN _ posNode1 <= pos AND pos <= posNode2; rev: BOOLEAN _ posNode2 <= pos AND pos <= posNode1; IF ch = arcCh AND (norm OR rev) THEN {quit _ TRUE; foundArc _ arc} }; ch: IPCTG.Channel _ IPCoTab.GetPrinCh[NARROW[instance.any], SideToEdgeType[pin.side]]; range: CoreRouteFlat.Range _ CoreRouteFlat.TranslateRange[instance, pin]; pos: INT _ (range.min + range.max)/2; IF ~Graphs0.EnumArcs[cig.graph, ArcProc] THEN GC.Error[programmingError, "Not suppose to happen."]}; SideToEdgeType: PROC [side: DABasics.Side] RETURNS [et: IP.EdgeTypes] ~ { et _ SELECT side FROM top => north, left => west, bottom => south, right => east, ENDCASE => GC.Error[programmingError, "Call maintainer"]}; OppsiteInt: PROC [ch: IPCTG.Channel, i: IPCTG.Intersection] RETURNS [oppsiteI: IPCTG.Intersection] ~ { IntTest: IPCTG.EachIntersectionAction ~ {IF i.ch = ch THEN {oppsiteI _ i; quit _ TRUE}}; quit: BOOLEAN _ AllIntersections[i.ch, IntTest]; IF ~quit THEN quit _ IntTest[IPCTG.End[i.ch, neg]]; IF ~quit THEN quit _ IntTest[IPCTG.End[i.ch, pos]]; IF ~quit THEN GC.Error[programmingError, "Not suppose to happen."]}; PQPosOfNode: PROC [node: Graphs0.Node, direction: IP.ChType] RETURNS [RTBasic.PQPos] ~ { p, q: INT; WITH node.nodeInfo SELECT FROM int: IntersectionInfo => IF direction = hor THEN {p _ int.vCh.coord; q _ int.hCh.coord} ELSE {p _ int.hCh.coord; q _ int.vCh.coord}; pin: PinInfo => { range: CoreRouteFlat.Range _ CoreRouteFlat.TranslateRange[pin.instance, pin.pPin]; ch: IPCTG.Channel _ IPCoTab.GetPrinCh [NARROW[pin.instance.any], SideToEdgeType[pin.pPin.side]]; p _ (range.min + range.max)/2; q _ ch.coord}; ENDCASE => GC.Error[callingError, "Invalid nodeInfo type."]; RETURN[[p, q]]}; PosOfNode: PROC [node: Graphs0.Node] RETURNS [DABasics.Position] ~ { x, y: INT; WITH node.nodeInfo SELECT FROM int: IntersectionInfo => {x _ int.vCh.coord; y _ int.hCh.coord}; pin: PinInfo => { range: CoreRouteFlat.Range _ CoreRouteFlat.TranslateRange[pin.instance, pin.pPin]; middle: INT _ (range.min + range.max)/2; ch: IPCTG.Channel _ IPCoTab.GetPrinCh [NARROW[pin.instance.any], SideToEdgeType[pin.pPin.side]]; IF ch.type = hor THEN {x _ middle; y _ ch.coord} ELSE {x _ ch.coord; y _ middle}}; ENDCASE => GC.Error[callingError, "Invalid nodeInfo type."]; RETURN[[x, y]]}; Length: PUBLIC PROC [nodeSetList: GCCIG.NodeSetList] RETURNS[n: INT _ 0] = { UNTIL nodeSetList = NIL DO n _ n+1; nodeSetList _ nodeSetList.rest; ENDLOOP}; EndOfCh: PROC [ch: IPCTG.Channel, int: IntersectionInfo, pol: IP.PolarityTypes] RETURNS [found: BOOLEAN _ FALSE] ~ { -- TRUE if node is at end of ch represented by pol trial: IPCTG.Channel _ IF ch.type = hor THEN int.vCh ELSE int.hCh; IF trial = IPCTG.End[ch, pol].ch THEN found _ TRUE}; MemberNode: PROC [node: GCCIG.Node, list: GCCIG.NodeList] RETURNS [BOOL] = { UNTIL list = NIL DO IF list.first = node THEN RETURN[TRUE]; list _ list.rest; ENDLOOP; RETURN[FALSE]}; MakeCDNode: PROC [node: Graphs0.Node, object: CD.Object, nodeLayer: CD.Layer] ~ { size: DABasics.Position _ [8, 8]; pos: DABasics.Position _ PosOfNode[node]; nodeObj: CD.Object _ CDRects.CreateRect[size, nodeLayer]; [] _ GCPrivate.IncludeOb[object, nodeObj, [pos.x - size.x/2, pos.y - size.y/2]]}; MakeCDArc: PROC [arc: Graphs0.Arc, object: CD.Object, arcLayer: CD.Layer] ~ { width: INT _ 4; pos1: DABasics.Position _ PosOfNode[arc.node1]; pos2: DABasics.Position _ PosOfNode[arc.node2]; xDim: INT _ MAX[ABS[pos1.x - pos2.x], width]; yDim: INT _ MAX[ABS[pos1.y - pos2.y], width]; arcObj: CD.Object _ CDRects.CreateRect[[xDim, yDim], arcLayer]; pos: DABasics.Position _ IF pos1.x = pos2.x THEN [pos1.x - width/2, MIN[pos1.y, pos2.y]] ELSE IF pos1.y = pos2.y THEN [MIN[pos1.x, pos2.x], pos1.y - width/2] ELSE [MIN[pos1.x, pos2.x], MIN[pos1.y, pos2.y]]; [] _ GCPrivate.IncludeOb[object, arcObj, pos]}; END. GCCIGImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last Edited by: Preas, January 15, 1987 11:46:11 am PST Don Curry December 4, 1987 4:18:30 pm PST Provide operations on a channel intersection graph SHARES GC = BEGIN Add the net to cig. Remove a net from cig Find shortest path among pins of net Find shortest path among nodeSetList and construct a ChipNDale object Internal Procedures Add the pin to cig. If the children don't face the side then channel intersection nodes must be sources and targets in the shortest path search. RETURNS TRUE iff this net has a physical pin on a boundry for the higher level cell find intersection on oppsite channel corresponding to this one find position of node in direction find position of node Κœ˜šΟc™Jšœ Οmœ1™˜†J˜—šΟn œŸœŸ˜JšŸœŸœŸœ6˜mJšŸœŸ˜ JšŸœŸœŸ™šœŸ˜J˜—šœ ŸœŸœŸœ˜J˜—JšœŸœŸœ˜2šœŸœŸœ˜BJšœŸœ Ÿœ˜6JšœŸœ Ÿœ˜6JšœŸœŸœ˜FJ˜J˜—Jšœ ŸœŸœ ˜ šœ ŸœŸœ˜0Jšœ$Ÿœ˜(JšœŸœ˜"Jšœ!˜!JšœŸœ˜"J˜—Jšœ ŸœŸœ ˜ šœ ŸœŸœ˜0JšœŸœ˜JšœŸœ Ÿœ˜J˜—š  œŸœŸœ Ÿœ ŸœŸœ ˜DJ– "Cedar" style˜– "Cedar" styleš œŸœ˜4– "Cedar" styleš œŸœ˜0Jšœ*˜*—J– "Cedar" stylešœ ŸœŸœ˜1– "Cedar" stylešœ7Ÿ˜:J– "Cedar" stylešœK˜K—J– "Cedar" stylešœ˜J– "Cedar" stylešœ,˜,JšœŸœ˜4J– "Cedar" style˜—– "Cedar" styleš œŸœ˜2– "Cedar" styleš œŸœ˜2JšœŸœ˜:J– "Cedar" stylešœ_˜_J– "Cedar" stylešœ˜—J– "Cedar" stylešœŸœŸœ˜HJ– "Cedar" stylešœŸœŸœ˜GJ– "Cedar" stylešœ,˜,– "Cedar" stylešœ˜J– "Cedar" stylešœB˜B—J– "Cedar" style˜—J– "Cedar" stylešœ(˜(J– "Cedar" stylešœŸœ Ÿœ"˜JšŸœŸœŸœ˜=—šœ˜JšœŸœ@˜bšŸœ'Ÿ˜-JšœŸœ˜1——JšŸœŸœ0˜=——JšœŸœ ˜,JšœŸœŸœ.˜;šœŸœŸ˜)JšŸœŸœ˜JšŸœŸœ˜—Jšœ˜Jšœ˜Jšœ7˜7——šœ˜Jšœ]˜]—J˜—š  œŸœŸœŸœ% ˜MJ˜—š  œŸœŸœŸœŸœ ˜PJšŸœ Ÿœ ˜JšœE™EJšœ-Ÿœ˜Pšœ)˜)JšœŸœ1˜:Jšœ˜—Jšœ˜šœ˜Jšœ]˜]—J˜—š   œŸœŸœŸœŸœ Ÿœ(˜fš œ˜"JšœŸœ1˜:J– "Cedar" stylešœ!˜!—š œ˜ JšœŸœ0˜9Jšœ˜—Jšœ,˜,Jšœ*˜*Jšœ ˜ ——head™š  œŸœŸœC˜]JšŸœ Ÿœ Ÿœ˜,Jšœ™šŸœ˜šŸœ˜&š œ˜"šŸœŸœŸ˜šœ˜šœ ŸœŸœŸ˜&Jšœ"˜"Jšœ!˜!Jšœ˜Jšœ˜JšŸœŸœ˜—šŸœ Ÿœ˜-JšŸœ Ÿœ˜&——JšœŸœ˜JšŸœŸœ0˜>——JšœŸ˜Jšœ6Ÿœ ˜DšŸœŸœŸ˜JšœŸœ˜3JšŸœŸœŸœ˜)šœ8˜8JšŸœ#˜(—šŸœ#Ÿ˜)šœ,˜,J™|——JšŸœ˜——šŸœŸœŸœŸœ4˜JšŸœŸœŸœ˜JšœJ˜JJšœŸœ˜,šœ6Ÿœ˜HJšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšœ Ÿœ˜#Jšœh˜hJšœh˜hJšœ%Ÿœœ˜?———J˜—– "Cedar" styleš œŸœ.˜C– "Cedar" stylešŸœ ŸœŸœ˜$š ŸœŸœŸœ4ŸœŸœŸœ˜UJšŸœŸœŸœ˜%š ŸœŸœŸœ5ŸœŸœŸœ˜XJš ŸœŸœŸœŸœŸœŸœ˜=———J– "Cedar" style˜—– "Cedar" styleš œŸœŸœ4˜VJ– "Cedar" stylešŸœ ŸœŸœ˜$JšŸœŸœG™SJšœŸœ˜3š ŸœŸœŸœ4ŸœŸœŸœ˜UJšŸœŸœŸœ˜$š ŸœŸœŸœ5ŸœŸœŸœ˜XšœŸœ˜%JšœŸœ;˜B—JšŸœŸœ%Ÿ˜1Jš ŸœŸœŸœŸœŸœŸœ˜=——J˜—– "Cedar" styleš  œŸœ"Ÿœ ˜?J– "Cedar" stylešŸœ˜J– "Cedar" stylešœ ŸœŸœK˜pJ˜—– "Cedar" styleš œŸ˜ – "Cedar" stylešœŸœ ŸœŸœ&˜WJ– "Cedar" stylešŸœ˜&—– "Cedar" stylešœ,Ÿœ˜EJ– "Cedar" stylešœ-˜-—J– "Cedar" stylešœ˜– "Cedar" stylešœ˜J– "Cedar" stylešœK˜K—J˜—– "Cedar" styleš œŸœŸœ Ÿœ˜KJ– "Cedar" stylešŸœŸœ˜Jš œŸœŸœ Ÿœ˜FJšœŸœ1˜YJšŸœŸœŸœ !˜[J˜—– "Cedar" styleš  œŸ˜– "Cedar" stylešœŸœA˜LJ– "Cedar" stylešŸœŸœ˜)—– "Cedar" styleš œ˜ JšœŸœ Ÿœ˜7JšœŸœ ˜(JšœŸœ ˜(Jšœ Ÿœ!˜.Jšœ Ÿœ!˜.J– "Cedar" stylešœŸœŸœ˜5J– "Cedar" stylešœŸœŸœ˜4J– "Cedar" styleš Ÿœ ŸœŸœŸœ Ÿœ˜E—JšœŸœŸœ*˜VJšœI˜IJšœŸœ˜%šŸœ'Ÿœ˜.JšŸœ4˜6—J˜—š œŸœŸœŸœ˜IšœŸœŸ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜JšŸœŸœ-˜:—J˜—š   œŸœŸœ ŸœŸœ Ÿœ˜fJšœ>™>Jš  œŸœŸœ ŸœŸœ˜XJšœŸœ#˜0JšŸœŸœŸœ˜3JšŸœŸœŸœ˜3JšŸœŸœŸœ4˜DJ˜—š  œŸœ!Ÿœ Ÿœ˜XJšœ"™"JšœŸœ˜ šŸœŸœŸ˜šœ˜šŸœ˜JšŸœ'˜+JšŸœ(˜,——šœ˜JšœR˜RšœŸœ˜%JšœŸœ3˜:—Jšœ-˜-—JšŸœŸœ/˜<—JšŸœ ˜J˜—š  œŸœŸœ˜DJšœ™J˜JšœŸœ˜ šŸœŸœŸ˜Jšœ@˜@šœ˜JšœR˜RJšœŸœ˜(šœŸœ˜%JšœŸœ3˜:—šŸœ˜JšŸœ˜JšŸœ˜!——JšŸœŸœ/˜?—JšŸœ ˜J˜—š  œŸœŸœŸœŸœŸœ ˜LšŸœŸœŸ˜Jšœ˜Jšœ˜JšŸœ˜ —J˜—š œŸœŸœ&Ÿœ˜OJšŸœ ŸœŸœ2˜WJš œŸœ ŸœŸœ Ÿœ ˜BJšŸœ ŸœŸœ Ÿœ˜4J˜—š   œŸœŸœ Ÿœ ŸœŸœ˜LšŸœŸœŸ˜JšŸœŸœŸœŸœ˜'Jšœ˜JšŸœ˜—JšŸœŸœ˜J˜—– "Cedar" styleš  œŸœŸœŸœ ˜QJšœ"˜"Jšœ*˜*Jšœ Ÿœ.˜9JšœQ˜QJ˜—š  œŸœŸœŸœ ˜MJšœŸœ˜Jšœ0˜0Jšœ0˜0JšœŸœŸœŸœ˜.JšœŸœŸœŸœ˜.JšœŸœ5˜?šœŸœ˜,JšŸœŸœ˜,šŸœŸœ˜JšŸœŸœ#˜,JšŸœŸœŸœ˜0——Jšœ/˜/J˜—J– "Cedar" stylešŸœ˜——…—8˜O6