DIRECTORY BitHacks, CoreClasses, CoreCreate, CoreProperties, MSI, Ports, Rosemary; MSIImpl: CEDAR PROGRAM IMPORTS BitHacks, CoreClasses, CoreCreate, CoreProperties, Ports, Rosemary EXPORTS MSI = BEGIN OPEN MSI, CoreCreate; LatchName: ROPE = Rosemary.Register[roseClassName: "Latch", init: LatchInit, evalSimple: LatchSimple]; LatchVdd: NAT = 0; LatchGnd: NAT = 1; LatchLoad: NAT = 2; LatchInput: NAT = 3; LatchOutput: NAT = 4; Latch: PUBLIC PROC RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: LatchName, public: Wires["Vdd", "Gnd", "Load", "Input", "Output"]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: LatchName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[LatchVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[LatchGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[LatchLoad], initType: l]; [] _ Ports.InitPort[wire: ct.public[LatchInput], initType: l]; [] _ Ports.InitPort[wire: ct.public[LatchOutput], initType: l, initDrive: drive]; }; LatchInit: Rosemary.InitProc = { state: REF Ports.Level _ NEW[Ports.Level]; state^ _ X; stateAny _ state; }; LatchSimple: Rosemary.EvalProc = { state: REF Ports.Level _ NARROW[stateAny]; SELECT p[LatchLoad].l FROM H => state^ _ p[LatchInput].l; X => IF state^#p[LatchInput].l THEN state^ _ X; ENDCASE; p[LatchOutput].l _ state^; }; RegisterName: ROPE = Rosemary.Register[roseClassName: "Register", init: RegisterInit, evalSimple: RegisterSimple]; RegVdd: NAT = 0; RegGnd: NAT = 1; RegLoad: NAT = 2; RegInput: NAT = 3; RegOutput: NAT = 4; Register: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: RegisterName, public: Wires["Vdd", "Gnd", "Load", Seq["Input", b], Seq["Output", b]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: RegisterName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[RegVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[RegGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[RegInput], initType: ls]; [] _ Ports.InitPort[wire: ct.public[RegLoad], initType: l]; [] _ Ports.InitPort[wire: ct.public[RegOutput], initType: ls, initDrive: drive]; }; RegisterInit: Rosemary.InitProc = { size: NAT _ p[RegInput].ls.size; state: Ports.LevelSequence _ NEW[Ports.LevelSequenceRec[size]]; FOR i: NAT IN [0..size) DO state[i] _ X; ENDLOOP; stateAny _ state; }; RegisterSimple: Rosemary.EvalProc = { state: Ports.LevelSequence _ NARROW[stateAny]; SELECT p[RegLoad].l FROM H => FOR i: NAT IN [0..p[RegInput].ls.size) DO state[i] _ p[RegInput].ls[i]; ENDLOOP; X => FOR i: NAT IN [0..p[RegInput].ls.size) DO IF state[i]#p[RegInput].ls[i] THEN state[i] _ X; ENDLOOP; ENDCASE; FOR i: NAT IN [0..p[RegOutput].ls.size) DO p[RegOutput].ls[i] _ state[i]; ENDLOOP; }; ConstantName: ROPE = Rosemary.Register[roseClassName: "Constant", init: ConstantInit, evalSimple: ConstantSimple]; ConstantProp: ATOM = CoreProperties.RegisterProperty[prop: $MSIConstant]; ConstantVdd: NAT = 0; ConstantGnd: NAT = 1; ConstantOutput: NAT = 2; Constant: PUBLIC PROC [b: NAT, v: INT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: ConstantName, public: Wires["Vdd", "Gnd", Seq["Output", b]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: ConstantName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[ConstantVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[ConstantGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[ConstantOutput], initType: ls, initDrive: drive]; CoreProperties.PutCellTypeProp[ct, ConstantProp, NEW[INT _ v]]; }; ConstantInit: Rosemary.InitProc = { stateAny _ CoreProperties.GetCellTypeProp[cellType, ConstantProp]; }; ConstantSimple: Rosemary.EvalProc = { state: REF INT _ NARROW[stateAny]; bits: NAT _ p[ConstantOutput].ls.size; FOR i: NAT IN [0..bits) DO p[ConstantOutput].ls[i] _ IF BitHacks.XthBitOfN[x: bits-1-i, n: state^] THEN H ELSE L; ENDLOOP; }; MultiplexorName: ROPE = Rosemary.Register[roseClassName: "Multiplexor", evalSimple: MultiplexorSimple]; MultiplexorSelect: NAT = 0; MultiplexorInput: NAT = 1; MultiplexorOutput: NAT = 2; Multiplexor: PUBLIC PROC [i: NAT _ 2] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: MultiplexorName, public: Wires[Seq["Select", i], Seq["Input", i], "Output"]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: MultiplexorName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[MultiplexorSelect], initType: ls]; [] _ Ports.InitPort[wire: ct.public[MultiplexorInput], initType: ls]; [] _ Ports.InitPort[wire: ct.public[MultiplexorOutput], initType: l, initDrive: drive]; }; MultiplexorSimple: Rosemary.EvalProc = { foundH: BOOL _ FALSE; FOR i: NAT IN [0..p[MultiplexorSelect].ls.size) DO SELECT p[MultiplexorSelect].ls[i] FROM X => {p[MultiplexorOutput].l _ X; EXIT}; H => IF foundH THEN {p[MultiplexorOutput].l _ X; EXIT} ELSE { foundH _ TRUE; p[MultiplexorOutput].l _ p[MultiplexorInput].ls[i]; }; ENDCASE; ENDLOOP; IF NOT foundH THEN p[MultiplexorOutput].l _ X; }; BusMultiplexorName: ROPE = Rosemary.Register[roseClassName: "BusMultiplexor", evalSimple: BusMultiplexorSimple]; BusMultiplexorSelect: NAT = 0; BusMultiplexorInput: NAT = 1; BusMultiplexorOutput: NAT = 2; BusMultiplexor: PUBLIC PROC [b: NAT, i: NAT _ 2] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: BusMultiplexorName, public: Wires[Seq["Select", i], Seq["Input", i, Seq[size: b]], Seq["Output", b]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: BusMultiplexorName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[BusMultiplexorSelect], initType: ls]; FOR in: NAT IN [0..i) DO [] _ Ports.InitPort[wire: ct.public[BusMultiplexorInput][in], initType: ls]; ENDLOOP; [] _ Ports.InitPort[wire: ct.public[BusMultiplexorOutput], initType: ls, initDrive: drive]; }; BusMultiplexorSimple: Rosemary.EvalProc = { SetX: PROC = { FOR bit: NAT IN [0..p[BusMultiplexorOutput].ls.size) DO p[BusMultiplexorOutput].ls[bit] _ X; ENDLOOP; }; foundH: BOOL _ FALSE; FOR i: NAT IN [0..p[BusMultiplexorSelect].ls.size) DO SELECT p[BusMultiplexorSelect].ls[i] FROM X => {SetX[]; EXIT}; H => IF foundH THEN {SetX[]; EXIT} ELSE { foundH _ TRUE; FOR bit: NAT IN [0..p[BusMultiplexorOutput].ls.size) DO p[BusMultiplexorOutput].ls[bit] _ p[BusMultiplexorInput][i].ls[bit]; ENDLOOP; }; ENDCASE; ENDLOOP; IF NOT foundH THEN SetX[]; }; BuffersName: ROPE = Rosemary.Register[roseClassName: "Buffers", evalSimple: BuffersSimple]; BuffersVdd: NAT = 0; BuffersGnd: NAT = 1; BuffersInput: NAT = 2; BuffersOutput: NAT = 3; Buffers: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: BuffersName, public: Wires["Vdd", "Gnd", Seq["Input", b], Seq["Output", b]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: BuffersName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[BuffersVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[BuffersGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[BuffersInput], initType: ls]; [] _ Ports.InitPort[wire: ct.public[BuffersOutput], initType: ls, initDrive: drive]; }; BuffersSimple: Rosemary.EvalProc = { FOR i: NAT IN [0..p[BuffersInput].ls.size) DO p[BuffersOutput].ls[i] _ p[BuffersInput].ls[i]; ENDLOOP; }; TristateBuffersName: ROPE = Rosemary.Register[roseClassName: "TristateBuffers", evalSimple: TristateBuffersSimple]; TristateBuffersVdd: NAT = 0; TristateBuffersGnd: NAT = 1; TristateBuffersDrive: NAT = 2; TristateBuffersInput: NAT = 3; TristateBuffersOutput: NAT = 4; TristateBuffers: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: TristateBuffersName, public: Wires["Vdd", "Gnd", "Drive", Seq["Input", b], Seq["Output", b]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: TristateBuffersName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[TristateBuffersVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[TristateBuffersGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[TristateBuffersDrive], initType: l]; [] _ Ports.InitPort[wire: ct.public[TristateBuffersInput], initType: ls]; [] _ Ports.InitPort[wire: ct.public[TristateBuffersOutput], initType: ls]; }; TristateBuffersSimple: Rosemary.EvalProc = { p[TristateBuffersOutput].d _ IF p[TristateBuffersDrive].l#L THEN drive ELSE none; FOR i: NAT IN [0..p[TristateBuffersInput].ls.size) DO p[TristateBuffersOutput].ls[i] _ p[TristateBuffersInput].ls[i]; ENDLOOP; }; AdderName: ROPE = Rosemary.Register[roseClassName: "Adder", evalSimple: AdderSimple]; AdderVdd: NAT = 0; AdderGnd: NAT = 1; AdderCarryIn: NAT = 2; AdderA: NAT = 3; AdderB: NAT = 4; AdderSum: NAT = 5; AdderCarryOut: NAT = 6; Adder: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: AdderName, public: Wires["Vdd", "Gnd", "CarryIn", Seq["A", b], Seq["B", b], Seq["Sum", b], "CarryOut"]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: AdderName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[AdderVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[AdderGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[AdderCarryIn], initType: l]; [] _ Ports.InitPort[wire: ct.public[AdderA], initType: ls]; [] _ Ports.InitPort[wire: ct.public[AdderB], initType: ls]; [] _ Ports.InitPort[wire: ct.public[AdderSum], initType: ls, initDrive: drive]; [] _ Ports.InitPort[wire: ct.public[AdderCarryOut], initType: l, initDrive: drive]; }; AdderSimple: Rosemary.EvalProc = { carry: Ports.Level _ p[AdderCarryIn].l; FOR i: NAT DECREASING IN [0..p[AdderA].ls.size) DO a: Ports.Level _ p[AdderA].ls[i]; b: Ports.Level _ p[AdderB].ls[i]; IF carry=X OR a=X OR b=X THEN { p[AdderSum].ls[i] _ X; carry _ X; } ELSE { ba: BOOL _ IF a=H THEN TRUE ELSE FALSE; bb: BOOL _ IF b=H THEN TRUE ELSE FALSE; bc: BOOL _ IF carry=H THEN TRUE ELSE FALSE; p[AdderSum].ls[i] _ IF BXor[ba, BXor[bb, bc]] THEN H ELSE L; carry _ IF (ba AND (bb OR bc)) OR (bb AND bc) THEN H ELSE L; }; ENDLOOP; p[AdderCarryOut].l _ carry; }; ComparatorName: ROPE = Rosemary.Register[roseClassName: "Comparator", evalSimple: ComparatorSimple]; CmpVdd: NAT = 0; CmpGnd: NAT = 1; CmpA: NAT = 2; CmpB: NAT = 3; CmpAEqB: NAT = 4; Comparator: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: ComparatorName, public: Wires["Vdd", "Gnd", Seq["A", b], Seq["B", b], "AEqB"]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: ComparatorName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[CmpVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[CmpGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[CmpA], initType: ls]; [] _ Ports.InitPort[wire: ct.public[CmpB], initType: ls]; [] _ Ports.InitPort[wire: ct.public[CmpAEqB], initType: l, initDrive: drive]; }; ComparatorSimple: Rosemary.EvalProc = { p[CmpAEqB].l _ H; FOR i: NAT IN [0..p[CmpA].ls.size) DO IF p[CmpA].ls[i]#p[CmpB].ls[i] THEN p[CmpAEqB].l _ L; IF p[CmpA].ls[i]=X OR p[CmpB].ls[i]=X THEN {p[CmpAEqB].l _ X; EXIT}; ENDLOOP; }; DecoderName: ROPE = Rosemary.Register[roseClassName: "Decoder", evalSimple: DecoderSimple]; DecoderVdd: NAT = 0; DecoderGnd: NAT = 1; DecoderAddress: NAT = 2; DecoderSelect: NAT = 3; ClockedDecoderClock: NAT = 4; Decoder: PUBLIC PROC [a: NAT, s: NAT _ 0] RETURNS [ct: CellType] = { IF s=0 THEN s _ BitHacks.TwoToThe[a]; ct _ CoreClasses.CreateUnspecified[ name: DecoderName, public: Wires["Vdd", "Gnd", Seq["Address", a], Seq["Select", s]]]; InitDecoder[ct]; }; ClockedDecoder: PUBLIC PROC [a: NAT, s: NAT _ 0] RETURNS [ct: CellType] = { IF s=0 THEN s _ BitHacks.TwoToThe[a]; ct _ CoreClasses.CreateUnspecified[ name: "ClockedDecoder", public: Wires["Vdd", "Gnd", Seq["Address", a], Seq["Select", s], "Clock"]]; InitDecoder[ct]; [] _ Ports.InitPort[wire: ct.public[ClockedDecoderClock], initType: l]; }; InitDecoder: PROC [ct: CellType] = { [] _ Rosemary.BindCellType[cellType: ct, roseClassName: DecoderName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[DecoderVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[DecoderGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[DecoderAddress], initType: ls]; [] _ Ports.InitPort[wire: ct.public[DecoderSelect], initType: ls, initDrive: drive]; }; DecoderSimple: Rosemary.EvalProc = { SetLevel: PROC[l: Ports.Level] = { FOR i: NAT IN [0..p[DecoderSelect].ls.size) DO p[DecoderSelect].ls[i] _ l; ENDLOOP; }; clocked: BOOL _ p.size-1=ClockedDecoderClock; IF clocked AND p[ClockedDecoderClock].l=X THEN SetLevel[X] ELSE { SetLevel[L]; IF NOT clocked OR p[ClockedDecoderClock].l=H THEN { bits: NAT _ p[DecoderAddress].ls.size; address: NAT _ 0; FOR i: NAT IN [0..bits) DO SELECT p[DecoderAddress].ls[i] FROM L => address _ 2*address; H => address _ (2*address) + 1; X => SetLevel[X]; ENDCASE => ERROR; ENDLOOP; IF address>p[DecoderSelect].ls.size THEN SIGNAL Rosemary.Stop[]; p[DecoderSelect].ls[address] _ H; }; }; }; ShiftRegisterName: ROPE = Rosemary.Register[roseClassName: "ShiftRegister", init: ShiftRegisterInit, evalSimple: ShiftRegisterSimple]; ShiftRegisterVdd: NAT = 0; ShiftRegisterGnd: NAT = 1; ShiftRegisterShiftA: NAT = 2; ShiftRegisterShiftB: NAT = 3; ShiftRegisterLoadA: NAT = 4; ShiftRegisterLeftNRight: NAT = 5; ShiftRegisterLeftInput: NAT = 6; ShiftRegisterRightInput: NAT = 7; ShiftRegisterInput: NAT = 8; ShiftRegisterOutput: NAT = 9; ShiftRegister: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: ShiftRegisterName, public: Wires["Vdd", "Gnd", "ShiftA", "ShiftB", "LoadA", "LeftNRight", "LeftInput", "RightInput", Seq["Input", b], Seq["Output", b]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: ShiftRegisterName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[ShiftRegisterVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[ShiftRegisterGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[ShiftRegisterShiftA], initType: l]; [] _ Ports.InitPort[wire: ct.public[ShiftRegisterShiftB], initType: l]; [] _ Ports.InitPort[wire: ct.public[ShiftRegisterLoadA], initType: l]; [] _ Ports.InitPort[wire: ct.public[ShiftRegisterLeftNRight], initType: l]; [] _ Ports.InitPort[wire: ct.public[ShiftRegisterLeftInput], initType: l]; [] _ Ports.InitPort[wire: ct.public[ShiftRegisterRightInput], initType: l]; [] _ Ports.InitPort[wire: ct.public[ShiftRegisterInput], initType: ls]; [] _ Ports.InitPort[wire: ct.public[ShiftRegisterOutput], initType: ls, initDrive: drive]; }; ShiftRegisterState: TYPE = REF ShiftRegisterStateRec; ShiftRegisterStateRec: TYPE = RECORD [ a: Ports.LevelSequence _ NIL, b: Ports.LevelSequence _ NIL]; ShiftRegisterInit: Rosemary.InitProc = { state: ShiftRegisterState _ NEW[ShiftRegisterStateRec]; size: NAT _ p[ShiftRegisterOutput].ls.size; state.a _ NEW[Ports.LevelSequenceRec[size]]; state.b _ NEW[Ports.LevelSequenceRec[size]]; FOR i: NAT IN [0..size) DO state.a[i] _ state.b[i] _ X; ENDLOOP; stateAny _ state; }; ShiftRegisterSimple: Rosemary.EvalProc = { SetX: PROC = { FOR bit: NAT IN [0..sizeMOne] DO state.a[bit] _ state.b[bit] _ p[ShiftRegisterOutput].ls[bit] _ X; ENDLOOP; }; state: ShiftRegisterState _ NARROW[stateAny]; sizeMOne: NAT _ p[ShiftRegisterInput].ls.size-1; IF p[ShiftRegisterShiftA].l=X OR p[ShiftRegisterShiftB].l=X OR p[ShiftRegisterLoadA].l=X OR (p[ShiftRegisterShiftA].l#L AND p[ShiftRegisterLoadA].l#L) THEN SetX[] ELSE { IF p[ShiftRegisterShiftA].l=H THEN { IF p[ShiftRegisterLeftNRight].l=X THEN SetX[] ELSE { IF p[ShiftRegisterLeftNRight].l=H THEN { FOR i: NAT IN [0..sizeMOne) DO state.a[i] _ state.b[i+1]; ENDLOOP; state.a[sizeMOne] _ p[ShiftRegisterRightInput].l; } ELSE { FOR i: NAT DECREASING IN [0..sizeMOne) DO state.a[i+1] _ state.b[i]; ENDLOOP; state.a[0] _ p[ShiftRegisterLeftInput].l; }; }; }; IF p[ShiftRegisterLoadA].l=H THEN { FOR i: NAT IN [0..sizeMOne] DO state.a[i] _ p[ShiftRegisterInput].ls[i]; ENDLOOP; }; IF p[ShiftRegisterShiftB].l=H THEN { FOR i: NAT IN [0..sizeMOne] DO state.b[i] _ state.a[i]; ENDLOOP; }; FOR i: NAT IN [0..sizeMOne] DO p[ShiftRegisterOutput].ls[i] _ state.b[i]; ENDLOOP; }; }; CounterName: ROPE = Rosemary.Register[roseClassName: "Counter", init: CounterInit, evalSimple: CounterSimple]; CounterVdd: NAT = 0; CounterGnd: NAT = 1; CounterCountA: NAT = 2; CounterCountB: NAT = 3; CounterLoadA: NAT = 4; CounterUpNDown: NAT = 5; CounterInput: NAT = 6; CounterOutput: NAT = 7; Counter: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: CounterName, public: Wires["Vdd", "Gnd", "CountA", "CountB", "LoadA", "UpNDown", Seq["Input", b], Seq["Output", b]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: CounterName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[CounterVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[CounterGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[CounterCountA], initType: l]; [] _ Ports.InitPort[wire: ct.public[CounterCountB], initType: l]; [] _ Ports.InitPort[wire: ct.public[CounterLoadA], initType: l]; [] _ Ports.InitPort[wire: ct.public[CounterUpNDown], initType: l]; [] _ Ports.InitPort[wire: ct.public[CounterInput], initType: ls]; [] _ Ports.InitPort[wire: ct.public[CounterOutput], initType: ls, initDrive: drive]; }; CounterState: TYPE = REF CounterStateRec; CounterStateRec: TYPE = RECORD [ a: Ports.LevelSequence _ NIL, b: Ports.LevelSequence _ NIL]; CounterInit: Rosemary.InitProc = { state: CounterState _ NEW[CounterStateRec]; size: NAT _ p[CounterOutput].ls.size; state.a _ NEW[Ports.LevelSequenceRec[size]]; state.b _ NEW[Ports.LevelSequenceRec[size]]; FOR i: NAT IN [0..size) DO state.a[i] _ state.b[i] _ X; ENDLOOP; stateAny _ state; }; CounterSimple: Rosemary.EvalProc = { SetX: PROC = { FOR bit: NAT IN [0..size) DO state.a[bit] _ state.b[bit] _ p[CounterOutput].ls[bit] _ X; ENDLOOP; }; state: CounterState _ NARROW[stateAny]; size: NAT _ p[CounterInput].ls.size; IF p[CounterCountA].l=X OR p[CounterCountB].l=X OR p[CounterLoadA].l=X OR (p[CounterCountA].l#L AND p[CounterLoadA].l#L) THEN SetX[] ELSE { IF p[CounterCountA].l=H THEN { IF p[CounterUpNDown].l=X THEN SetX[] ELSE { IF p[CounterUpNDown].l=H THEN { carry: Ports.Level _ H; FOR i: NAT DECREASING IN [0..size) DO state.a[i] _ IF carry=X OR state.b[i]=X THEN X ELSE IF BXor[carry=H, state.b[i]=H] THEN H ELSE L; carry _ IF carry=X OR state.b[i]=X THEN X ELSE IF carry=H AND state.b[i]=H THEN H ELSE L; ENDLOOP; } ELSE { borrow: Ports.Level _ H; FOR i: NAT DECREASING IN [0..size) DO state.a[i] _ IF borrow=X OR state.b[i]=X THEN X ELSE IF BXor[borrow=H, state.b[i]=H] THEN H ELSE L; borrow _ IF borrow=X OR state.b[i]=X THEN X ELSE IF borrow=H AND state.b[i]=L THEN H ELSE L; ENDLOOP; }; }; }; IF p[CounterLoadA].l=H THEN { FOR i: NAT IN [0..size) DO state.a[i] _ p[CounterInput].ls[i]; ENDLOOP; }; IF p[CounterCountB].l=H THEN { FOR i: NAT IN [0..size) DO state.b[i] _ state.a[i]; ENDLOOP; }; FOR i: NAT IN [0..size) DO p[CounterOutput].ls[i] _ state.b[i]; ENDLOOP; }; }; RegisterFileName: ROPE = Rosemary.Register[roseClassName: "RegisterFile", init: RegisterFileInit, evalSimple: RegisterFileSimple]; RegisterFileProp: ATOM = CoreProperties.RegisterProperty[prop: $MSIRegisterFile]; RegisterFileVdd: NAT = 0; RegisterFileGnd: NAT = 1; RegisterFileLoad: NAT = 2; RegisterFileAddress: NAT = 3; RegisterFileInput: NAT = 4; RegisterFileOutput: NAT = 5; RegisterFile: PUBLIC PROC [b: NAT, a: NAT, w: NAT _ 0] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: RegisterFileName, public: Wires["Vdd", "Gnd", "Load", Seq["Address", a], Seq["Input", b], Seq["Output", b]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: RegisterFileName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[RegisterFileVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[RegisterFileGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[RegisterFileLoad], initType: l]; [] _ Ports.InitPort[wire: ct.public[RegisterFileAddress], initType: ls]; [] _ Ports.InitPort[wire: ct.public[RegisterFileInput], initType: ls]; [] _ Ports.InitPort[wire: ct.public[RegisterFileOutput], initType: ls, initDrive: drive]; IF w=0 THEN w _ BitHacks.TwoToThe[a]; CoreProperties.PutCellTypeProp[ct, RegisterFileProp, NEW[NAT _ w]]; }; RegisterFileState: TYPE = REF RegisterFileStateRec; RegisterFileStateRec: TYPE = RECORD [ bits: SEQUENCE size: NAT OF Ports.LevelSequence]; RegisterFileInit: Rosemary.InitProc = { words: NAT _ NARROW[CoreProperties.GetCellTypeProp[cellType, RegisterFileProp], REF NAT]^; bits: NAT _ p[RegisterFileOutput].ls.size; state: RegisterFileState _ NEW[RegisterFileStateRec[words]]; FOR w: NAT IN [0..words) DO state[w] _ NEW[Ports.LevelSequenceRec[bits]]; FOR b: NAT IN [0..bits) DO state[w][b] _ X; ENDLOOP; ENDLOOP; stateAny _ state; }; RegisterFileSimple: Rosemary.EvalProc = { state: RegisterFileState _ NARROW[stateAny]; words: NAT _ state.size; bits: NAT _ p[RegisterFileOutput].ls.size; adr: NAT _ 0; FOR a: NAT IN [0..p[RegisterFileAddress].ls.size) DO aBit: Ports.Level _ p[RegisterFileAddress].ls[a]; IF aBit=X THEN { IF p[RegisterFileLoad].l#L THEN FOR w: NAT IN [0..words) DO FOR b: NAT IN [0..bits) DO state[w][b] _ X; ENDLOOP; ENDLOOP; FOR b: NAT IN [0..bits) DO p[RegisterFileOutput].ls[b] _ X; ENDLOOP; EXIT; } ELSE adr _ 2*adr + (IF p[RegisterFileAddress].ls[a]=H THEN 1 ELSE 0); REPEAT FINISHED => { IF p[RegisterFileLoad].l=H THEN FOR b: NAT IN [0..bits) DO state[adr][b] _ p[RegisterFileInput].ls[b]; ENDLOOP ELSE IF p[RegisterFileLoad].l=X THEN FOR b: NAT IN [0..bits) DO state[adr][b] _ X; ENDLOOP; FOR b: NAT IN [0..bits) DO p[RegisterFileOutput].ls[b] _ state[adr][b]; ENDLOOP; } ENDLOOP; }; MultiPortRegisterFileName: ROPE = Rosemary.Register[roseClassName: "MultiPortRegisterFile", init: MultiPortRegisterFileInit, evalSimple: MultiPortRegisterFileSimple]; MultiPortRegisterFileProp: ATOM = CoreProperties.RegisterProperty[prop: $MSIMultiPortRegisterFile]; MultiPortRegisterFileVdd: NAT = 0; MultiPortRegisterFileGnd: NAT = 1; MultiPortRegisterFileLoad: NAT = 2; MultiPortRegisterFileWriteAddress: NAT = 3; MultiPortRegisterFileReadAddress: NAT = 4; MultiPortRegisterFileInput: NAT = 5; MultiPortRegisterFileOutput: NAT = 6; MultiPortRegisterFile: PUBLIC PROC [b: NAT, a: NAT, w: NAT _ 0, rp: NAT _ 1, wp: NAT _ 1] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[ name: MultiPortRegisterFileName, public: Wires["Vdd", "Gnd", Seq["Load", wp], Seq["WriteAddress", wp, Seq[size: a]], Seq["ReadAddress", rp, Seq[size: a]], Seq["Input", wp, Seq[size: b]], Seq["Output", rp, Seq[size: b]]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: MultiPortRegisterFileName]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: "MSI"]; [] _ Ports.InitPort[wire: ct.public[MultiPortRegisterFileVdd], initType: l]; [] _ Ports.InitPort[wire: ct.public[MultiPortRegisterFileGnd], initType: l]; [] _ Ports.InitPort[wire: ct.public[MultiPortRegisterFileLoad], initType: ls]; FOR port: NAT IN [0..wp) DO [] _ Ports.InitPort[wire: ct.public[MultiPortRegisterFileWriteAddress][port], initType: ls]; [] _ Ports.InitPort[wire: ct.public[MultiPortRegisterFileInput][port], initType: ls]; ENDLOOP; FOR port: NAT IN [0..rp) DO [] _ Ports.InitPort[wire: ct.public[MultiPortRegisterFileReadAddress][port], initType: ls]; [] _ Ports.InitPort[wire: ct.public[MultiPortRegisterFileOutput][port], initType: ls, initDrive: drive]; ENDLOOP; IF w=0 THEN w _ BitHacks.TwoToThe[a]; CoreProperties.PutCellTypeProp[ct, MultiPortRegisterFileProp, NEW[NAT _ w]]; }; MultiPortRegisterFileState: TYPE = REF MultiPortRegisterFileStateRec; MultiPortRegisterFileStateRec: TYPE = RECORD [ bits: SEQUENCE size: NAT OF Ports.LevelSequence]; MultiPortRegisterFileInit: Rosemary.InitProc = { words: NAT _ NARROW[CoreProperties.GetCellTypeProp[cellType, MultiPortRegisterFileProp], REF NAT]^; bits: NAT _ p[MultiPortRegisterFileOutput][0].ls.size; state: MultiPortRegisterFileState _ NEW[MultiPortRegisterFileStateRec[words]]; FOR w: NAT IN [0..words) DO state[w] _ NEW[Ports.LevelSequenceRec[bits]]; FOR b: NAT IN [0..bits) DO state[w][b] _ X; ENDLOOP; ENDLOOP; stateAny _ state; }; MultiPortRegisterFileSimple: Rosemary.EvalProc = { state: MultiPortRegisterFileState _ NARROW[stateAny]; words: NAT _ state.size; bits: NAT _ p[MultiPortRegisterFileOutput][0].ls.size; FOR port: NAT IN [0..p[MultiPortRegisterFileInput].size) DO adr: NAT _ 0; FOR a: NAT IN [0..p[MultiPortRegisterFileWriteAddress][port].ls.size) DO aBit: Ports.Level _ p[MultiPortRegisterFileWriteAddress][port].ls[a]; IF aBit=X THEN { IF p[MultiPortRegisterFileLoad].ls[port]#L THEN FOR w: NAT IN [0..words) DO FOR b: NAT IN [0..bits) DO state[w][b] _ X; ENDLOOP; ENDLOOP; EXIT; } ELSE adr _ 2*adr + (IF p[MultiPortRegisterFileWriteAddress][port].ls[a]=H THEN 1 ELSE 0); REPEAT FINISHED => { IF p[MultiPortRegisterFileLoad].ls[port]=H THEN FOR b: NAT IN [0..bits) DO state[adr][b] _ p[MultiPortRegisterFileInput][port].ls[b]; ENDLOOP ELSE IF p[MultiPortRegisterFileLoad].ls[port]=X THEN FOR b: NAT IN [0..bits) DO state[adr][b] _ X; ENDLOOP; } ENDLOOP; ENDLOOP; FOR port: NAT IN [0..p[MultiPortRegisterFileOutput].size) DO adr: NAT _ 0; FOR a: NAT IN [0..p[MultiPortRegisterFileReadAddress][port].ls.size) DO aBit: Ports.Level _ p[MultiPortRegisterFileReadAddress][port].ls[a]; IF aBit=X THEN { FOR b: NAT IN [0..bits) DO p[MultiPortRegisterFileOutput][port].ls[b] _ X; ENDLOOP; EXIT; } ELSE adr _ 2*adr + (IF p[MultiPortRegisterFileReadAddress][port].ls[a]=H THEN 1 ELSE 0); REPEAT FINISHED => { FOR b: NAT IN [0..bits) DO p[MultiPortRegisterFileOutput][port].ls[b] _ state[adr][b]; ENDLOOP; } ENDLOOP; ENDLOOP; }; BXor: PROC [x, y: BOOL] RETURNS [z: BOOL] = { z _ (x AND NOT y) OR (NOT x AND y) }; END. MSIImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Barth, May 20, 1986 5:04:05 pm PDT Latch Register Constant Multiplexor BusMultiplexor Buffers TristateBuffers Adder Comparator Decoders ShiftRegister Counter RegisterFile MultiPortRegisterFile สบ– "cedar" style˜codešœ ™ Kšœ ฯmœ1™˜>KšœQ˜QKšœ˜K˜—š  œ˜ Kšœžœžœ˜*K˜ Kšœ˜Kšœ˜K˜—š  œ˜"Kšœžœžœ ˜*šžœž˜Kšœ˜Kšœžœžœ ˜/Kšžœ˜—Kšœ˜Kšœ˜K˜——šœ™Kš  œžœ`˜rKš œžœ˜Kš œžœ˜Kš œžœ˜Kš œžœ˜Kš  œžœ˜K˜š  œžœžœžœžœ˜9šœ#˜#Kšœ˜KšœH˜H—KšœF˜FKšœ3˜3Kšœ:˜:Kšœ:˜:Kšœ=˜=Kšœ;˜;KšœP˜PKšœ˜K˜—š  œ˜#Kšœžœ˜ Kšœžœ˜?Kš žœžœžœ žœžœ˜1Kšœ˜Kšœ˜K˜—š œ˜%Kšœžœ ˜.šžœž˜šœžœžœžœž˜.Kšœ˜Kšžœ˜—šœžœžœžœž˜.Kšžœžœ˜0Kšžœ˜—Kšžœ˜—šžœžœžœž˜*Kšœ˜Kšžœ˜—Kšœ˜K˜——š ™Kš  œžœ`˜rKš  œžœ7˜IKš  œžœ˜Kš  œžœ˜Kš œžœ˜K˜š  œžœžœžœžœžœ˜Ašœ#˜#Kšœ˜Kšœ/˜/—KšœF˜FKšœ3˜3Kšœ?˜?Kšœ?˜?KšœU˜UKšœ1žœžœ˜?Kšœ˜K˜—š  œ˜#KšœB˜BKšœ˜K˜—š œ˜%Kšœžœžœžœ ˜"Kšœžœ˜&šžœžœžœ ž˜Kšœžœ,žœžœ˜VKšžœ˜—Kšœ˜K˜——š  ™ Kš œžœR˜gKš œžœ˜Kš œžœ˜Kš œžœ˜K˜š   œžœžœžœžœ˜@šœ#˜#Kšœ˜Kšœ<˜<—KšœI˜IKšœ3˜3KšœF˜FKšœE˜EKšœW˜WKšœ˜K˜—š œ˜(Kšœžœžœ˜šžœžœžœ#ž˜2šžœž˜&Kšœ"žœ˜(š œžœžœžœžœ˜=Kšœ žœ˜Kšœ3˜3K˜—Kšžœ˜—Kšžœ˜—Kšžœžœžœ˜.Kšœ˜K˜——š ™Kš œžœX˜pKš œžœ˜Kš œžœ˜Kš œžœ˜K˜š  œžœžœžœžœžœ˜Kšœ#˜#Kšœ˜KšœR˜R—KšœL˜LKšœ3˜3KšœI˜Išžœžœžœž˜KšœL˜LKšžœ˜—Kšœ[˜[Kšœ˜K˜—š œ˜+K˜š œžœ˜šžœžœžœ&ž˜7Kšœ$˜$Kšžœ˜—K˜K˜—Kšœžœžœ˜šžœžœžœ&ž˜5šžœž˜)Kšœžœ˜š œžœžœ žœžœ˜)Kšœ žœ˜šžœžœžœ&ž˜7KšœD˜DKšžœ˜—K˜—Kšžœ˜—Kšžœ˜—Kšžœžœžœ˜Kšœ˜K˜——š ™Kš  œžœJ˜[Kš  œžœ˜Kš  œžœ˜Kš  œžœ˜Kš  œžœ˜K˜š  œžœžœžœžœ˜8šœ#˜#Kšœ˜Kšœ@˜@—KšœE˜EKšœ3˜3Kšœ>˜>Kšœ>˜>KšœA˜AKšœT˜TKšœ˜K˜—š  œ˜$šžœžœžœž˜-Kšœ/˜/Kšžœ˜—Kšœ˜K˜——š ™Kš œžœZ˜sKš œžœ˜Kš œžœ˜Kš œžœ˜Kš œžœ˜Kš œžœ˜K˜š  œžœžœžœžœ˜@šœ#˜#Kšœ˜KšœI˜I—KšœM˜MKšœ3˜3KšœF˜FKšœF˜FKšœH˜HKšœI˜IKšœJ˜JKšœ˜K˜—š œ˜,Kšœžœžœžœ˜Qšžœžœžœ&ž˜5Kšœ?˜?Kšžœ˜—Kšœ˜K˜——š ™Kš  œžœF˜UKš œžœ˜Kš œžœ˜Kš  œžœ˜Kš œžœ˜Kš œžœ˜Kš œžœ˜Kš  œžœ˜K˜š  œžœžœžœžœ˜6šœ#˜#Kšœ˜Kšœ]˜]—KšœC˜CKšœ3˜3Kšœ<˜˜>Kšœ>˜>KšœC˜CKšœT˜TKšœ˜K˜—š  œ˜$K˜š œžœ˜"šžœžœžœž˜.Kšœ˜Kšžœ˜—K˜K˜—Kšœ žœ ˜-Kšžœ žœžœ ˜:šžœ˜Kšœ ˜ šžœžœ žœžœ˜3Kšœžœ˜&Kšœ žœ˜šžœžœžœ ž˜šžœž˜#Kšœ˜Kšœ˜Kšœ˜Kšžœžœ˜—Kšžœ˜—Kšžœ"žœžœ˜@Kšœ!˜!K˜—Kšœ˜—Kšœ˜K˜——š  ™ Kš œžœo˜†Kš œžœ˜Kš œžœ˜Kš œžœ˜Kš œžœ˜Kš œžœ˜Kš œžœ˜!Kš œžœ˜ Kš œžœ˜!Kš œžœ˜Kš œžœ˜K˜š   œžœžœžœžœ˜>šœ#˜#Kšœ˜Kšœ†˜†—KšœK˜KKšœ3˜3KšœD˜DKšœD˜DKšœG˜GKšœG˜GKšœF˜FKšœK˜KKšœJ˜JKšœK˜KKšœG˜GKšœZ˜ZKšœ˜K˜—Kšœžœžœ˜5šœžœžœ˜&Kšœžœ˜Kšœžœ˜K˜—š œ˜(Kšœžœ˜7Kšœžœ"˜+Kšœ žœ˜,Kšœ žœ˜,Kš žœžœžœ žœžœ˜@Kšœ˜Kšœ˜K˜—š œ˜*K˜š œžœ˜šžœžœžœž˜ KšœA˜AKšžœ˜—K˜K˜—Kšœžœ ˜-Kšœ žœ#˜0Kš žœžœžœžœžœžœ˜ขšžœ˜šžœžœ˜$Kšžœ žœ˜-šžœ˜šžœ žœ˜(šžœžœžœž˜Kšœ˜Kšžœ˜—Kšœ1˜1K˜—šžœ˜š žœžœž œžœž˜)Kšœ˜Kšžœ˜—Kšœ)˜)K˜—K˜—K˜—šžœžœ˜#šžœžœžœž˜Kšœ)˜)Kšžœ˜—K˜—šžœžœ˜$šžœžœžœž˜Kšœ˜Kšžœ˜—K˜—šžœžœžœž˜Kšœ*˜*Kšžœ˜—Kšœ˜—Kšœ˜K˜——š ™Kš  œžœ]˜nKš  œžœ˜Kš  œžœ˜Kš  œžœ˜Kš  œžœ˜Kš  œžœ˜Kš œžœ˜Kš  œžœ˜Kš  œžœ˜K˜š  œžœžœžœžœ˜8šœ#˜#Kšœ˜Kšœh˜h—KšœE˜EKšœ3˜3Kšœ>˜>Kšœ>˜>KšœA˜AKšœA˜AKšœ@˜@KšœB˜BKšœA˜AKšœT˜TKšœ˜K˜—Kšœžœžœ˜)šœžœžœ˜ Kšœžœ˜Kšœžœ˜K˜—š  œ˜"Kšœžœ˜+Kšœžœ˜%Kšœ žœ˜,Kšœ žœ˜,Kš žœžœžœ žœžœ˜@Kšœ˜Kšœ˜K˜—š  œ˜$K˜š œžœ˜šžœžœžœ ž˜Kšœ;˜;Kšžœ˜—Kšœ˜K˜—Kšœžœ ˜'Kšœžœ˜$Kšžœžœฯtœžœžœžœžœ˜„šžœ˜šžœžœ˜Kšžœžœ˜$šžœ˜šžœžœ˜Kšœ˜šžœžœž œ ž˜%Kšœ žœ žœžœžœžœžœžœ˜aKšœžœ žœžœžœžœ žœžœžœ˜YKšžœ˜—K˜—šžœ˜Kšœ˜šžœžœž œ ž˜%Kšœ žœ žœžœžœžœžœžœ˜cKšœ žœ žœžœžœžœ žœžœžœ˜\Kšžœ˜—K˜—K˜—K˜—šžœžœ˜šžœžœžœ ž˜Kšœ#˜#Kšžœ˜—K˜—šžœžœ˜šžœžœžœ ž˜Kšœ˜Kšžœ˜—K˜—šžœžœžœ ž˜Kšœ$˜$Kšžœ˜—Kšœ˜—Kšœ˜K˜——š  ™ Kš œžœl˜‚Kš œžœ;˜QKš œžœ˜Kš œžœ˜Kš œžœ˜Kš œžœ˜Kš œžœ˜Kš œžœ˜K˜š  œžœžœžœžœžœžœ˜Qšœ#˜#Kšœ˜Kšœ[˜[—KšœJ˜JKšœ3˜3KšœC˜CKšœC˜CKšœD˜DKšœH˜HKšœF˜FKšœY˜YKšžœžœ˜%Kšœ5žœžœ˜CKšœ˜K˜—Kšœžœžœ˜3šœžœžœ˜%Kšœžœžœžœ˜1K˜—š œ˜'Kš œžœžœ=žœžœ˜ZKšœžœ!˜*Kšœžœ˜<šžœžœžœ ž˜Kšœ žœ˜-šžœžœžœ ž˜Kšœ˜Kšžœ˜—Kšžœ˜—Kšœ˜Kšœ˜K˜—š œ˜)Kšœžœ ˜,Kšœžœ˜Kšœžœ!˜*Kšœžœ˜ šžœžœžœ%ž˜4Kšœ1˜1šžœžœ˜š žœžœžœžœžœ ž˜;šžœžœžœ ž˜Kšœ˜Kšžœ˜—Kšžœ˜—šžœžœžœ ž˜Kšœ ˜ Kšžœ˜—Kšžœ˜K˜—Kšžœžœ žœžœ˜Ešžœžœ˜š žœžœžœžœžœ ž˜:Kšœ+˜+Kšž˜—š žœžœžœžœžœžœ ž˜?Kšœ˜Kšžœ˜—šžœžœžœ ž˜Kšœ,˜,Kšžœ˜—K˜—Kšžœ˜—Kšœ˜K˜——š ™Kš œžœ‡˜ฆKš œžœD˜cKš œžœ˜"Kš œžœ˜"Kš œžœ˜#Kš !œžœ˜+Kš  œžœ˜*Kš œžœ˜$Kš œžœ˜%K˜š œžœžœžœžœžœ žœ žœžœ˜tšœ#˜#Kšœ ˜ Kšœผ˜ผ—KšœS˜SKšœ3˜3KšœL˜LKšœL˜LKšœN˜Nšžœžœžœ ž˜Kšœ\˜\KšœU˜UKšžœ˜—šžœžœžœ ž˜Kšœ[˜[Kšœh˜hKšžœ˜—Kšžœžœ˜%Kšœ>žœžœ˜LKšœ˜K˜—Kšœžœžœ˜Ešœžœžœ˜.Kšœžœžœžœ˜1K˜—š œ˜0Kš œžœžœFžœžœ˜cKšœžœ-˜6Kšœ$žœ'˜Nšžœžœžœ ž˜Kšœ žœ˜-šžœžœžœ ž˜Kšœ˜Kšžœ˜—Kšžœ˜—Kšœ˜Kšœ˜K˜—š œ˜2Kšœ$žœ ˜5Kšœžœ˜Kšœžœ-˜6šžœžœžœ)ž˜;Kšœžœ˜ šžœžœžœ9ž˜HKšœE˜Ešžœžœ˜š žœ)žœžœžœžœ ž˜Kšžœžœžœ ž˜Kšœ˜Kšžœ˜—Kšžœ˜—Kšžœ˜K˜—Kšžœžœ4žœžœ˜Yšžœžœ˜š žœ)žœžœžœžœ ž˜JKšœ:˜:Kšž˜—š žœžœ)žœžœžœžœ ž˜OKšœ˜Kšžœ˜—K˜—Kšžœ˜—Kšžœ˜—šžœžœžœ*ž˜