DIRECTORY Atom, CDCommandOps, CDSequencer, Core, CoreCDUser, CoreClasses, CoreFlat, CoreOps, CoreProperties, FS, RefTab, Sequence, Sisyph, SymTab, TerminalIO, IO, Rope, XilinxIO; XilinxIOImpl: CEDAR PROGRAM IMPORTS Atom, CDCommandOps, CoreCDUser, CoreClasses, CoreFlat, CoreOps, CoreProperties, FS, RefTab, Sisyph, SymTab, TerminalIO, IO, Rope EXPORTS XilinxIO SHARES Sisyph = BEGIN OPEN XilinxIO; ROPE: TYPE = Rope.ROPE; LOR: TYPE = LIST OF ROPE; seqProp: ATOM = $XilinxIOSeqProp; SeqData: TYPE = REF SeqDataRec; SeqDataRec: TYPE = RECORD [ axis: Axis, startIndex: NAT, orthogonalIndex: NAT, delta: INT]; BindList: TYPE = LIST OF RECORD[wire: Core.Wire, name: ROPE]; primitives: SymTab.Ref _ SymTab.Create[]; -- cell type name to Primitive Primitive: TYPE = REF PrimitiveRec; PrimitiveRec: TYPE = RECORD [ translate: TranslateProc, data: REF ANY]; TranslateProc: TYPE = PROC [circuit: FlatCircuit, root, cell: Core.CellType, instance: CoreClasses.CellInstance, name: ROPE, flatCell: CoreFlat.FlatCellTypeRec, flatWireToSignal, bindings: RefTab.Ref, part2000: BOOL, data: REF ANY]; Pins: TYPE = LIST OF Pin; PinRecList: TYPE = LIST OF PinRec; Pin: TYPE = REF PinRec; PinRec: TYPE = RECORD [ coreName: ROPE, xilinxName: ROPE, direction: InOrOut, physicalPin: BOOL _ FALSE, tristate: BOOL _ FALSE, invert: BOOL _ FALSE]; InOrOut: TYPE = {In, Out}; directionNames: ARRAY InOrOut OF ROPE _ ["I", "O"]; FlatCircuit: TYPE = REF FlatCircuitRec; FlatCircuitRec: TYPE = RECORD [ symbols: Symbols _ NIL, signals: Signals _ NIL, partType: ROPE _ NIL]; Symbols: TYPE = LIST OF Symbol; Symbol: TYPE = REF SymbolRec; SymbolRec: TYPE = RECORD [ name: ROPE _ NIL, type: ROPE _ NIL, connections: SymbolSignalPins _ NIL, parameters: LOR _ NIL, configs: LOR _ NIL]; SymbolSignalPins: TYPE = LIST OF SymbolSignalPin; SymbolSignalPin: TYPE = REF SymbolSignalPinRec; SymbolSignalPinRec: TYPE = RECORD [ symbol: Symbol _ NIL, signal: Signal _ NIL, pin: Pin _ NIL, parameters: LOR _ NIL]; Signals: TYPE = LIST OF Signal; Signal: TYPE = REF SignalRec; SignalRec: TYPE = RECORD [ name: ROPE _ NIL, connections: SymbolSignalPins _ NIL, pin: ROPE _ NIL, -- NIL => not forced unbonded: BOOL _ FALSE, parameters: LOR _ NIL]; PinSignals: TYPE = LIST OF PinSignalRec; PinSignalRec: TYPE = RECORD [ pin: Pin _ NIL, signal: Signal _ NIL]; Loc: PUBLIC PROC [cx: Sisyph.Context, x, y: INT] RETURNS [trash: NAT _ 0] = { SELECT TRUE FROM x>=0 AND y>=0 => Sisyph.AddProp[cx, $ParLoc, IO.PutFR["\"LOC=%g%g\"", IO.char[NumToLet[x]], IO.char[NumToLet[y]]], TRUE]; x<0 AND y<0 => NULL; ENDCASE => ERROR; }; Set: PUBLIC PROC [cx: Sisyph.Context, x, y: INT, axis: Axis _ ax] RETURNS [trash: NAT _ 0] = { Sisyph.Store[cx, "x", NEW[INT _ x]]; Sisyph.Store[cx, "y", NEW[INT _ y]]; Sisyph.Store[cx, "axis", NEW[Axis _ axis]]; }; Seq: PUBLIC PROC [cx: Sisyph.Context, axis: Axis, startIndex, orthogonalIndex: NAT, delta: INT _ 1] RETURNS [trash: NAT _ 0] = { previousProps: Core.Properties _ Sisyph.GetCoreInstProps[cx]; Sisyph.Store[cx, Sisyph.coreInstPropsRope, NEW [Core.Properties _ CoreProperties.PutProp[previousProps, seqProp, NEW[SeqDataRec _ [axis, startIndex, orthogonalIndex, delta]]]]]; }; SaveCellType: PUBLIC PROC [cellType: Core.CellType, fileName: ROPE _ NIL] RETURNS [multiplyDriven: LOR _ NIL] = { circuit: FlatCircuit _ FlattenCircuit[cellType]; pruned: RefTab.Ref _ PruneFlattenedCircuit[circuit]; multiplyDriven _ CheckMultipleDrivers[circuit]; IF fileName=NIL THEN fileName _ Rope.Cat[CoreOps.GetCellTypeName[cellType], ".xnf"]; WriteFlattenedCircuit[circuit, pruned, fileName]; }; FlattenCircuit: PROC [cellType: Core.CellType] RETURNS [circuit: FlatCircuit] = { PushPins: CoreOps.EachWireProc = { pinList: ROPE _ NARROW[CoreProperties.GetWireProp[wire, $Pins]]; IF pinList#NIL THEN { ris: IO.STREAM _ IO.RIS[pinList]; FOR i: INT IN [0..wire.size) DO pin: ROPE _ IO.GetCedarTokenRope[ris].token; currentValue: ROPE _ NARROW[CoreProperties.GetWireProp[wire[i], $Pin]]; IF i#(wire.size-1) THEN { kind: IO.TokenKind; token: IO.ROPE; [kind, token] _ IO.GetCedarTokenRope[ris]; IF kind#tokenSINGLE OR NOT Rope.Equal[token, ","] THEN ERROR; }; IF wire[i].size#0 THEN ERROR; IF currentValue=NIL THEN CoreProperties.PutWireProp[wire[i], $Pin, pin]; ENDLOOP; }; }; FlattenCellType: CoreFlat.BoundFlatCellProc = { GetParms: CoreOps.EachWireProc = { FindParms: PROC [prop: ATOM, val: REF ANY] = { propName: ROPE _ Atom.GetPName[prop]; IF Rope.Match["Par*", propName, FALSE] THEN { SetParm: PROC [wire: Core.Wire] = { signal: Signal _ CreateBoundSignal[wire, circuit, cellType, flatWireToSignal, bindings, flatCell]; signal.parameters _ CONS[parm, signal.parameters]; }; parm: ROPE _ NARROW[val]; IF wire.size#0 THEN [] _ CoreOps.VisitRootAtomics[wire, SetParm] ELSE SetParm[wire]; }; }; CoreProperties.Enumerate[wire.properties, FindParms]; }; name: ROPE _ CoreOps.GetCellTypeName[cell]; primitive: Primitive _ NARROW[SymTab.Fetch[primitives, name].val]; clbMapProp: REF BOOL _ NARROW[CoreProperties.GetCellTypeProp[cell, $CLBMap]]; IF clbMapProp#NIL AND clbMapProp^ THEN CreateCLBMap[circuit, cellType, cell, instance, name, flatCell, flatWireToSignal, bindings, part2000, NIL]; IF cell.class=CoreClasses.recordCellClass THEN { rct: CoreClasses.RecordCellType _ NARROW[cell.data]; FOR instanceIndex: NAT IN [0..rct.size) DO seqData: SeqData _ NARROW[CoreProperties.GetCellInstanceProp[rct[instanceIndex], seqProp]]; IF seqData#NIL THEN { child: Core.CellType _ rct[instanceIndex].type; sct: Sequence.SequenceCellType _ NARROW[child.data]; recast: Core.CellType _ CoreOps.Recast[child]; recastRCT: CoreClasses.RecordCellType _ NARROW[recast.data]; FOR subInstanceIndex: NAT IN [0..recastRCT.size) DO seqIndex: NAT _ seqData.startIndex + (subInstanceIndex*seqData.delta); x, y: NAT _ 0; SELECT seqData.axis FROM ax => {x _ seqIndex; y _ seqData.orthogonalIndex}; ay => {x _ seqData.orthogonalIndex; y _ seqIndex}; ENDCASE => ERROR; CoreProperties.PutCellInstanceProp[recastRCT[subInstanceIndex], $ParLoc, IO.PutFR["LOC=%g%g", IO.char[NumToLet[y]], IO.char[NumToLet[x]]]]; ENDLOOP; }; ENDLOOP; [] _ CoreOps.VisitWireSeq[NARROW[cell.data, CoreClasses.RecordCellType].internal, GetParms]; }; IF primitive=NIL THEN CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, FlattenCellType] ELSE primitive.translate[circuit, cellType, cell, instance, name, flatCell, flatWireToSignal, bindings, part2000, primitive.data]; }; flatWireToSignal: RefTab.Ref _ RefTab.Create[hash: CoreFlat.FlatWireHash, equal: CoreFlat.FlatWireEqual]; part2000: BOOL _ FALSE; circuit _ NEW[FlatCircuitRec]; circuit.partType _ NARROW[CoreProperties.InheritCellTypeProp[cellType, $XilinxPartType]]; IF circuit.partType=NIL THEN circuit.partType _ "2064PC68-33"; part2000 _ Rope.Fetch[circuit.partType]='2; [] _ CoreOps.VisitWire[cellType.public, PushPins]; FlattenCellType[cell: cellType, bindings: CoreFlat.InitialBindingTable[cellType]]; }; clbMapPins: Pins _ PinRecListToPinList[LIST[ ["A", "A", In], ["B", "B", In], ["C", "C", In], ["D", "D", In], ["E", "E", In], ["DI", "DI", In], ["EC", "EC", In], ["K", "K", In], ["RD", "RD", In], ["X", "X", In], ["Y", "Y", In]]]; CreateCLBMap: TranslateProc = { MakeBind: PROC [wire: Core.Wire] = { coreName: ROPE _ NARROW[CoreProperties.GetWireProp[wire, $Pin]]; IF coreName=NIL AND NOT GlobalDelete[CoreOps.GetFullWireName[public, wire]] THEN ERROR; IF coreName#NIL THEN bindlist _ CONS[[wire, coreName], bindlist]; }; bindlist: BindList _ NIL; symbol: Symbol _ NIL; public: Core.Wire _ cell.public; CoreOps.VisitRootAtomics[public, MakeBind]; symbol _ MakeSymbol[CoreFlat.CellTypePathRope[root, flatCell], "CLBMAP", bindlist, clbMapPins, circuit, root, flatCell, flatWireToSignal, bindings]; GetParameters[symbol, instance]; }; trace: BOOL _ FALSE; PruneFlattenedCircuit: PROC [circuit: FlatCircuit] RETURNS [pruned: RefTab.Ref] = { CheckSignal: RefTab.EachPairAction = { signal: Signal _ NARROW[key]; sensed, physical: BOOL _ FALSE; IF RefTab.Fetch[pruned, signal].found THEN RETURN; [sensed, physical] _ SensedPhysicalDrivenTristate[signal, pruned]; IF NOT sensed AND (signal.unbonded OR NOT physical) THEN { IF trace THEN TerminalIO.PutF["\npruning signal: %g", IO.rope[signal.name]]; IF NOT RefTab.Insert[pruned, signal, signal] THEN ERROR; FOR cl: SymbolSignalPins _ signal.connections, cl.rest UNTIL cl=NIL DO ssp: SymbolSignalPin _ cl.first; IF ssp.pin.direction=Out THEN IF NOT RefTab.Insert[pruned, ssp, ssp] THEN ERROR; [] _ RefTab.Insert[symbolCheck, ssp.symbol, ssp.symbol]; ENDLOOP; }; }; CheckSymbol: RefTab.EachPairAction = { symbol: Symbol _ NARROW[key]; IF RefTab.Fetch[pruned, symbol].found THEN RETURN; FOR cl: SymbolSignalPins _ symbol.connections, cl.rest UNTIL cl=NIL DO ssp: SymbolSignalPin _ cl.first; IF ssp.pin.direction=Out AND NOT RefTab.Fetch[pruned, ssp].found THEN RETURN; ENDLOOP; IF trace THEN TerminalIO.PutF["\npruning symbol: %g", IO.rope[symbol.name]]; IF NOT RefTab.Insert[pruned, symbol, symbol] THEN ERROR; FOR cl: SymbolSignalPins _ symbol.connections, cl.rest UNTIL cl=NIL DO ssp: SymbolSignalPin _ cl.first; IF ssp.pin.direction=In THEN IF NOT RefTab.Insert[pruned, ssp, ssp] THEN ERROR; [] _ RefTab.Insert[signalCheck, ssp.signal, ssp.signal]; ENDLOOP; }; signalCheck: RefTab.Ref _ RefTab.Create[]; symbolCheck: RefTab.Ref _ RefTab.Create[]; pruned _ RefTab.Create[]; FOR sl: Signals _ circuit.signals, sl.rest UNTIL sl=NIL DO IF NOT RefTab.Insert[signalCheck, sl.first, sl.first] THEN ERROR; ENDLOOP; UNTIL RefTab.GetSize[symbolCheck]=0 AND RefTab.GetSize[signalCheck]=0 DO [] _ RefTab.Pairs[signalCheck, CheckSignal]; RefTab.Erase[signalCheck]; [] _ RefTab.Pairs[symbolCheck, CheckSymbol]; RefTab.Erase[symbolCheck]; ENDLOOP; }; CheckMultipleDrivers: PROC [circuit: FlatCircuit] RETURNS [names: LOR _ NIL]= { Driven: TYPE = {Never, Always, Tristate}; FOR sl: Signals _ circuit.signals, sl.rest UNTIL sl=NIL DO driven: Driven _ Never; FOR cl: SymbolSignalPins _ sl.first.connections, cl.rest UNTIL cl=NIL DO ssp: SymbolSignalPin _ cl.first; IF ssp.pin.direction=Out THEN { IF driven=Always OR (driven=Tristate AND NOT ssp.pin.tristate) THEN { names _ CONS[sl.first.name, names]; EXIT; }; driven _ IF ssp.pin.tristate THEN Tristate ELSE Always; }; ENDLOOP; ENDLOOP; }; WriteFlattenedCircuit: PROC [circuit: FlatCircuit, pruned: RefTab.Ref, fileName: ROPE] = { WriteRecord: PROC [record: ROPE, parameters: LOR _ NIL] = { FOR rl: LOR _ parameters, rl.rest UNTIL rl=NIL DO record _ Rope.Cat[record, ",", rl.first]; ENDLOOP; IF Rope.Length[record]>=253 THEN ERROR; IO.PutF[stream, "%g\n", IO.rope[record]]; }; stream: IO.STREAM _ FS.StreamOpen[fileName, $create]; WriteRecord["LCANET,2"]; WriteRecord[IO.PutFR["PROG,Core2XNF,1,%g", IO.time[]]]; WriteRecord[Rope.Cat["PART,", circuit.partType]]; FOR sl: Symbols _ circuit.symbols, sl.rest UNTIL sl=NIL DO symbol: Symbol _ sl.first; IF NOT RefTab.Fetch[pruned, symbol].found THEN { WriteRecord[IO.PutFR["SYM,%g,%g", IO.rope[symbol.name], IO.rope[symbol.type]], symbol.parameters]; FOR cl: SymbolSignalPins _ symbol.connections, cl.rest UNTIL cl=NIL DO ssp: SymbolSignalPin _ cl.first; pinRecord: ROPE _ IO.PutFR["PIN,%g,%g,%g", IO.rope[ssp.pin.xilinxName], IO.rope[directionNames[ssp.pin.direction]], IO.rope[ssp.signal.name]]; IF ssp.pin.invert OR ssp.parameters#NIL THEN pinRecord _ Rope.Cat[pinRecord, ","]; IF ssp.pin.invert THEN pinRecord _ Rope.Cat[pinRecord, ",INV"]; WriteRecord[pinRecord, ssp.parameters]; ENDLOOP; FOR rl: LOR _ symbol.configs, rl.rest UNTIL rl=NIL DO WriteRecord[Rope.Cat["CFG,", rl.first]]; ENDLOOP; WriteRecord["END"]; }; ENDLOOP; WriteRecord["PWR,1,public-$Vdd"]; WriteRecord["PWR,0,public-$Gnd"]; FOR sl: Signals _ circuit.signals, sl.rest UNTIL sl=NIL DO signal: Signal _ sl.first; sensed, physical, driven, tristate: BOOL _ FALSE; [sensed, physical, driven, tristate] _ SensedPhysicalDrivenTristate[signal, pruned]; IF physical OR signal.parameters#NIL THEN { signalRecord: ROPE _ IF physical THEN "EXT," ELSE "SIG,"; signalRecord _ Rope.Cat[signalRecord, signal.name]; IF physical THEN { signalRecord _ Rope.Cat[signalRecord, SELECT TRUE FROM signal.unbonded => ",U", driven AND sensed => ",B", driven AND tristate => ",T", driven => ",O", sensed => ",I", ENDCASE => ERROR]; IF signal.pin#NIL OR signal.parameters#NIL THEN signalRecord _ Rope.Cat[signalRecord, SELECT TRUE FROM signal.pin#NIL => IO.PutFR[",,LOC=%g%g", IO.rope[IF Rope.Fetch[signal.pin] IN ['0..'9] THEN "P" ELSE NIL], IO.rope[signal.pin]], signal.parameters#NIL => ",", ENDCASE => ERROR]; }; WriteRecord[signalRecord, signal.parameters]; }; ENDLOOP; WriteRecord["EOF"]; IO.Close[stream]; }; SimpleData: TYPE = REF SimpleDataRec; SimpleDataRec: TYPE = RECORD [ xilinxType: ROPE, pins: Pins]; RegisterSimplePrimitive: PROC [coreName: ROPE, xilinxType: ROPE, pins: PinRecList, aliases: LOR _ NIL] = { simpleData: SimpleData _ NEW[SimpleDataRec _ [ xilinxType: xilinxType, pins: PinRecListToPinList[pins]]]; RegisterPrimitive[coreName, FlattenSimplePrimitive, simpleData]; FOR al: LOR _ aliases, al.rest UNTIL al=NIL DO RegisterPrimitive[al.first, FlattenSimplePrimitive, simpleData]; ENDLOOP; }; FlattenSimplePrimitive: TranslateProc = { simpleData: SimpleData _ NARROW[data]; symbol: Symbol _ MakeSymbol[CoreFlat.CellTypePathRope[root, flatCell], simpleData.xilinxType, MakeBindList[cell.public], simpleData.pins, circuit, root, flatCell, flatWireToSignal, bindings]; GetParameters[symbol, instance]; }; CLBData: TYPE = REF CLBDataRec; CLBDataRec: TYPE = RECORD [ config: ROPE, equate: ROPE]; clbPins: Pins _ PinRecListToPinList[LIST[ ["A", "A", In], ["B", "B", In], ["C", "C", In], ["D", "D", In], ["X", "X", Out]]]; RegisterCLBPrimitive: PROC [coreName: ROPE, config: ROPE, equate: ROPE] = { clbData: CLBData _ NEW[CLBDataRec _ [ config: config, equate: equate]]; RegisterPrimitive[coreName, FlattenCLBPrimitive, clbData]; }; FlattenCLBPrimitive: TranslateProc = { clbData: CLBData _ NARROW[data]; configs: LOR _ LIST[Rope.Cat["EQUATE F=", clbData.equate]]; symbol: Symbol; configs _ CONS[Rope.Cat["CONFIG X:F F:", clbData.config], configs]; configs _ CONS[Rope.Cat["BASE ", IF part2000 THEN "F" ELSE "FG"], configs]; symbol _ MakeSymbol[CoreFlat.CellTypePathRope[root, flatCell], "CLB", MakeBindList[cell.public], clbPins, circuit, root, flatCell, flatWireToSignal, bindings, NIL, configs]; GetParameters[symbol, instance]; }; flopPins: Pins _ PinRecListToPinList[LIST[ ["D", "D", In], ["CK", "C", In], ["Q", "Q", Out]]]; flopEnPins: Pins _ PinRecListToPinList[LIST[ ["D", "D", In], ["CK", "C", In], ["Q", "Q", Out], ["en", "CE", In]]]; flopReg1Pins: Pins _ PinRecListToPinList[LIST[ ["Input", "D", In], ["CK", "C", In], ["Output", "Q", Out], ["en", "CE", In]]]; invPins: Pins _ PinRecListToPinList[LIST[ ["I", "I", In], ["X", "O", Out]]]; FlattenFlopPrimitive: TranslateProc = { symbol: Symbol; flatName: ROPE _ CoreFlat.CellTypePathRope[root, flatCell]; lora: LIST OF REF ANY _ NARROW[data]; nqName: ROPE _ CoreOps.FixStupidRef[lora.first]; pins: Pins _ NARROW[lora.rest.first]; d: Core.Wire _ CoreOps.FindWire[cell.public, pins.first.coreName]; c: Core.Wire _ CoreOps.FindWire[cell.public, pins.rest.first.coreName]; q: Core.Wire _ CoreOps.FindWire[cell.public, pins.rest.rest.first.coreName]; en: Core.Wire _ IF pins.rest.rest.rest=NIL THEN NIL ELSE CoreOps.FindWire[cell.public, pins.rest.rest.rest.first.coreName]; nq: Core.Wire _ CoreOps.FindWire[cell.public, nqName]; bindList: BindList _ LIST[[d, pins.first.coreName], [c, pins.rest.first.coreName], [q, pins.rest.rest.first.coreName]]; IF en#NIL THEN bindList _ CONS[[en, pins.rest.rest.rest.first.coreName], bindList]; symbol _ MakeSymbol[flatName, "DFF", bindList, pins, circuit, root, flatCell, flatWireToSignal, bindings]; [] _ MakeSymbol[Rope.Cat[flatName, "ManufacturedInverter"], "INV", LIST[[q, "I"], [nq, "X"]], invPins, circuit, root, flatCell, flatWireToSignal, bindings]; GetParameters[symbol, instance]; }; symPins: Pins _ PinRecListToPinList[LIST[ ["I", "I", In], ["X", "O", Out]]]; FlattenSymDriverPrimitive: TranslateProc = { flatName: ROPE _ CoreFlat.CellTypePathRope[root, flatCell]; i: Core.Wire _ CoreOps.FindWire[cell.public, "I"]; x: Core.Wire _ CoreOps.FindWire[cell.public, "X"]; nx: Core.Wire _ CoreOps.FindWire[cell.public, "nX"]; [] _ MakeSymbol[Rope.Cat[flatName, "ManufacturedBuffer"], "BUF", LIST[[i, "I"], [x, "X"]], symPins, circuit, root, flatCell, flatWireToSignal, bindings]; [] _ MakeSymbol[Rope.Cat[flatName, "ManufacturedInverter"], "INV", LIST[[i, "I"], [nx, "X"]], symPins, circuit, root, flatCell, flatWireToSignal, bindings]; }; tPin: Pin _ NEW[PinRec _ ["?", "T", In]]; iPin: Pin _ NEW[PinRec _ ["I", "I", In]]; oPin: Pin _ NEW[PinRec _ ["X", "O", Out,,TRUE]]; FlattenTristateDriver: TranslateProc = { symbol: Symbol; flatName: ROPE _ CoreFlat.CellTypePathRope[root, flatCell]; en: Signal _ CreateBoundSignal[CoreOps.FindWire[cell.public, "EN"], circuit, root, flatWireToSignal, bindings, flatCell]; i: Signal _ CreateBoundSignal[CoreOps.FindWire[cell.public, "I"], circuit, root, flatWireToSignal, bindings, flatCell]; x: Signal _ CreateBoundSignal[CoreOps.FindWire[cell.public, "X"], circuit, root, flatWireToSignal, bindings, flatCell]; nenb: Signal _ CreateSignal[circuit]; [] _ AddSymbol[circuit, Rope.Cat[flatName, "ManufacturedEnableInverter"], "INV", LIST[[iPin, en], [oPin, nenb]]]; symbol _ AddSymbol[circuit, Rope.Cat[flatName, "ManufacturedTristate"], "TBUF", LIST[[tPin, nenb], [iPin, i], [oPin, x]]]; GetParameters[symbol, instance]; }; FlattenTristateDriverInv: TranslateProc = { symbol: Symbol; flatName: ROPE _ CoreFlat.CellTypePathRope[root, flatCell]; en: Signal _ CreateBoundSignal[CoreOps.FindWire[cell.public, "EN"], circuit, root, flatWireToSignal, bindings, flatCell]; i: Signal _ CreateBoundSignal[CoreOps.FindWire[cell.public, "I"], circuit, root, flatWireToSignal, bindings, flatCell]; x: Signal _ CreateBoundSignal[CoreOps.FindWire[cell.public, "X"], circuit, root, flatWireToSignal, bindings, flatCell]; nenb: Signal _ CreateSignal[circuit]; nd: Signal _ CreateSignal[circuit]; [] _ AddSymbol[circuit, Rope.Cat[flatName, "ManufacturedEnableInverter"], "INV", LIST[[iPin, en], [oPin, nenb]]]; [] _ AddSymbol[circuit, Rope.Cat[flatName, "ManufacturedDataInverter"], "INV", LIST[[iPin, i], [oPin, nd]]]; symbol _ AddSymbol[circuit, Rope.Cat[flatName, "ManufacturedTristate"], "TBUF", LIST[[tPin, nenb], [iPin, nd], [oPin, x]]]; GetParameters[symbol, instance]; }; WriteXNF: PROC [command: CDSequencer.Command] = { XNFOne: CoreCDUser.EachRootCellTypeProc ~ { md: LOR _ SaveCellType[root]; FOR lor: LOR _ md, lor.rest UNTIL lor=NIL DO TerminalIO.PutF["\nMultiply driven: %g", IO.rope[lor.first]]; ENDLOOP; TerminalIO.PutF["\nXNF written: %g", IO.rope[CoreOps.GetCellTypeName[root]]]; }; [] _ CoreCDUser.EnumerateSelectedCellTypes[command.design, XNFOne]; }; NumToLet: PROC [n: NAT] RETURNS [l: CHAR] = { l _ LOOPHOLE[LOOPHOLE['A, NAT] + n]; }; RegisterPrimitive: PROC [coreName: ROPE, proc: TranslateProc, data: REF ANY _ NIL] = { primitive: Primitive _ NEW[PrimitiveRec _ [ translate: proc, data: data]]; IF NOT SymTab.Insert[primitives, coreName, primitive] THEN ERROR; }; PinRecListToPinList: PROC [pins: PinRecList] RETURNS [refPins: Pins _ NIL] = { t: Pins _ NIL; FOR pl: PinRecList _ pins, pl.rest UNTIL pl=NIL DO t _ CONS[NEW[PinRec _ pl.first], t]; ENDLOOP; FOR pl: Pins _ t, pl.rest UNTIL pl=NIL DO refPins _ CONS[pl.first, refPins]; ENDLOOP; }; MakeBindList: PROC [public: Core.Wire] RETURNS [bindlist: BindList _ NIL] = { MakeBind: PROC [wire: Core.Wire] = { coreName: ROPE _ CoreOps.GetFullWireName[public, wire]; IF NOT GlobalDelete[coreName] THEN bindlist _ CONS[[wire, coreName], bindlist]; }; CoreOps.VisitRootAtomics[public, MakeBind]; }; MakeSymbol: PROC [name, type: ROPE, bind: BindList, pins: Pins, circuit: FlatCircuit, root: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec, flatWireToSignal, bindings: RefTab.Ref, parameters, configs: LOR _ NIL] RETURNS [symbol: Symbol] = { symbol _ CreateSymbol[circuit, name, type, parameters, configs]; FOR bl: BindList _ bind, bl.rest UNTIL bl=NIL DO IF NOT GlobalDelete[bl.first.name] THEN FOR pl: Pins _ pins, pl.rest UNTIL pl=NIL DO IF Rope.Equal[pl.first.coreName, bl.first.name] THEN { signal: Signal _ CreateBoundSignal[bl.first.wire, circuit, root, flatWireToSignal, bindings, flatCell]; CreateSSP[symbol, pl.first, signal]; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; ENDLOOP; }; AddSymbol: PROC [circuit: FlatCircuit, name, type: ROPE, bindings: PinSignals] RETURNS [symbol: Symbol] = { symbol _ CreateSymbol[circuit, name, type]; FOR ps: PinSignals _ bindings, ps.rest UNTIL ps=NIL DO CreateSSP[symbol, ps.first.pin, ps.first.signal]; ENDLOOP; }; CreateSymbol: PROC [circuit: FlatCircuit, name, type: ROPE, parameters, configs: LOR _ NIL] RETURNS [symbol: Symbol] = { symbol _ NEW[SymbolRec]; symbol.name _ name; symbol.type _ type; symbol.parameters _ parameters; symbol.configs _ configs; circuit.symbols _ CONS[symbol, circuit.symbols]; }; CreateBoundSignal: PROC [wire: Core.Wire, circuit: FlatCircuit, root: Core.CellType, flatWireToSignal: RefTab.Ref, bindings: RefTab.Ref, flatCell: CoreFlat.FlatCellTypeRec] RETURNS [signal: Signal] = { flatWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[bindings, wire].val]; IF flatWire=NIL THEN { flatWire _ NEW[CoreFlat.FlatWireRec]; flatWire.wire _ wire; flatWire.flatCell _ flatCell; }; signal _ NARROW[RefTab.Fetch[flatWireToSignal, flatWire].val]; IF signal=NIL THEN { signal _ CreateSignal[circuit, SignalName[root, flatWire]]; IF NOT RefTab.Insert[flatWireToSignal, NEW[CoreFlat.FlatWireRec _ flatWire^], signal] THEN ERROR; signal.pin _ NARROW[CoreProperties.GetWireProp[flatWire.wire, $Pin]]; }; }; CreateSignal: PROC [circuit: FlatCircuit, name: ROPE _ NIL] RETURNS [signal: Signal] = { signal _ NEW[SignalRec]; IF name=NIL THEN name _ SignalName[NIL, NIL]; signal.name _ name; circuit.signals _ CONS[signal, circuit.signals]; }; CreateSSP: PROC [symbol: Symbol, pin: Pin, signal: Signal] = { ssp: SymbolSignalPin _ NEW[SymbolSignalPinRec]; ssp.symbol _ symbol; ssp.pin _ pin; ssp.signal _ signal; symbol.connections _ CONS[ssp, symbol.connections]; signal.connections _ CONS[ssp, signal.connections]; }; GlobalDelete: PROC [name: ROPE] RETURNS [yes: BOOL _ FALSE] = { yes _ Rope.Equal[name, "Vdd"] OR Rope.Equal[name, "Gnd"] OR Rope.Equal[name, "RosemaryLogicTime"]; }; nameCount: INT _ 0; SignalName: PROC [cellType: Core.CellType, flatWire: CoreFlat.FlatWire] RETURNS [name: ROPE _ NIL] = { BuildNew: Rope.ActionType = { c _ SELECT c FROM '/ => '$, '(, '[ => '<, '), '] => '>, '. => '-, '* => '_, ENDCASE => c; IF c IN ['A..'Z] THEN name _ Rope.Concat[name, "$"]; name _ Rope.Concat[name, Rope.FromChar[c]]; }; ManufactureName: PROC = { name _ IO.PutFR["N%g", IO.int[nameCount]]; nameCount _ nameCount + 1; }; IF cellType=NIL OR flatWire=NIL THEN ManufactureName[] ELSE { old: ROPE _ CoreFlat.WirePathRope[cellType, flatWire^]; shortName: ROPE _ CoreOps.GetShortWireName[flatWire.wire]; SELECT TRUE FROM Rope.Equal[shortName, "Vdd"] => name _ "public-$Vdd"; Rope.Equal[shortName, "Gnd"] => name _ "public-$Gnd"; Rope.Fetch[old]#'/ => [] _ Rope.Map[base: old, action: BuildNew]; ENDCASE => ManufactureName[]; }; }; SensedPhysicalDrivenTristate: PROC [signal: Signal, pruned: RefTab.Ref] RETURNS [sensed, physical, driven, tristate: BOOL _ FALSE] = { FOR cl: SymbolSignalPins _ signal.connections, cl.rest UNTIL cl=NIL DO ssp: SymbolSignalPin _ cl.first; IF NOT RefTab.Fetch[pruned, ssp].found THEN { sensed _ sensed OR ssp.pin.direction=In; physical _ physical OR ssp.pin.physicalPin; driven _ driven OR ssp.pin.direction=Out; tristate _ tristate OR ssp.pin.tristate; }; ENDLOOP; }; GetParameters: PROC [symbol: Symbol, instance: CoreClasses.CellInstance] = { FindParms: PROC [prop: ATOM, val: REF ANY] = { propName: ROPE _ Atom.GetPName[prop]; IF Rope.Match["Par*", propName, FALSE] THEN { parm: ROPE _ NARROW[val]; symbol.parameters _ CONS[parm, symbol.parameters]; }; }; CoreProperties.Enumerate[instance.properties, FindParms]; }; RegisterSimplePrimitive["IBuf", "IBUF", LIST[ ["I", "I", In, TRUE], ["X", "O", Out]]]; RegisterSimplePrimitive["OBuf", "OBUF", LIST[ ["I", "I", In], ["X", "O", Out, TRUE]]]; RegisterSimplePrimitive["OBufZ", "OBUFZ", LIST[ ["I", "I", In], ["EN", "T", In,,,TRUE], ["X", "O", Out, TRUE, TRUE]]]; RegisterSimplePrimitive["OutFF", "OUTFF", LIST[ ["D", "D", In], ["CK", "C", In], ["Q", "Q", Out, TRUE]]]; RegisterSimplePrimitive["OutFFZ", "OUTFFZ", LIST[ ["D", "D", In], ["EN", "T", In,,,TRUE], ["CK", "C", In], ["X", "O", Out, TRUE, TRUE]]]; RegisterSimplePrimitive["InFF", "INFF", LIST[ ["D", "D", In, TRUE], ["CK", "C", In], ["Q", "Q", Out]]]; RegisterSimplePrimitive["InLatch", "INLATCH", LIST[ ["D", "D", In, TRUE], ["E", "E", In], ["X", "O", In], ["Q", "Q", Out]]]; RegisterSimplePrimitive["inv", "INV", LIST[ ["I", "I", In], ["X", "O", Out]], LIST["invP", "invB", "invPB", "invBuffer", "invDriver"]]; RegisterSimplePrimitive["driver", "BUF", LIST[ ["I", "I", In], ["X", "O", Out]]]; RegisterPrimitive["symDriver", FlattenSymDriverPrimitive, NIL]; RegisterPrimitive["3BufferI", FlattenTristateDriverInv, NIL]; RegisterPrimitive["3BufferNI", FlattenTristateDriver, NIL]; RegisterSimplePrimitive["AClk", "ACLK", LIST[ ["I", "I", In], ["X", "O", Out]]]; RegisterSimplePrimitive["GClk", "GCLK", LIST[ ["I", "I", In], ["X", "O", Out]]]; RegisterSimplePrimitive["and2", "AND", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["X", "O", Out]]]; RegisterSimplePrimitive["and3", "AND", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["I-C", "3", In], ["X", "O", Out]]]; RegisterSimplePrimitive["and4", "AND", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["I-C", "3", In], ["I-D", "4", In], ["X", "O", Out]]]; RegisterSimplePrimitive["or2", "OR", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["X", "O", Out]]]; RegisterSimplePrimitive["or3", "OR", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["I-C", "3", In], ["X", "O", Out]]]; RegisterSimplePrimitive["or4", "OR", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["I-C", "3", In], ["I-D", "4", In], ["X", "O", Out]]]; RegisterSimplePrimitive["nand2", "NAND", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["X", "O", Out]]]; RegisterSimplePrimitive["nand3", "NAND", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["I-C", "3", In], ["X", "O", Out]]]; RegisterSimplePrimitive["nand4", "NAND", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["I-C", "3", In], ["I-D", "4", In], ["X", "O", Out]]]; RegisterSimplePrimitive["nor2", "NOR", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["X", "O", Out]]]; RegisterSimplePrimitive["nor3", "NOR", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["I-C", "3", In], ["X", "O", Out]]]; RegisterSimplePrimitive["nor4", "NOR", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["I-C", "3", In], ["I-D", "4", In], ["X", "O", Out]]]; RegisterSimplePrimitive["xor2", "XOR", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["X", "O", Out]]]; RegisterSimplePrimitive["xnor2", "XNOR", LIST[ ["I-A", "1", In], ["I-B", "2", In], ["X", "O", Out]]]; RegisterCLBPrimitive["a22o2iP", "A:B:C:D", "~((A*B)+(C*D))"]; RegisterCLBPrimitive["a22o2i", "A:B:C:D", "~((A*B)+(C*D))"]; RegisterCLBPrimitive["o22a2iP", "A:B:C:D", "~((A+B)*(C+D))"]; RegisterCLBPrimitive["o22a2i", "A:B:C:D", "~((A+B)*(C+D))"]; RegisterCLBPrimitive["a21o2i", "A:B:C", "~((A*B)+C)"]; RegisterCLBPrimitive["o21a2i", "A:B:C", "~((A+B)*C)"]; RegisterSimplePrimitive["DFF", "DFF", LIST[ ["D", "D", In], ["ap", "SD", In], ["ar", "RD", In], ["CK", "C", In], ["Q", "Q", Out]]]; RegisterSimplePrimitive["ffAR", "DFF", LIST[ ["D", "D", In], ["r", "RD", In], ["CK", "C", In], ["Q", "Q", Out]]]; RegisterPrimitive["ff", FlattenFlopPrimitive, LIST["NQ", flopPins]]; RegisterPrimitive["ffEn", FlattenFlopPrimitive, LIST["NQ", flopEnPins]]; RegisterPrimitive["reg1", FlattenFlopPrimitive, LIST["nOutput", flopReg1Pins]]; RegisterSimplePrimitive["pullUp", "PULLUP", LIST[ ["out", "O", Out, FALSE, FALSE]]]; RegisterSimplePrimitive["Osc", "OSC", LIST[ ["X", "O", Out]]]; CDCommandOps.RegisterWithMenu[$SpecialMenu, "WriteXNF", "Extract selected cells and write xnf files", $WriteXNF, WriteXNF]; END. ÒXilinxIOImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Barth, November 7, 1989 8:20:31 am PST Last Edited by: Gasbarro July 18, 1989 6:23:49 pm PDT Types and Globals Primitive Data Base Flattened Circuit some connections' pin.physicalPin = TRUE causes an EXT record to be emitted using unbonded, pin, and parameters all connections' pin.physicalPin = FALSE and parameters#NIL causes a SIG record to be emitted Placement Functions Simple CLB Flop SymDriver Tristate Driver Interactive Command Utilities CoreFlat uses Letter Digit / ( ) [ ] . * LCA allows Letter Digit $  - < > / but / is reserved for path names and names are case insensitive Registration Really should load the primitive definitions by scanning a cell in Xilinx.dale I/O Symbols Inverters, Buffers RegisterSimplePrimitive["3BufferNI", "TBUF", LIST[ ["I", "I", In], ["EN", "T", In,,,TRUE], ["X", "O", Out, FALSE, TRUE]]]; Gates: 2, 3, and 4 input Gates, compound Flops Misc. Ê 1– "cedar" style˜codešœ™Kšœ Ïmœ1™Kšœ+˜+Kšœ2˜2KšœR˜RK˜K˜—šœ'žœ˜,Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—š¡ œ˜š¡œžœ˜$Kšœ žœžœ)˜@Kš žœ žœžœžœ5žœžœ˜WKšžœ žœžœ žœ˜AK˜—Kšœžœ˜Kšœžœ˜K˜ Kšœ+˜+Kšœ”˜”Kšœ ˜ K˜K˜—šœžœžœ˜K˜—š¡œžœžœ˜Sš¡ œ˜&Kšœžœ˜Kšœžœž˜Kšžœ$žœžœ˜2KšœB˜Bš žœžœžœžœžœ žœ˜:Kšžœžœ)žœ˜LKšžœžœ'žœžœ˜8šžœ4žœžœž˜FKšœ ˜ Kš žœžœžœžœ!žœžœ˜PKšœ8˜8Kšžœ˜—K˜—K˜—š¡ œ˜&Kšœžœ˜Kšžœ$žœžœ˜2šžœ4žœžœž˜FKšœ ˜ Kš žœžœžœ!žœžœ˜MKšžœ˜—Kšžœžœ)žœ˜LKšžœžœ'žœžœ˜8šžœ4žœžœž˜FKšœ ˜ Kš žœžœžœžœ!žœžœ˜OKšœ8˜8Kšžœ˜—K˜—Kšœ*˜*K˜*K˜šžœ(žœžœž˜:Kšžœžœ0žœžœ˜AKšžœ˜—šžœžœž˜HKšœ,˜,Kšœ˜Kšœ,˜,Kšœ˜Kšžœ˜—K˜K˜—š ¡œžœžœ žœžœ˜OKšœžœ˜)šžœ(žœžœž˜:K˜šžœ6žœžœž˜HKšœ ˜ šžœžœ˜š žœžœžœžœžœ˜EKšœžœ˜#Kšžœ˜K˜—Kšœ žœžœ žœ˜7K˜—Kšžœ˜—Kšžœ˜—K˜K˜—š¡œžœ6žœ˜Zš ¡ œžœ žœžœžœ˜;š žœžœžœžœž˜1Kšœ)˜)Kšžœ˜—Kšžœžœžœ˜'Kšžœžœ˜)K˜—Kšœžœžœžœ˜5Kšœ˜Kšœ žœžœ ˜7Kšœ1˜1šžœ(žœžœž˜:K˜šžœžœ$žœ˜0Kšœ žœžœžœ(˜bšžœ4žœžœž˜FKšœ ˜ Kš œ žœžœžœžœ*žœ˜ŽKšžœžœžœžœ&˜RKšžœžœ)˜?Kšœ'˜'Kšžœ˜—š žœžœžœžœž˜5Kšœ(˜(Kšžœ˜—Kšœ˜K˜—Kšžœ˜—Kšœ!˜!Kšœ!˜!šžœ(žœžœž˜:Kšœ˜Kšœ$žœžœ˜1KšœT˜Tšžœ žœžœžœ˜+Kš œžœžœ žœžœ˜9Kšœ3˜3šžœ žœ˜šœ&žœžœž˜6Kšœ˜Kšœžœ˜Kšœžœ˜Kšœ˜Kšœ˜Kšžœžœ˜—š žœ žœžœžœžœ˜0šœ&žœžœž˜6Kšœ žœžœžœžœžœ žœžœžœžœ˜€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šœ ˜ K˜K˜——šž™Kšœ žœžœ ˜šœ žœžœ˜Kšœžœ˜ Kšœžœ˜K˜—šœ$žœ˜)Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—š ¡œžœ žœ žœ žœ˜Kšœžœ˜%Kšœ˜Kšœ˜—Kšœ:˜:K˜K˜—š¡œ˜&Kšœžœ˜ Kšœ žœžœ(˜;K˜Kšœ žœ5˜CKš œ žœžœ žœžœ˜KKšœŸžœ ˜­Kšœ ˜ K˜K˜——šœ™šœ%žœ˜*Kšœ˜Kšœ˜K˜K˜—šœ'žœ˜,Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—šœ)žœ˜.Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—šœ$žœ˜)Kšœ˜K˜K˜—š¡œ˜'K˜Kšœ žœ-˜;Kš œžœžœžœžœžœ˜%Kšœžœ$˜0Kšœ žœ˜%KšœB˜BKšœG˜GKšœL˜LKš œžœžœžœžœžœC˜{Kšœ6˜6Kšœžœ^˜wKšžœžœžœ žœ5˜SKšœj˜jKšœCžœU˜œKšœ ˜ K˜K˜——šœ ™ šœ$žœ˜)Kšœ˜K˜K˜—š¡œ˜,Kšœ žœ-˜;Kšœ2˜2Kšœ2˜2Kšœ4˜4KšœAžœT˜™KšœCžœU˜œK˜K˜——™Kšœ žœ˜)Kšœ žœ˜)šœ žœžœ˜0K˜—š¡œ˜(K˜Kšœ žœ-˜;Kšœy˜yKšœw˜wKšœw˜wKšœ%˜%KšœQžœ˜qKšœPžœ&˜zKšœ ˜ K˜K˜—š¡œ˜+K˜Kšœ žœ-˜;Kšœy˜yKšœw˜wKšœw˜wKšœ%˜%Kšœ#˜#KšœQžœ˜qKšœOžœ˜lKšœPžœ'˜{Kšœ ˜ K˜K˜——™š¡œžœ#˜1š¡œ%˜+Kšœžœ˜š žœžœžœžœž˜,Kšœ)žœ˜=Kšžœ˜—Kšœ%žœ&˜MK˜—KšœC˜CK˜——™ š ¡œžœžœžœžœ˜-Kšœžœžœžœ˜$K˜K˜—š ¡œžœ žœžœžœžœ˜Všœžœ˜+Kšœ˜Kšœ ˜ —Kšžœžœ0žœžœ˜AK˜K˜—š¡œžœžœžœ˜NKšœ žœ˜šžœ žœžœž˜2Kšœžœžœ˜$Kšžœ˜—šžœžœžœž˜)Kšœ žœ˜"Kšžœ˜—K˜K˜—š¡ œžœžœžœ˜Mš¡œžœ˜$Kšœ žœ)˜7Kšžœžœžœ žœ˜OK˜—Kšœ+˜+K˜K˜—š ¡ œžœžœªžœžœžœ˜óKšœ@˜@šžœžœžœž˜0š žœžœžœžœžœž˜Tšžœ.žœ˜6Kšœg˜gK˜$Kšžœ˜Kšœ˜—Kšžœžœžœ˜Kšžœ˜—Kšžœ˜—K˜K˜—š¡ œžœ$žœžœ˜kKšœ+˜+šžœ$žœžœž˜6Kšœ1˜1Kšžœ˜—K˜K˜—š ¡ œžœ$žœžœžœžœ˜xKšœ žœ ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœžœ˜0K˜K˜—š¡œžœ–žœ˜ÉKšœžœ#˜Gšžœ žœžœ˜Kšœ žœ˜%K˜Kšœ˜K˜—Kšœ žœ/˜>šžœžœžœ˜Kšœ;˜;Kš žœžœ!žœ,žœžœ˜aKšœ žœ2˜EK˜—K˜K˜—š ¡ œžœžœžœžœ˜XKšœ žœ ˜Kš žœžœžœžœžœ˜-Kšœ˜Kšœžœ˜0K˜K˜—š¡ œžœ/˜>Kšœžœ˜/Kšœ˜Kšœ˜Kšœ˜Kšœžœ˜3Kšœžœ˜3K˜K˜—š ¡ œžœžœžœžœžœ˜?Kšœžœžœ'˜bK˜K˜—Kšœ žœ˜š ¡ œžœ8žœžœžœ˜fK™(šžœ ™#K™?—š¡œ˜šœžœž˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšžœ˜ —Kšžœžœ žœ˜4Kšœ+˜+K˜—š¡œžœ˜Kšœžœžœ˜*K˜K˜—Kš žœ žœžœ žœžœ˜6šžœ˜Kšœžœ.˜7Kšœ žœ+˜:šžœžœž˜Kšœ5˜5Kšœ5˜5KšœA˜AKšžœ˜—K˜—K˜K˜—š ¡œžœ&žœ&žœžœ˜†šžœ4žœžœž˜FKšœ ˜ šžœžœ!žœ˜-Kšœžœ˜(Kšœžœ˜+Kšœžœ˜)Kšœžœ˜(K˜—Kšžœ˜—K˜K˜—š¡ œžœ9˜Lš ¡ œžœžœžœžœ˜.Kšœ žœ˜%šžœžœžœ˜-Kšœžœžœ˜Kšœžœ˜2K˜—K˜—Kšœ9˜9K˜K˜——šœ ™ ™NK™—šœÏb ™ šœ(žœ˜-Kšœžœ˜Kšœ˜—šœ(žœ˜-Kšœ˜Kšœžœ˜—šœ*žœ˜/Kšœ˜Kšœžœ˜Kšœžœžœ˜—šœ*žœ˜/Kšœ˜Kšœ˜Kšœžœ˜—šœ,žœ˜1Kšœ˜Kšœžœ˜Kšœ˜Kšœžœžœ˜—šœ(žœ˜-Kšœžœ˜Kšœ˜K˜—šœ.žœ˜3Kšœžœ˜Kšœ˜Kšœ˜K˜—K˜—š¢™šœ&žœ˜+Kšœ˜Kšœžœ5˜K—šœ)žœ˜.Kšœ˜Kšœ˜—Kšœ:žœ˜?Kšœ8žœ˜=Kšœ6žœ˜;šœ-žœ™2Kšœ™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šœ<˜