DIRECTORY Asserting, Basics, Convert, IO, OrderedSymbolTableRef, PrincOps, PrincOpsUtils, Rope, RoseCreate, RoseEvents, RoseIOHacks, RoseRun, RoseTypes; RoseCreateImpl: CEDAR PROGRAM IMPORTS Asserting, Convert, IO, OSTR: OrderedSymbolTableRef, PrincOpsUtils, Rope, RoseCreate, RoseEvents, RoseIOHacks, RoseRun, RoseTypes EXPORTS RoseCreate, RoseTypes = BEGIN OPEN RoseCreate, RoseTypes; cellTypes: SymbolTable _ OSTR.CreateTable[CompareCellTypes]; roots: PUBLIC SymbolTable _ OSTR.CreateTable[CompareComponents]; bogosityKey: ATOM = $bogosityKey; survey: ERClass _ NEW [ERClassRep _ [ CellInstance: SurveyCellInstance, NodeInstance: NodeInstance, Equivalence: Equivalence ]]; EqualInterfaces: PUBLIC PROC [a, b: Ports] RETURNS [structurally, fully: BOOL] = { structurally _ fully _ a.length = b.length; FOR portIndex: PortIndex IN [0 .. a.length) WHILE structurally DO IF NOT ( Conforming[a[portIndex].type, b[portIndex].type] AND a[portIndex].input = b[portIndex].input AND a[portIndex].output = b[portIndex].output AND a[portIndex].name.Equal[b[portIndex].name] ) THEN structurally _ fully _ FALSE; IF NOT ( FieldEqual[a[portIndex].simple, b[portIndex].simple] AND FieldEqual[a[portIndex].switch, b[portIndex].switch] AND a[portIndex].type = b[portIndex].type AND a[portIndex].XPhobic = b[portIndex].XPhobic ) THEN fully _ FALSE; ENDLOOP; }; MinSize: PROC [f: Field] RETURNS [words: CARDINAL] = { words _ WITH f SELECT FROM word => firstWord + wordCount, bit => wordOffset + (bitOffset + bitCount + Basics.bitsPerWord - 1)/Basics.bitsPerWord, ENDCASE => ERROR; }; FieldEqual: PROC [f1, f2: Field] RETURNS [eq: BOOL] = {eq _ Bitten[f1] = Bitten[f2]}; Bitten: PROC [f: Field] RETURNS [b0, db: CARDINAL] = { WITH x: f SELECT FROM bit => RETURN [x.wordOffset*Basics.bitsPerWord+x.bitOffset, x.bitCount]; word => RETURN [x.firstWord*Basics.bitsPerWord, x.wordCount*Basics.bitsPerWord]; ENDCASE => ERROR; }; RegisterCellType: PUBLIC PROC [ incrementally: BOOL _ FALSE, name: ROPE, expandProc: ExpandProc _ NIL, ioCreator: IOCreator _ NIL, driveCreator: DriveCreator _ NIL, initializer: Initializer _ NIL, evals: EvalProcs _ [], tests: CellTestList _ NIL, ports: Ports, typeData: REF ANY _ NIL, other: Assertions _ NIL ] RETURNS [type: CellType] = BEGIN replace: BOOL = NOT incrementally; conformingInterface, equalInterface: BOOL _ FALSE; oldHadBehavior: BOOL _ FALSE; newHasBehavior: BOOL _ evals.EvalSimple # NIL OR evals.PropUD # NIL; simpleWordCount, switchWordCount: CARDINAL _ 0; hasASwitchPort: BOOL _ FALSE; FOR portIndex: PortIndex IN [0 .. ports.length) DO port: Port _ ports[portIndex]; simpleWordCount _ MAX[simpleWordCount, MinSize[port.simple]]; switchWordCount _ MAX[switchWordCount, MinSize[port.switch]]; IF port.type = NIL THEN ERROR Error[IO.PutFR["No NodeType given for Port %g", IO.rope[port.name]]]; IF NOT port.type.simple THEN hasASwitchPort _ TRUE; ENDLOOP; type _ NARROW[cellTypes.Lookup[name]]; IF type = NIL THEN { type _ NEW [CellTypeRep _ [name: name, testers: OSTR.CreateTable[CompareTests]]]; cellTypes.Insert[type]; } ELSE { [conformingInterface, equalInterface] _ EqualInterfaces[ports, type.ports]; oldHadBehavior _ type.evals.EvalSimple # NIL OR type.evals.PropUD # NIL; }; IF type.firstInstance # NIL THEN { firstLeaf: BOOL _ TRUE; IF NOT incrementally THEN ERROR Error["Can't forget about instances", type]; IF NOT conformingInterface THEN ERROR Error["Can't change interface structure of existing instances", type]; FOR instance: Cell _ type.firstInstance, instance.nextInstance WHILE instance # NIL DO IF instance.type # type THEN ERROR; IF instance.expansion = Leaf THEN { IF firstLeaf THEN { firstLeaf _ FALSE; IF NOT oldHadBehavior THEN ERROR; IF NOT newHasBehavior THEN ERROR Error["Can't relieve existing instances of behavior", type]; IF NOT equalInterface THEN ERROR Error["Can't change interface of existing instances", type]; }; IF instance.realCellStuff.evals # type.evals THEN ERROR; instance.realCellStuff.evals _ evals; }; ENDLOOP; }; type.ports _ ports; IF NOT equalInterface THEN { type.simpleWordCount _ simpleWordCount; type.switchWordCount _ switchWordCount; type.hasASwitchPort _ hasASwitchPort; }; IF replace OR expandProc # NIL THEN type.expand _ expandProc; IF replace OR ioCreator # NIL THEN type.ioCreator _ ioCreator; IF replace OR driveCreator # NIL THEN type.driveCreator _ driveCreator; IF replace OR initializer # NIL THEN type.initializer _ initializer; IF replace OR evals # [] THEN type.evals _ evals; IF replace OR typeData # NIL THEN type.typeData _ typeData; IF incrementally THEN type.other _ Asserting.Union[other, type.other] ELSE type.other _ other; IF NOT incrementally THEN type.testers.DeleteAllItems[]; FOR tests _ tests, tests.rest WHILE tests # NIL DO [] _ SetTest[test: NEW [CellTestRep _ tests.first], of: type, mayOverwriteOld: incrementally]; ENDLOOP; END; GetCellType: PUBLIC PROC [name: ROPE] RETURNS [type: CellType] = {type _ NARROW[cellTypes.Lookup[name]]}; GetTest: PUBLIC PROC [name: ROPE, from: CellType] RETURNS [t: CellTest] = {t _ NARROW[from.testers.Lookup[name]]}; SetTest: PUBLIC PROC [test: CellTest, of: CellType, mayOverwriteOld: BOOL _ FALSE] RETURNS [old: CellTest] = { old _ NARROW[of.testers.Lookup[test]]; IF old # NIL THEN { IF mayOverwriteOld THEN {IF of.testers.Delete[test] # old THEN ERROR} ELSE ERROR Error[IO.PutFR["Duplicate Test (named %g) given for cell type %g", IO.rope[test.name], IO.rope[of.name]]]; }; of.testers.Insert[test]; }; CreateSim: PUBLIC PROC [steady: BOOL] RETURNS [sim: Simulation] = { sim _ NEW [SimulationRep _ [steady: steady]]; RoseEvents.Notify[event: $NewSim, arg: sim]; }; CreateTopCell: PUBLIC PROC [instanceName, typeName: ROPE, decider: ExpandDeciderClosure, sim: Simulation] = BEGIN bbTableSpace: PrincOps.BBTableSpace; bbTable: PrincOps.BitBltTablePtr; FinishLinkingCell: PROC [item: REF ANY] RETURNS [stop: BOOL] = BEGIN cell: Cell _ NARROW[item]; type: CellType _ cell.type; stop _ FALSE; SELECT cell.expansion FROM Expand => { cell.internalNodes.EnumerateIncreasing[OptimizePieces]; cell.components.EnumerateIncreasing[FinishLinkingCell]; }; Leaf => { [cell.realCellStuff.effectivePorts, cell.realCellStuff.implNodes] _ EffectiveInterface[cell]; FOR epi: EffectivePortIndex IN [0 .. cell.realCellStuff.effectivePorts.length) DO ep: EffectivePort _ cell.realCellStuff.effectivePorts[epi]; targType: NodeType _ ep.implType; node: Node _ cell.realCellStuff.implNodes[epi]; portPtr: Ptr _ SlotToPtr[[cell, epi], NOT targType.simple]; IF targType.procs.InitPort # NIL THEN targType.procs.InitPort[node, portPtr]; RoseIOHacks.Copy[from: node.valPtr, to: portPtr, bitCount: node.bitCount, bbTable: bbTable]; IF Transduced[ep] THEN { modelPtr: Ptr _ SlotToPtr[[cell, epi], NOT ep.type.simple]; targType.procs.Transduce[ fromT: targType, toT: ep.type, fromP: portPtr, toP: modelPtr]; }; ENDLOOP; IF type.initializer # NIL THEN type.initializer[cell: cell]; }; ENDCASE => ERROR; END; type: CellType; TRUSTED {bbTable _ PrincOpsUtils.AlignedBBTable[@bbTableSpace]}; type _ NARROW[cellTypes.Lookup[typeName]]; IF type = NIL THEN ERROR Error[IO.PutFR["No such type: %g", IO.rope[typeName]]]; sim.root _ NEW [CellRep _ [ name: instanceName, type: type, sim: sim, parent: NIL, leftChild: NIL, rightSibling: NIL, firstInternalNode: NIL, internalNodes: OSTR.CreateTable[CompareNodes], components: OSTR.CreateTable[CompareComponents], interfaceNodes: NEW [NodeSR[0]], other: Asserting.AssertFn1[$ExpandDeciderClosure, decider, NIL], substantiality: Shadow, expansion: Expand, realCellStuff: NIL]]; FinishSurveyingCell[sim.root, NIL]; [] _ FinishLinkingCell[sim.root]; END; LevelList: TYPE = LIST OF Level; Level: TYPE = RECORD [ s: Selector, pl: PieceList]; OptimizePieces: PROC [item: REF ANY] RETURNS [stop: BOOL] = { n: Node _ NARROW[item]; Optimize: PROC [ll: LevelList] RETURNS [opt: PieceList] = { FOR ll _ ll, ll.rest WHILE ll # NIL AND ll.first.pl = NIL DO NULL ENDLOOP; IF ll = NIL THEN opt _ NIL ELSE { in: Node _ ll.first.pl.first.twardImpl; s: Selector _ Compose[ll.first.s, ll.first.pl.first.reln]; ll.first.pl _ ll.first.pl.rest; IF in.significances[inImpl] THEN { p: Piece _ [n, in, s]; in.parentPieces _ CONS[p, in.parentPieces]; opt _ CONS[p, Optimize[ll]]; } ELSE { IF in.significances[fromDesign] THEN ERROR; IF in.childPieces = NIL THEN ERROR; opt _ Optimize[CONS[[s, in.childPieces], ll]]; }; }; }; stop _ FALSE; IF NOT n.significances[fromDesign] THEN ERROR; n.childPieces _ Optimize[LIST[[[whole[]], n.childPieces]]]; }; EffectiveInterface: PROC [cell: Cell] RETURNS [effectivePorts: EffectivePorts, implNodes: NodeS] = { n: CARDINAL _ 0; FOR pi: PortIndex IN [0 .. cell.type.ports.length) DO node: Node _ cell.interfaceNodes[pi]; IF node.significances[inImpl] THEN n _ n + 1 ELSE { FOR pl: PieceList _ Implify[node.childPieces], Implify[pl.rest] WHILE pl # NIL DO n _ n + 1; ENDLOOP; }; ENDLOOP; effectivePorts _ NEW [EffectivePortsRep[n]]; implNodes _ NEW [NodeSR[n]]; n _ 0; FOR pi: PortIndex IN [0 .. cell.type.ports.length) DO node: Node _ cell.interfaceNodes[pi]; port: Port _ cell.type.ports[pi]; children: PieceList _ IF node.childPieces # NIL THEN node.childPieces ELSE LIST[[node, node, [whole[]]]]; firstEffectivePortIndex: EffectivePortIndex _ n; FOR pl: PieceList _ Implify[children], Implify[pl.rest] WHILE pl # NIL DO implNode: Node _ pl.first.twardImpl; mod: ROPE _ SelectorToRope[pl.first.reln]; effectivePorts[n] _ [ simple: port.simple, switch: port.switch, name: port.name.Cat[mod], type: port.type, input: port.input, output: port.output, XPhobic: port.XPhobic, other: port.other, implType: implNode.type, containingPort: pi ]; implNodes[n] _ pl.first.twardImpl; n _ n + 1; ENDLOOP; effectivePorts[pi].firstEffectivePortIndex _ firstEffectivePortIndex; ENDLOOP; IF n # implNodes.length THEN ERROR; }; SurveyCellInstance: PROC [erInstance: REF ANY, instanceName, typeName, interfaceNodes: ROPE, other: Assertions _ NIL] RETURNS [cell: Cell] = BEGIN within: Cell _ NARROW[erInstance]; type: CellType; type _ NARROW[cellTypes.Lookup[typeName]]; IF type = NIL THEN ERROR Error[IO.PutFR["No such type: %g", IO.rope[typeName]]]; IF within = NIL THEN ERROR; cell _ NEW [CellRep _ [ name: instanceName, type: type, sim: within.sim, parent: within, leftChild: NIL, rightSibling: NIL, firstInternalNode: NIL, internalNodes: OSTR.CreateTable[CompareNodes], components: OSTR.CreateTable[CompareComponents], interfaceNodes: NEW [NodeSR[type.ports.length]], other: other, substantiality: Shadow, expansion: Expand, realCellStuff: NIL]]; FinishSurveyingCell[cell, interfaceNodes]; END; FinishSurveyingCell: PROC [cell: Cell, interfaceNodes: ROPE] = BEGIN type: CellType _ cell.type; thisChild, lastChild: Cell; thisNode, lastNode: Node; IF cell.parent = NIL THEN { IF type.ports.length > 0 THEN ERROR Error["Can't make root with non-empty interface", cell]; } ELSE { cell.parent.components.Insert[cell !OSTR.DuplicateKey => ERROR Error[IO.PutFR["Duplicated Cell name: %g", IO.rope[cell.name]]]]; cell.rightSibling _ cell.parent.leftChild; cell.parent.leftChild _ cell; }; cell.nextInstance _ type.firstInstance; type.firstInstance _ cell; FillInInterfaceNodes[cell, interfaceNodes]; cell.expansion _ FindAndUseExpandDecider[cell]; SELECT cell.expansion FROM Expand => BEGIN cell.substantiality _ Shadow; cell.realCellStuff _ NIL; type.expand[thisCell: cell, to: [cell, survey]]; END; Leaf => BEGIN cell.substantiality _ Real; cell.realCellStuff _ NEW [RealCellStuffRep _ [ effectivePorts: NIL, implNodes: NIL, schedNext: notInCellList, nextNeeded: notInCellList, nextNoted: notInCellList, newIO: NIL, oldIO: NIL, switchIO: NIL, newDriveAsAny: NIL, oldDriveAsAny: NIL, newIOAsWP: NIL, oldIOAsWP: NIL, switchIOAsWP: NIL, newDrive: NIL, oldDrive: NIL, state: NIL, evals: type.evals]]; FOR portIndex: PortIndex IN [0..type.ports.length) DO node: Node _ cell.interfaceNodes[portIndex]; targType: NodeType _ cell.type.ports[portIndex].type; IF cell.type.ports[portIndex].XPhobic THEN node.XPhobic _ TRUE; ENDLOOP; IF type.ioCreator # NIL THEN { cell.realCellStuff.newIO _ type.ioCreator[ct: type, switch: FALSE]; cell.realCellStuff.oldIO _ type.ioCreator[ct: type, switch: FALSE]; cell.realCellStuff.newDriveAsAny _ type.driveCreator[ct: type]; cell.realCellStuff.oldDriveAsAny _ type.driveCreator[ct: type]; IF type.hasASwitchPort OR cell.realCellStuff.hasTransducedPort THEN cell.realCellStuff.switchIO _ type.ioCreator[ct: type, switch: TRUE]; } ELSE IF type.simpleWordCount > 0 OR type.switchWordCount > 0 THEN ERROR Error[IO.PutFR["No IOCreator for type %g", IO.rope[type.name]]]; cell.realCellStuff.newIOAsWP _ LOOPHOLE[cell.realCellStuff.newIO]; cell.realCellStuff.oldIOAsWP _ LOOPHOLE[cell.realCellStuff.oldIO]; cell.realCellStuff.switchIOAsWP _ LOOPHOLE[cell.realCellStuff.switchIO]; TRUSTED { cell.realCellStuff.newDrive _ LOOPHOLE[cell.realCellStuff.newDriveAsAny]; cell.realCellStuff.oldDrive _ LOOPHOLE[cell.realCellStuff.oldDriveAsAny]; }; END; ENDCASE => ERROR; lastChild _ NIL; thisChild _ cell.leftChild; WHILE thisChild # NIL DO nextChild: Cell _ thisChild.rightSibling; thisChild.rightSibling _ lastChild; lastChild _ thisChild; thisChild _ nextChild; ENDLOOP; cell.leftChild _ lastChild; lastNode _ NIL; thisNode _ cell.firstInternalNode; WHILE thisNode # NIL DO nextNode: Node _ thisNode.next; thisNode.next _ lastNode; lastNode _ thisNode; thisNode _ nextNode; ENDLOOP; cell.firstInternalNode _ lastNode; IF cell.parent = NIL THEN roots.Insert[cell !OSTR.DuplicateKey => ERROR Error[IO.PutFR["Duplicated Root name: %g", IO.rope[cell.name]]]] ELSE IF cell.substantiality = Real THEN RoseRun.ScheduleCell[cell]; END; GetName: PROC [from: IO.STREAM] RETURNS [name: ROPE] = { first: CHAR _ from.PeekChar[]; SELECT first FROM '" => name _ from.GetRopeLiteral[]; ENDCASE => name _ from.GetTokenRope[IDBreak].token; }; IDBreak: IO.BreakProc = {RETURN [SELECT char FROM IO.SP, IO.CR, IO.LF, IO.TAB => sepr, ',, ': => break, ENDCASE => other]}; FillInInterfaceNodes: PUBLIC PROC [cell: Cell, interfaceNodes: ROPE] = BEGIN index: CARDINAL _ 0; in: IO.STREAM _ IO.RIS[interfaceNodes]; [] _ in.GetIndex[]; --wake up generic GetIndex impl FOR i: NAT _ in.SkipWhitespace[], in.SkipWhitespace[] WHILE NOT in.EndOf[] DO nodeName: ROPE _ GetName[in]; portName: ROPE; portIndex: PortIndex; [] _ in.SkipWhitespace[]; IF (NOT in.EndOf[]) AND (in.PeekChar[] = ':) THEN BEGIN portName _ nodeName; IF in.GetChar[] # ': THEN ERROR; [] _ in.SkipWhitespace[]; IF in.EndOf[] THEN ERROR Error[IO.PutFR["Interface spec syntax error, at %g", IO.int[in.GetIndex[]]]]; nodeName _ GetName[in]; IF (portIndex _ GetIndex[cell.type.ports, portName]) = notFound THEN ERROR Error[IO.PutFR["No such port (%g) for CellType %g", IO.rope[portName], IO.rope[cell.type.name]]]; END ELSE BEGIN IF index >= cell.interfaceNodes.length THEN ERROR Error[IO.PutFR["No %g'th element in %g's Interface", IO.int[index], IO.rope[cell.type.name]]]; portName _ cell.type.ports[portIndex _ index].name; END; IF cell.interfaceNodes[portIndex] # NIL THEN ERROR Error[IO.PutFR["Port %g specified twice in \"%g\"", IO.rope[portName], IO.rope[interfaceNodes]]]; cell.interfaceNodes[portIndex] _ LookupCellNode[cell.parent, nodeName]; IF cell.interfaceNodes[portIndex] = NIL THEN ERROR Error[IO.PutFR["Node %g not found", IO.rope[nodeName]]]; IF NOT Conforming[cell.interfaceNodes[portIndex].type, cell.type.ports[portIndex].type] THEN ERROR InterfaceMismatch[ cell: cell, index: portIndex, expected: cell.type.ports[portIndex].type, got: cell.interfaceNodes[portIndex].type]; index _ index + 1; [] _ in.SkipWhitespace[]; IF in.EndOf[] THEN EXIT; IF in.GetChar[] # ', THEN ERROR Error[IO.PutFR["Interface spec syntax error (missing comma), at %g", IO.int[in.GetIndex[]]]]; ENDLOOP; FOR portIndex: PortIndex IN [0 .. cell.interfaceNodes.length) DO IF cell.interfaceNodes[portIndex] = NIL THEN BEGIN nodeName: ROPE _ cell.type.ports[portIndex].name; cell.interfaceNodes[portIndex] _ LookupCellNode[cell.parent, nodeName]; IF cell.interfaceNodes[portIndex] = NIL THEN ERROR Error[IO.PutFR["Port %g not specified in \"%g\"", IO.rope[nodeName], IO.rope[interfaceNodes]]]; END; ENDLOOP; in.Close[]; END; GetIndex: PUBLIC PROC [ports: Ports, key: ROPE] RETURNS [index: CARDINAL] = BEGIN FOR i: CARDINAL IN [0..ports.length) DO IF key.Equal[ports[i].name] THEN RETURN [i]; ENDLOOP; RETURN [notFound]; END; NumberOfExpandDecisions: INTEGER = (ORD[LAST[ExpandDecision]] - ORD[FIRST[ExpandDecision]]) + 1; FindAndUseExpandDecider: PROC [cell: Cell] RETURNS [ExpandDecision] = BEGIN ed: ExpandDecision; possibilities: [0 .. NumberOfExpandDecisions]; [ed, possibilities] _ PickOne[cell]; IF possibilities = 1 THEN RETURN [ed]; IF possibilities = 0 THEN ERROR Error[IO.PutFR["Can't do anything with type %g", IO.rope[cell.type.name]]]; FOR temp: Cell _ cell, temp.parent WHILE temp # NIL DO asAny: REF ANY _ Asserting.FnVal[$ExpandDeciderClosure, temp.other]; edc: ExpandDeciderClosure; try: ExpandDecision; IF asAny = NIL THEN LOOP; edc _ NARROW[asAny]; try _ edc.Decide[cell, edc.otherData]; IF Possible[cell, try] THEN RETURN [try]; ENDLOOP; RETURN [ed]; END; PickOne: PROC [cell: Cell] RETURNS [whatToDo: ExpandDecision, possibilities: [0..3]] = BEGIN possibilities _ 0; FOR i: [1..NumberOfExpandDecisions] IN [1..NumberOfExpandDecisions] DO d: ExpandDecision _ orderedChoices[i]; IF Possible[cell, d] THEN {whatToDo _ d; possibilities _ possibilities + 1}; ENDLOOP; END; orderedChoices: ARRAY [1..2] OF ExpandDecision = [Leaf, Expand]; Possible: PUBLIC PROC [cell: Cell, whatToDo: ExpandDecision] RETURNS [possible: BOOLEAN] = BEGIN evalable: BOOL _ cell.type.evals.EvalSimple # NIL OR cell.type.evals.PropUD # NIL; iok: BOOL _ (cell.type.simpleWordCount = 0 AND cell.type.switchWordCount = 0) OR cell.type.ioCreator # NIL; RETURN [SELECT whatToDo FROM Leaf => evalable AND iok, Expand => cell.type.expand # NIL, ENDCASE => ERROR]; END; XPhobicize: PUBLIC PROC [n: Node] RETURNS [m: Node-- = n --] = {(m _ n).XPhobic _ TRUE}; Words: TYPE = REF WordSeq; WordSeq: TYPE = RECORD [words: SEQUENCE length: CARDINAL OF CARDINAL]; NodeInstance: PROC [erInstance: REF ANY, name: ROPE, type: NodeType, initialValue, initialValueFormat: ROPE _ NIL, initData: REF ANY _ NIL, other: Assertions _ NIL] RETURNS [node: Node] = { cellIn: Cell _ NARROW[erInstance]; node _ CreateNode[strIn: CellToStr[cellIn], cellIn: cellIn, name: name, type: type, initialValue: initialValue, initialValueFormat: initialValueFormat, initData: initData, other: other, significance: fromDesign]}; CreateNode: PROC [strIn: Structure, cellIn: Cell, name: ROPE, type: NodeType, initialValue, initialValueFormat: ROPE _ NIL, initData: REF ANY _ NIL, other: Assertions _ NIL, significance: NodeSignificance] RETURNS [node: Node] = BEGIN bitCount: NAT _ type.procs.Bits[type]; wordCount: NAT _ (bitCount + Basics.bitsPerWord - 1)/Basics.bitsPerWord; val: Words _ NEW [WordSeq[wordCount]]; sigs: NodeSignificances _ implOnly; sigs[significance] _ TRUE; node _ NEW [NodeRep _ [ name: name, type: type, valRef: val, valPtr: nilPtr, bitCount: bitCount, initialValue: initialValue, initialValueFormat: type.procs.GetFormat[type, initialValueFormat], cellIn: cellIn, strIn: strIn, nextPerturbed: notInNodeList, nextAffected: notInNodeList, nextX: notInNodeList, prevX: notInNodeList, significances: sigs, next: NIL, parentPieces: NIL--fill in later, in OptimizePieces--, other: other ]]; TRUSTED {node.valPtr _ [word: @val[0], bit: 0]}; IF node.initialValueFormat = NIL THEN ERROR Error[IO.PutFR["Bad initialValueFormat %g for %g", IO.rope[initialValueFormat], IO.rope[name]]]; SELECT significance FROM fromDesign => { cellIn.internalNodes.Insert[node !OSTR.DuplicateKey => ERROR Error[IO.PutFR["Duplicated Node name: %g", IO.rope[name]]]]; node.next _ cellIn.firstInternalNode; cellIn.firstInternalNode _ node; }; inImpl => NULL; ENDCASE => ERROR; IF type.procs.InitNode # NIL THEN type.procs.InitNode[node, initData, strIn.sim.steady]; IF initialValue # NIL THEN { valStream: IO.STREAM _ IO.RIS[node.initialValue]; ok: BOOL _ node.initialValueFormat.ParseValue[node, node.initialValueFormat, node.valPtr, valStream]; [] _ valStream.SkipWhitespace[]; IF NOT (ok AND valStream.EndOf[]) THEN SIGNAL Warning[IO.PutFR[ "Unable to parse %g by format (%g) for node %g (of type %g)", IO.rope[Convert.RopeFromRope[node.initialValue]], IO.rope[initialValueFormat], IO.rope[node.name], IO.rope[node.type.procs.UserDescription[node.type]]]]; }; IF NOT type.simple THEN RoseRun.PerturbNode[node, NIL]; END; Equivalence: PROC [erInstance: REF ANY, a, b: NodeExpression] = BEGIN within: Cell _ NARROW[erInstance]; la, lb: NodeList; la _ ToNodes[a, NIL]; lb _ ToNodes[b, NIL]; EquivNodeLists[la, lb]; END; ToNodes: PROC [ne: NodeExpression, tail: NodeList] RETURNS [l: NodeList] = { l _ tail; WITH ne SELECT FROM x: PrimaryNE => { IF x.node.childPieces = NIL AND NOT x.node.significances[inImpl] THEN ERROR; IF x.node.significances[inImpl] THEN l _ CONS[SelectNode[x.node, x.selector].at, l] ELSE l _ Select[x.node.childPieces, x.selector, l]; }; x: UnnamedConsNE => { FOR i: INT DECREASING IN [0 .. x.length) DO l _ ToNodes[x.elts[i], l]; ENDLOOP; }; x: CatenateNE => { FOR i: INT DECREASING IN [0 .. x.length) DO l _ ToNodes[x.pieces[i], l]; ENDLOOP; }; ENDCASE => ERROR; }; Select: PROC [pl: PieceList, s: Selector, tail: NodeList] RETURNS [ol: NodeList] = { first, count, direction, last, min, max: INT; up: BOOL; endPiece: PieceList; prevList, el: NodeList _ NIL; firstSize, endSize: INT; [first, count, up] _ StandardSelectorRep[s, PieceListLength[pl]]; IF count < 2 THEN up _ TRUE; direction _ UpToInt[up]; IF NOT up THEN ERROR--lazy implementor--; last _ first + (count-1)*direction; min _ MIN[first, last]; max _ MAX[first, last]; DO pl _ Implify[pl]; firstSize _ NodeLength[pl.first.twardImpl]; IF min < firstSize THEN EXIT; min _ min - firstSize; max _ max - firstSize; pl _ pl.rest; ENDLOOP; endPiece _ pl; DO endPiece _ Implify[endPiece]; el _ LIST[endPiece.first.twardImpl]; endSize _ NodeLength[endPiece.first.twardImpl]; IF prevList = NIL THEN ol _ el ELSE prevList.rest _ el; IF max < endSize THEN EXIT; max _ max - endSize; prevList _ el; endPiece _ endPiece.rest; ENDLOOP; el.rest _ tail; IF min > 0 OR max+1 < endSize THEN { IF ol = el THEN ol.first _ SelectNode[ol.first, [range[min, 1+max-min, TRUE]]].at ELSE { IF min > 0 THEN ol.first _ SelectNode[ol.first, [range[min, firstSize-min, TRUE]]].at; IF max+1 < endSize THEN el.first _ SelectNode[el.first, [range[0, max+1, TRUE]]].at; }; }; }; UpToInt: ARRAY BOOL OF INT = [FALSE: -1, TRUE: 1]; Implify: PROC [il: PieceList, tail: PieceList _ NIL] RETURNS [ol: PieceList] = { Append: PROC [l1, l2: PieceList] RETURNS [l: PieceList] = { IF l2 = NIL THEN RETURN [l1]; IF l1 = NIL THEN RETURN [l2]; l _ CONS[l1.first, Append[l1.rest, l2]]}; IF il.first.twardImpl.significances[inImpl] THEN RETURN [Append[il, tail]]; IF il.first.twardImpl.significances[fromDesign] THEN ERROR; ol _ Append[Implify[il.first.twardImpl.childPieces, il.rest], tail]; }; EquivNodeLists: PROC [a, b: NodeList] = { Munch: PROC [pl: PieceList, nl: NodeList] RETURNS [ans: NodeList] = { IF pl = NIL THEN RETURN [nl]; ans _ CONS[pl.first.twardImpl, Munch[pl.rest, nl]]; }; WHILE a#NIL AND b#NIL DO na, nb: Node; la, lb: INT; WHILE NOT a.first.significances[inImpl] DO a _ Munch[a.first.childPieces, a.rest] ENDLOOP; WHILE NOT b.first.significances[inImpl] DO b _ Munch[b.first.childPieces, b.rest] ENDLOOP; la _ NodeLength[na _ a.first]; lb _ NodeLength[nb _ b.first]; IF la = lb THEN { JoinNodes[na, nb]; a _ a.rest; b _ b.rest; } ELSE IF la < lb THEN { before, at, rest: Node; [before: before, at: at, after: rest] _ SelectNode[nb, [range[0, la, TRUE]]]; IF before # NIL THEN ERROR; JoinNodes[na, at]; a _ a.rest; b.first _ rest; } ELSE IF lb < la THEN { before, at, rest: Node; [before: before, at: at, after: rest] _ SelectNode[na, [range[0, lb, TRUE]]]; IF before # NIL THEN ERROR; JoinNodes[nb, at]; b _ b.rest; a.first _ rest; } ELSE ERROR; ENDLOOP; IF a#NIL OR b#NIL THEN ERROR Error["Non-corresponding node expressions equivalenced"]; }; StandardSelectorRep: PROC [s: Selector, len: INT _ -1] RETURNS [first, count: INT, up: BOOL] = { WITH x: s SELECT FROM whole => {first _ 0; count _ len; up _ TRUE}; number => {first _ x.index; count _ 1; up _ TRUE}; range => {first _ x.first; count _ x.count; up _ x.up}; ENDCASE => ERROR; }; SelectNode: PROC [n: Node, s: Selector] RETURNS [before, at, after: Node] = { first, count: INT; up: BOOL; nl: INT _ NodeLength[n]; firstSel, lastSel: Selector.range; Add: PROC [in: Node, s: Selector] = { n.childPieces _ CONS[[n, in, s], n.childPieces]; }; First: PROC = { IF first > 0 THEN { firstSel _ [range[0, first, TRUE]]; before _ CreateNode[ strIn: n.strIn, cellIn: NIL, name: IO.PutFR["%g%g", IO.rope[n.name], IO.rope[SelectorToRope[firstSel]]], type: n.type.procs.SubType[n.type, firstSel], significance: inImpl ]; Add[before, firstSel]; } ELSE before _ NIL; }; Mid: PROC = { at _ CreateNode[ strIn: n.strIn, cellIn: NIL, name: IO.PutFR["%g%g", IO.rope[n.name], IO.rope[SelectorToRope[s]]], type: n.type.procs.SubType[n.type, s], significance: inImpl ]; Add[at, s]; }; Last: PROC = { IF first + count < nl THEN { lastSel _ [range[first + count, nl - (first + count), TRUE]]; after _ CreateNode[ strIn: n.strIn, cellIn: NIL, name: IO.PutFR["%g%g", IO.rope[n.name], IO.rope[SelectorToRope[lastSel]]], type: n.type.procs.SubType[n.type, lastSel], significance: inImpl ]; Add[after, lastSel]; } ELSE after _ NIL; }; IF NOT n.significances[inImpl] THEN ERROR; IF n.childPieces # NIL THEN ERROR; IF s = [whole[]] THEN RETURN [NIL, n, NIL]; [first, count, up] _ StandardSelectorRep[s]; IF NOT up THEN ERROR--lazy implementor--; IF nl < count THEN ERROR; IF nl = count THEN RETURN [NIL, n, NIL]; IF up --make sure n.childPieces come out in right order-- THEN {Last[]; Mid[]; First[]} ELSE {First[]; Mid[]; Last[]}; n.significances[inImpl] _ FALSE; IF n.childPieces.rest = NIL THEN ERROR; }; JoinNodes: PROC [n1, n2: Node] = { equiv: BOOL; keep, lose: Node; IF n1.strIn # n2.strIn THEN ERROR Error[IO.PutFR["Can't equivalence nodes %g and %g because they're in different structures", IO.rope[LongNodeName[n1]], IO.rope[LongNodeName[n2]]]]; IF n1.significances[fromDesign] THEN n1 _ DummyDown[n1]; IF n2.significances[fromDesign] THEN n2 _ DummyDown[n2]; IF n1.significances # implOnly OR n2.significances # implOnly THEN ERROR; equiv _ n1.type = n2.type; IF NOT (equiv OR Conforming[n1.type, n2.type]) THEN ERROR Error[IO.PutFR["Can't equivalence nodes %g and %g because their types don't match", IO.rope[LongNodeName[n1]], IO.rope[LongNodeName[n2]]]]; IF n1.type.procs.Equivalent # NIL AND NOT equiv THEN equiv _ n1.type.procs.Equivalent[n1.type, n2.type]; IF n2.type.procs.Equivalent # NIL AND NOT equiv THEN equiv _ n2.type.procs.Equivalent[n2.type, n1.type]; IF NOT equiv THEN { ERROR --lazy implementor--; }; SELECT TRUE FROM n1.strength < n2.strength => {keep _ n2; lose _ n1}; n1.strength >= n2.strength => {keep _ n1; lose _ n2}; ENDCASE => ERROR; keep.name _ keep.name.Cat["&", lose.name]; IF keep.strength = lose.strength AND NOT RoseIOHacks.Equal[keep.valPtr, lose.valPtr, keep.bitCount] THEN ERROR; IF keep.bitCount # lose.bitCount THEN ERROR; IF keep.currentStrength # keep.strength OR lose.currentStrength # lose.strength THEN ERROR; IF keep.switchConnections # NIL OR lose.switchConnections # NIL THEN ERROR; IF keep.byStrength # ALL[emptyHead] OR lose.byStrength # ALL[emptyHead] THEN ERROR; IF keep.found OR lose.found THEN ERROR; keep.XPhobic _ keep.XPhobic OR lose.XPhobic; IF keep.watchers # ALL[NIL] OR lose.watchers # ALL[NIL] THEN ERROR; IF keep.next # NIL OR lose.next # NIL THEN ERROR; IF keep.parentPieces # NIL OR lose.parentPieces # NIL THEN ERROR; IF keep.childPieces # NIL OR lose.childPieces # NIL THEN ERROR; IF keep.other # NIL OR lose.other # NIL THEN ERROR; lose.replacedBy _ keep; }; DummyDown: PROC [dn: Node] RETURNS [in: Node] = { ERROR --lazy implementor--; }; Conforming: PROC [t1, t2: NodeType] RETURNS [c: BOOL] = { An: PROC [nt: NodeType] RETURNS [flavor: ATOM, length: INTEGER] = { WITH nt SELECT FROM x: AtomNodeType => {flavor _ x.flavor; length _ 1}; x: ArrayNodeType => {flavor _ x.element.flavor; length _ x.length}; ENDCASE => ERROR; }; c _ An[t1] = An[t2]; }; PieceListLength: PROC [pl: PieceList] RETURNS [len: INT] = { len _ 0; FOR pl _ pl, pl.rest WHILE pl # NIL DO len _ len + NodeLength[pl.first.twardImpl]; ENDLOOP; }; NodeLength: PROC [n: Node] RETURNS [l: INTEGER] = { WITH n.type SELECT FROM x: AtomNodeType => l _ 1; x: ArrayNodeType => l _ x.length; ENDCASE => ERROR; }; SelectorToRope: PROC [s: Selector] RETURNS [r: ROPE] = { r _ WITH s SELECT FROM whole => ".whole", number => IO.PutFR["[%g]", IO.int[index]], range => SELECT count FROM <1 => ERROR, =1 => IO.PutFR["[%g]", IO.int[first]], >1 => IO.PutFR["%g..%g)", IO.int[first], IO.int[first+count*UpToInt[up]]], ENDCASE => ERROR, ENDCASE => ERROR; }; Compose: PROC [s1, s2: Selector] RETURNS [s: Selector] = { xFirst, yFirst, zFirst, xCount, yCount, zCount: INTEGER; xUp, yUp, zUp, scalar: BOOL; IF s1 = [whole[]] THEN RETURN [s2]; IF s2 = [whole[]] THEN RETURN [s1]; scalar _ s1.kind = number OR s2.kind = number; [xFirst, xCount, xUp] _ StandardSelectorRep[s1]; [yFirst, yCount, yUp] _ StandardSelectorRep[s2]; zFirst _ xFirst + yFirst*UpToInt[xUp]; zCount _ yCount; zUp _ xUp = yUp; IF scalar AND zCount # 1 THEN ERROR; IF scalar THEN RETURN [[number[zFirst]]] ELSE RETURN [[range[zFirst, zCount, zUp]]]; }; CompareCellTypes: PROC [r1, r2: REF ANY] RETURNS [Basics.Comparison] --OSTR.CompareProc-- = BEGIN ToKey: SAFE PROC [ref: REF ANY] RETURNS [ROPE] = {RETURN [WITH ref SELECT FROM r: ROPE => r, ct: CellType => ct.name, ENDCASE => ERROR]}; RETURN [ToKey[r1].Compare[ToKey[r2]]]; END; CompareComponents: PUBLIC PROC [r1, r2: REF ANY] RETURNS [Basics.Comparison] --OSTR.CompareProc-- = BEGIN ToKey: SAFE PROC [ref: REF ANY] RETURNS [ROPE] = {RETURN [WITH ref SELECT FROM r: ROPE => r, c: Cell => c.name, ENDCASE => ERROR]}; RETURN [ToKey[r1].Compare[ToKey[r2]]]; END; CompareNodes: PUBLIC PROC [r1, r2: REF ANY] RETURNS [Basics.Comparison] --OSTR.CompareProc-- = BEGIN k1, k2: ROPE; WITH r1 SELECT FROM r: ROPE => k1 _ r; n: Node => k1 _ n.name; ENDCASE => ERROR; k2 _ WITH r2 SELECT FROM r: ROPE => r, n: Node => n.name, ENDCASE => ERROR; RETURN [k1.Compare[k2]]; END; CompareTests: PROC [r1, r2: REF ANY] RETURNS [Basics.Comparison] --OSTR.CompareProc-- = BEGIN ToKey: SAFE PROC [ref: REF ANY] RETURNS [ROPE] = {RETURN [WITH ref SELECT FROM r: ROPE => r, a: CellTest => a.name, ENDCASE => ERROR]}; RETURN [ToKey[r1].Compare[ToKey[r2]]]; END; END. [Indigo]r>Rosemary.DF=>RoseCreateImpl.Mesa Last Edited by: Spreitzer, April 15, 1985 11:50:54 am PST Identification: Structure: Behavior: Other: do it in wrong order for now; parent will fix up after done expanding: link in wrong order now; fix up when done expanding: Κ'– "cedar" style˜JšœΟmœ!™4J™9J˜IcodešΟk œžœp˜˜K˜šΠbxœžœž˜Kšžœžœžœe˜‰Kšžœ˜—K˜Kšžœžœ˜!K˜Kšœžœ˜Kšžœ žœžœžœ"˜GKšžœ žœžœžœ ˜DKšžœ žœ žœ˜1Kšžœ žœ žœžœ˜;šžœ˜Kšžœ0˜4Kšžœ˜—Kšžœžœžœ˜8šžœžœ žœž˜2KšœžœH˜^Kšžœ˜—Kšžœ˜—K˜š   œžœžœžœžœ˜@Kšœžœ˜(—K˜š  œžœžœžœžœ˜IKšœžœ˜(—K˜š  œžœžœ1žœžœžœ˜nKšœžœ˜&šžœžœžœ˜šžœ˜Kšžœžœžœžœ˜2Kš žœžœžœ;žœžœ˜u—K˜—Kšœ˜K˜—K˜š   œžœžœ žœžœ˜CKšœžœ$˜-Kšœ,˜,Kšœ˜—K˜š  œžœžœžœ3˜kKšž˜Kšœ$˜$Kšœ!˜!š  œžœžœžœžœžœ˜>Kšž˜Kšœ žœ˜Kšœ˜Kšœžœ˜ šžœž˜šœ ˜ Kšœ7˜7Kšœ7˜7K˜—˜ Kšœ]˜]šžœžœ1ž˜QKšœ;˜;Kšœ!˜!Kšœ/˜/Kšœ&žœ˜;Kšžœžœžœ(˜MKšœ\˜\šžœžœ˜Kšœ'žœ˜;˜K˜K˜ Kšœ˜K˜—K˜—Kšžœ˜—Kšžœžœžœ˜Kšž˜Kšœ˜K˜K˜šžœžœžœ˜Kšžœžœžœ9˜\K˜—šžœ˜Kš œ$žœžœžœ#žœ˜€šœF™FK˜*K˜—K˜—K˜'K˜K˜+Kšœ/˜/šžœž˜šœ ž˜K˜Kšœžœ˜K˜0Kšžœ˜—šœž˜ K˜šœžœ˜.Kšœžœ˜Kšœ žœ˜KšœN˜NKšœžœ žœ žœ˜&Kšœžœžœ˜'Kšœ žœ žœžœ˜2Kšœ žœ žœ˜Kšœžœ˜ Kšœ˜—šžœžœž˜5Kšœ,˜,K˜5Kšžœ$žœžœ˜?Kšžœ˜—šžœžœžœ˜Kšœ<žœ˜CKšœ<žœ˜CKšœ?˜?Kšœ?˜?Kšžœžœ&žœ@žœ˜‰Kšœ˜—Kšžœžœžœžœžœžœ#žœ˜ˆKšœžœ˜BKšœžœ˜BKšœ"žœ˜Hšžœ˜ Kšœžœ#˜IKšœžœ#˜IK˜—Kšžœ˜—Kšžœžœ˜—Kšœ žœ˜K˜šžœ žœž˜K˜)K˜#K˜K˜Kšžœ˜—K˜Kšœ žœ˜K˜"šžœ žœž˜K˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—Kšœ"˜"šžœž˜Kš žœžœžœžœ#žœ˜sKšžœžœžœ˜C—Kšžœ˜—K˜š  œžœžœžœžœžœ˜8Kšœžœ˜šžœž˜K˜#Kšžœ,˜3—K˜—K˜šœ žœ ˜šœžœžœž˜Kšžœžœžœžœžœžœžœžœ ˜$Kšœ˜Kšžœ ˜——K˜š œžœžœžœ˜FKšž˜Kšœžœ˜Kš œžœžœžœžœ˜'KšœΟc˜3š žœžœ,žœžœ ž˜MKšœ žœ˜Kšœ žœ˜Kšœ˜Kšœ˜šžœžœ žœž˜1Kšž˜K˜Kšžœžœžœ˜ Kšœ˜Kš žœ žœžœžœ-žœ˜fKšœ˜Kš žœ>žœžœžœ,žœžœ˜¬Kšž˜—šžœž˜ Kš žœ%žœžœžœ-žœ žœ˜Kšœ3˜3Kšžœ˜—Kšžœ"žœžœžœžœ,žœžœ˜”K˜GKš žœ"žœžœžœžœžœ˜kšžœžœRžœžœ˜uK˜ K˜Kšœ*˜*Kšœ*˜*—K˜Kšœ˜Kšžœ žœžœ˜Kš žœžœžœžœ=žœ˜}Kšžœ˜—šžœžœ#ž˜@šžœ"žœž˜,Kšž˜Kšœ žœ#˜1K˜GKšžœ"žœžœžœžœ*žœžœ˜’Kšžœ˜—Kšžœ˜—K˜ Kšžœ˜—K˜š  œžœžœžœžœ žœ˜KKšž˜šžœžœžœž˜'Kšžœžœžœ˜,Kšžœ˜—Kšžœ ˜Kšžœ˜—K˜Kš œžœžœžœžœžœ˜`K˜š œžœžœ˜EKšž˜K˜Kšœ.˜.K˜$Kšžœžœžœ˜&Kš žœžœžœžœ)žœ˜kšžœ žœžœž˜6Kšœžœžœ6˜DK˜Kšœ˜Kšžœ žœžœžœ˜Kšœžœ˜Kšœ&˜&Kšžœžœžœ˜)Kšžœ˜—Kšžœ˜ Kšžœ˜—K˜š œžœžœ4˜VKšž˜K˜šžœ!žœž˜FKšœ&˜&Kšžœžœ3˜LKšžœ˜—Kšžœ˜—K˜Kšœžœžœ!˜@K˜š  œžœžœ(žœ žœ˜ZKšž˜Kš œ žœ žœžœžœ˜RKš œžœ"žœ žœžœ˜kšžœžœ ž˜Kšœžœ˜Kšœžœ˜!Kšžœžœ˜—Kšžœ˜—K˜š   œžœžœ žœ ‘ œ˜>Kšœžœ˜—K˜Kšœžœžœ ˜Kš œ žœžœ žœ žœžœžœ˜FK˜š  œžœžœžœžœ4žœžœ žœžœžœžœžœ˜½Kšœžœ ˜"KšœΥ˜Υ—K˜š  œžœ(žœ4žœžœ žœžœžœžœ"žœ˜δKšž˜Kšœ žœ˜&Kšœ žœ:˜HKšœ žœ˜&Kšœ#˜#Kšœžœ˜šœžœ ˜K˜ K˜ Kšœ ˜ K˜K˜Kšœ˜KšœC˜CK˜K˜ K˜K˜K˜K˜Kšœ˜Kšœžœ˜ Kšœž‘$œ˜6K˜ Kšœ˜—Kšžœ)˜0Kšžœžœžœžœžœ+žœžœ˜Œšžœž˜šœ˜Kš œ"žœžœžœ#žœ˜yšœ4™4K˜%K˜ —Kšœ˜—Kšœ žœ˜Kšžœžœ˜—Kšžœžœžœ7˜Xšžœžœžœ˜Kš œ žœžœžœžœ˜1Kšœžœ]˜eK˜ š žœžœžœžœžœ žœ˜?K˜=Kšžœ/˜1Kšžœ˜Kšžœ˜Kšžœ4˜6—K˜—Kšžœžœ žœžœ˜7Kšžœ˜—K˜š  œžœžœžœ˜?Kšž˜Kšœžœ ˜"K˜Kšœžœ˜Kšœžœ˜Kšœ˜Kšžœ˜—K˜š œžœ&žœ˜LK˜ šžœžœž˜˜Kš žœžœžœžœžœžœ˜Lšžœ˜Kšžœžœ&˜3Kšžœ/˜3—K˜—šœ˜š žœžœž œžœž˜+Kšœ˜Kšžœ˜—K˜—šœ˜š žœžœž œžœž˜+Kšœ˜Kšžœ˜—K˜—Kšžœžœ˜—K˜—K˜š œžœ.žœ˜TKšœ)žœ˜-Kšœžœ˜ K˜Kšœžœ˜Kšœžœ˜K˜AKšžœ žœžœ˜Kšœ˜Kš žœžœžœž‘œ˜)K˜#Kšœžœ˜Kšœžœ˜šž˜K˜Kšœ+˜+Kšžœžœžœ˜Kšœ˜Kšœ˜K˜ Kšžœ˜—Kšœ˜šž˜Kšœ˜Kšœžœ˜$Kšœ/˜/Kšžœ žœžœ žœ˜7Kšžœžœžœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—Kšœ˜šžœ žœžœ˜$šžœ˜ Kšžœ8žœ˜Fšžœ˜Kšžœ žœ<žœ˜VKšžœžœ2žœ˜TK˜——K˜—K˜—K˜Kš œ žœžœžœžœžœžœ˜2K˜š œžœ#žœžœ˜Pš œžœžœ˜;Kšžœžœžœžœ˜Kšžœžœžœžœ˜Kšœžœ!˜)—Kšžœ*žœžœ˜KKšžœ.žœžœ˜;K˜DK˜—K˜š œžœ˜)š œžœžœ˜EKšžœžœžœžœ˜Kšœžœ)˜3K˜—š žœžœžœžœž˜KšœΟdœ’œ˜ Kšœ’œ’œžœ˜ Kšžœžœžœ(žœ˜ZKšžœžœžœ(žœ˜ZKšœ’œ’œ ˜Kšœ’œ’œ ˜šžœ’œ’œžœ˜Kšœ ’œ’œ˜K˜ K˜ K˜—š žœžœ’œ’œžœ˜K˜Kšœ4’œ ’œžœ˜MKšžœ žœžœžœ˜Kšœ ’œ˜K˜ Kšœ˜K˜—š žœžœ’œ’œžœ˜K˜Kšœ4’œ ’œžœ˜MKšžœ žœžœžœ˜Kšœ ’œ˜K˜ Kšœ˜K˜—Kšžœžœ˜ Kšžœ˜—Kš žœžœžœžœžœžœ:˜VK˜—K˜š  œžœžœžœžœžœ˜`šžœžœž˜Kšœ'žœ˜-Kšœ,žœ˜2K˜7Kšžœžœ˜—K˜—K˜š  œžœžœ˜MKšœžœ˜Kšœžœ˜ Kšœžœ˜Kšœ"˜"š œžœ˜%Kšœžœ˜0Kšœ˜—š œžœ˜šžœ žœ˜Kšœžœ˜#šœ˜K˜Kšœžœ˜ šœžœ˜Kšžœ˜Kšžœ!˜#—K˜-K˜K˜—Kšœ˜K˜—Kšžœ žœ˜K˜—š œžœ˜ ˜K˜Kšœžœ˜ šœžœ˜Kšžœ˜Kšžœ˜—Kšœ&˜&K˜K˜—Kšœ ˜ K˜—š œžœ˜šžœžœ˜Kšœ6žœ˜=šœ˜K˜Kšœžœ˜ šœžœ˜Kšžœ˜Kšžœ ˜"—Kšœ,˜,K˜K˜—Kšœ˜K˜—Kšžœ žœ˜K˜—Kšžœžœžœžœ˜*Kšžœžœžœžœ˜"Kš žœžœžœžœžœ˜+K˜,Kš žœžœžœž‘œ˜)Kšžœ žœžœ˜Kš žœ žœžœžœžœ˜(šžœ‘3˜9Kšžœ˜Kšžœ˜—Kšœžœ˜ Kšžœžœžœžœ˜'K˜—K˜š  œžœ˜"Kšœžœ˜ K˜Kš žœžœžœžœTžœžœ˜΅Kšžœžœ˜8Kšžœžœ˜8Kšžœžœžœžœ˜IKšœ˜KšžœžœžœžœžœžœLžœžœ˜ΕKš žœžœžœžœžœ4˜hKš žœžœžœžœžœ4˜hšžœžœžœ˜Kšžœ‘œ˜K˜—šžœžœž˜K˜5K˜5Kšžœžœ˜—K˜*Kš žœžœžœ<žœžœ˜oKšžœžœžœ˜,Kšžœ&žœ&žœžœ˜[Kš žœžœžœžœžœžœ˜KKš žœžœ žœžœ žœžœ˜SKšžœ žœ žœžœ˜'Kšœžœ˜,Kšžœžœžœžœžœžœžœžœ˜CKš žœ žœžœ žœžœžœ˜1Kš žœžœžœžœžœžœ˜AKš žœžœžœžœžœžœ˜?Kš žœžœžœžœžœžœ˜3Kšœ˜K˜—K˜š  œžœ žœ˜1Kšžœ‘œ˜K˜—K˜š  œžœžœžœ˜9š  œžœžœ žœ žœ˜Cšžœžœž˜K˜3K˜CKšžœžœ˜—K˜—K˜K˜—K˜š œžœžœžœ˜=K˜šžœžœžœž˜&Kšœ+˜+Kšžœ˜—K˜—K˜š  œžœ žœžœ˜3šžœžœž˜Kšœ˜Kšœ!˜!Kšžœžœ˜—K˜—K˜š œžœžœžœ˜8šœžœžœž˜K˜Kšœ žœžœ ˜*šœ žœž˜Kšœžœ˜ Kšœžœžœ ˜&Kšœžœžœ žœ˜JKšžœžœ˜—Kšžœžœ˜—K˜—K˜š œžœžœ˜:Kšœ0žœ˜8Kšœžœ˜Kšžœžœžœ˜#Kšžœžœžœ˜#Kšœžœ˜.K˜0K˜0K˜&K˜K˜Kšžœžœ žœžœ˜$šžœ˜ Kšžœžœ˜Kšžœžœ ˜+—K˜—K˜š  œžœ žœžœžœ‘œ˜[Kšž˜š œžœžœžœžœžœžœ˜0šœžœžœžœž˜Kšœžœ žœžœ˜:——Kšžœ ˜&Kšžœ˜—K˜š œžœžœ žœžœžœ‘žœ ‘œ˜cKšž˜š œžœžœžœžœžœžœ˜0šœžœžœžœž˜Kšœžœžœžœ˜4——Kšžœ ˜&Kšžœ˜—K˜š  œžœžœ žœžœžœ‘œ˜^Kšž˜Kšœžœ˜ šžœžœž˜Kšœžœ ˜Kšœ˜Kšžœžœ˜—šœžœžœž˜Kšœžœ˜ K˜Kšžœžœ˜—Kšžœ˜Kšžœ˜—K˜š   œžœ žœžœžœ‘œ˜WKšž˜š œžœžœžœžœžœžœ˜0šœžœžœžœž˜Kšœžœžœžœ˜8——Kšžœ ˜&Kšžœ˜—K˜Kšžœ˜—…—wΐŸξ