<> <> DIRECTORY Basics, BitmapViewer, ImagerPixelMaps, ImagerPixelMapsExtras, Rope, Sage, TerminalIO, ViewRec; CrossRAMTest: CEDAR PROGRAM IMPORTS Basics, BitmapViewer, ImagerPixelMaps, ImagerPixelMapsExtras, Sage, TerminalIO, ViewRec = BEGIN OPEN Sage; HM6116: BOOL = FALSE; -- False means CrossRAM DefaultAddressState: DriveState = H; <> UnusedPulsePair: PulsePair = 4; PrechargePulsePair: PulsePair = 0; AccessPulsePair: PulsePair = 1; AddressPulsePair: PulsePair = 2; DataOutPulsePair: PulsePair = 3; DataInPulseLine: PulseLine = 6; AddressIndex: TYPE = [0..11); DataIndex: TYPE = [0..33); LastDataIndex: DataIndex = IF HM6116 THEN 7 ELSE 32; ChipSelectChannel: Channel = 57; -- HM6116 only PrechargeChannel: Channel = 25; -- CrossRAM only AccessChannel: Channel = 22; -- CrossRAM only WriteChannel: Channel = IF HM6116 THEN 60 ELSE 26; ReadChannel: Channel = IF HM6116 THEN 59 ELSE 27; AddressChannels: ARRAY AddressIndex OF Channel; DataChannels: ARRAY DataIndex OF Channel; pulseTaps: PulseLineTaps _ NEW[PulseLineTapRec]; channelControl: ChannelControlData _ NEW[ChannelControlDataRec]; initialData: ChannelVector _ NEW[ChannelVectorRec]; InitializeTaps: PROCEDURE [pulseTaps: PulseLineTaps, uh: UserHandle] = TRUSTED { OPEN pulseTaps, uh; lastUnassignedTap: Tap _ LAST[Tap]; UsedPulseLineIndex: TYPE = [0..11); usedPulseLines: ARRAY UsedPulseLineIndex OF PulseLine _ [0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 15]; UnusedPulseLineIndex: TYPE = [0..5); unusedPulseLines: ARRAY UnusedPulseLineIndex OF PulseLine _ [4, 5, 12, 13, 14]; taps[WidthPulseLine] _ width; taps[CyclePulseLine] _ cycle; taps[PrechargePulsePair] _ prechargeM; taps[PrechargePulsePair+8] _ prechargeS; taps[AccessPulsePair] _ accessM; taps[AccessPulsePair+8] _ accessS; taps[AddressPulsePair] _ addressM; taps[AddressPulsePair+8] _ addressS; taps[DataOutPulsePair] _ dataM; taps[DataOutPulsePair+8] _ dataS; taps[DataInPulseLine] _ dataIn; FOR unpl: UnusedPulseLineIndex IN UnusedPulseLineIndex DO UNTIL lastUnassignedTap=FIRST[Tap] DO FOR upl: UsedPulseLineIndex IN UsedPulseLineIndex DO IF taps[usedPulseLines[upl]]=lastUnassignedTap THEN EXIT REPEAT FINISHED => GOTO FoundUnassignedTap; ENDLOOP; lastUnassignedTap _ lastUnassignedTap-1; REPEAT FoundUnassignedTap => { taps[unusedPulseLines[unpl]] _ lastUnassignedTap; lastUnassignedTap _ lastUnassignedTap-1; }; FINISHED => ERROR; ENDLOOP; ENDLOOP; }; SetRAMCycle: PROC [cv: ChannelVector, cycle: CycleIndex, address: Address, data: LONG CARDINAL, parity: BOOL, write: BOOL] = TRUSTED { OPEN cv; FirstDataBit: DataIndex = IF HM6116 THEN 25 ELSE 0; thisStage: OutputStage _ 2*cycle; nextStage: OutputStage _ thisStage+1; pb: DriveState _ IF NOT write THEN T ELSE IF parity THEN H ELSE L; d1: LongAsWords _ [Basics.HighHalf[LOOPHOLE[data, LONG CARDINAL]], Basics.LowHalf[LOOPHOLE[data, LONG CARDINAL]]]; d: WordsAsBool _ LOOPHOLE[d1, WordsAsBool]; a: WordAsBool _ LOOPHOLE[address]; FOR ai: AddressIndex IN AddressIndex DO ab: DriveState _ IF a[ai+FirstAddressBit] THEN H ELSE L; stageData[AddressChannels[ai]].force[thisStage] _ ab; stageData[AddressChannels[ai]].force[nextStage] _ ab; ENDLOOP; FOR di: DataIndex IN [0..LastDataIndex) DO bi: [0..32) _ di+FirstDataBit; db: DriveState _ IF NOT write THEN T ELSE IF d[bi] THEN H ELSE L; stageData[DataChannels[di]].force[thisStage] _ db; stageData[DataChannels[di]].force[nextStage] _ db; stageData[DataChannels[di]].sense[currentCycle] _ d[bi]; IF write THEN PutBit[dataBitmap, address, di, d[bi]]; ENDLOOP; stageData[DataChannels[LastDataIndex]].force[thisStage] _ pb; stageData[DataChannels[LastDataIndex]].force[nextStage] _ pb; stageData[DataChannels[LastDataIndex]].sense[currentCycle] _ parity; IF write THEN PutBit[dataBitmap, address, LastDataIndex, parity]; stageData[WriteChannel].force[thisStage] _ IF HM6116 THEN H ELSE L; stageData[WriteChannel].force[nextStage] _ IF (NOT HM6116 AND write) OR (HM6116 AND NOT write) THEN H ELSE L; stageData[ReadChannel].force[thisStage] _ IF HM6116 THEN H ELSE L; stageData[ReadChannel].force[nextStage] _ IF (NOT HM6116 AND NOT write) OR (HM6116 AND write) THEN H ELSE L; }; <> CycleData: TYPE = RECORD [ write: BOOL _ FALSE, address: Address _ 0, parity: BOOL _ FALSE, data: LONG CARDINAL _ 0]; UserHandle: TYPE = REF UserRec; UserRec: TYPE = RECORD [ width: Tap _ 0, cycle: Tap _ 63, prechargeS: Tap _ IF HM6116 THEN 62 ELSE 25, prechargeM: Tap _ IF HM6116 THEN 61 ELSE 15, accessS: Tap _ IF HM6116 THEN 30 ELSE 30, accessM: Tap _ IF HM6116 THEN 7 ELSE 7, addressS: Tap _ IF HM6116 THEN 5 ELSE 5, addressM: Tap _ IF HM6116 THEN 1 ELSE 1, dataS: Tap _ IF HM6116 THEN 13 ELSE 13, dataM: Tap _ IF HM6116 THEN 6 ELSE 6, dataIn: Tap _ IF HM6116 THEN 14 ELSE 14, reportVectors: BOOL _ FALSE, reportErrors: BOOL _ FALSE, quit: BOOL _ FALSE, dicentraName: Rope.ROPE _ "Grumpy", connected: BOOL _ FALSE, Connect: PROC[uh: UserHandle], IllinoisPattern: PROC[uh: UserHandle], WriteReadPattern: PROC[uh: UserHandle], ScopeLoop: PROC[uh: UserHandle], scopeLoopData: ARRAY CycleIndex OF CycleData ]; Start: PROCEDURE = TRUSTED { h: UserHandle _ NEW [UserRec]; h.ScopeLoop _ ScopeLoop; h.Connect _ Connect; h.IllinoisPattern _ IllinoisPattern; h.WriteReadPattern _ WriteReadPattern; AddressChannels _ IF HM6116 THEN [6, 5, 4, 3, 2, 1, 0, 7, 62, 61, 58] ELSE [21, 20, 19, 17, 16, 15, 14, 12, 11, 10, 9]; DataChannels _ IF HM6116 THEN [8, 9, 10, 52, 53, 54, 55, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ELSE [5, 4, 3, 2, 0, 63, 62, 61, 59, 58, 57, 56, 54, 53, 52, 51, 49, 48, 47, 46, 44, 43, 42, 41, 38, 37, 36, 35, 33, 32, 31, 30, 28]; [] _ ViewRec.ViewRef[agg: h, specs: ViewRec.BindAllOfATypeFromRefs[h, NEW[UserHandle _ h]], createOptions: [maxEltsHeight: 600], viewerInit: [iconic: FALSE, name: "CrossRAM Tester"], paint: TRUE]; dataViewer _ BitmapViewer.Create[info: [name: "CrossRAM Data Bit Map"]]; dataBitmap _ ImagerPixelMaps.Create[0, rectangle]; errorViewer _ BitmapViewer.Create[info: [name: "CrossRAM Error Bit Map"]]; errorBitmap _ ImagerPixelMaps.Create[0, rectangle]; BitmapViewer.SetBitmap[dataViewer, dataBitmap]; BitmapViewer.SetBitmap[errorViewer, errorBitmap]; }; Connect: PROCEDURE [uh: UserHandle] = TRUSTED { TRUSTED { <> uh.connected _ TRUE; }; }; <> LastRow: INT = IF HM6116 THEN 127 ELSE 255; LastColumn: INT = IF HM6116 THEN 127 ELSE 263; rectangle: BitmapViewer.DeviceRectangle = [0, 0, LastRow, LastColumn]; dataViewer: BitmapViewer.Viewer; dataBitmap: ImagerPixelMaps.PixelMap; errorViewer: BitmapViewer.Viewer; errorBitmap: ImagerPixelMaps.PixelMap; PutBit: PROC[bitmap: ImagerPixelMaps.PixelMap, address: Address, bit: DataIndex, data: BOOL] = { <> <> <> address _ Basics.BITXOR[address, 2A0H]; ImagerPixelMapsExtras.SetBit[bitmap, IF HM6116 THEN address/16 ELSE address/8, IF HM6116 THEN bit*16 + (address MOD 16) ELSE bit*8 + (address MOD 8), LOOPHOLE[data, CARDINAL]]; }; Refresh: PROC = { BitmapViewer.TouchUp[dataViewer, rectangle]; BitmapViewer.TouchUp[errorViewer, rectangle]; }; ClearErrorMap: PROC = { FOR address: Address IN Address DO FOR bit: DataIndex IN [0..LastDataIndex] DO PutBit[errorBitmap, address, bit, FALSE]; ENDLOOP; ENDLOOP; }; <> <<>> Address: TYPE = [0..2048); FirstAddressBit: CARDINAL = 5; Size: INT = LAST[Address]+1; CycleIndex: TYPE = [0..16); SenseBuffer: TYPE = REF SenseBufferRec; SenseBufferRec: TYPE = RECORD[PACKED ARRAY Channel OF SenseData]; WordAsBool: TYPE = PACKED ARRAY [0..16) OF BOOL; WordsAsBool: TYPE = PACKED ARRAY [0..32) OF BOOL; LongAsWords: TYPE = MACHINE DEPENDENT RECORD [ high: CARDINAL, low: CARDINAL]; unassertedClock: DriveState _ IF HM6116 THEN H ELSE L; assertedClock: DriveState _ IF HM6116 THEN L ELSE H; sense: SenseBuffer _ NEW[SenseBufferRec]; vector: ChannelVector _ NEW[ChannelVectorRec]; currentCycle: CycleIndex; tester: Tester; WriteReadPattern: PROCEDURE [uh: UserHandle] = TRUSTED { OPEN uh; currentCycle _ 0; InitializeTaps[pulseTaps, uh]; IllinoisChannelControl[channelControl]; IllinoisInitialData[initialData]; IF connected THEN tester _ InitializeTester[pulseTaps, channelControl, initialData]; vector.testerCycles _ 16; ClearErrorMap[]; UNTIL uh.quit DO FOR address: CARDINAL IN Address DO localCycle: CycleIndex _ currentCycle; IF (LAST[CycleIndex]-localCycle) < 4 THEN THROUGH [localCycle..LAST[CycleIndex]) DO CycleRAM[uh, 0, 0, FALSE, TRUE] ENDLOOP; CycleRAM[uh, address, 0, FALSE, TRUE]; CycleRAM[uh, address, 0, FALSE, FALSE]; CycleRAM[uh, address, LAST[INT], TRUE, TRUE]; CycleRAM[uh, address, LAST[INT], TRUE, FALSE]; IF uh.quit THEN EXIT; ENDLOOP; ENDLOOP; IF NOT uh.quit THEN FlushLoads[uh]; IF connected THEN FinalizeTester[tester]; }; IllinoisPattern: PROCEDURE [uh: UserHandle] = TRUSTED { OPEN uh; StepIndex: TYPE = [0..8); complementUpper: ARRAY StepIndex OF BOOL = [TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE]; writeData: ARRAY StepIndex OF BOOL = [TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE]; readData: ARRAY StepIndex OF BOOL = [FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE]; halfBit: INT _ Size; currentCycle _ 0; InitializeTaps[pulseTaps, uh]; IllinoisChannelControl[channelControl]; IllinoisInitialData[initialData]; IF connected THEN tester _ InitializeTester[pulseTaps, channelControl, initialData]; vector.testerCycles _ 16; ClearErrorMap[]; <> <> FOR address: Address IN Address DO CycleRAM[uh, address, 0, FALSE, TRUE]; ENDLOOP; FlushLoads[uh]; UNTIL (halfBit _ halfBit/2) = (IF HM6116 THEN 8 ELSE 4) DO FOR step: StepIndex IN StepIndex DO HalfStep[uh: uh, upper: complementUpper[step], data: writeData[step], write: TRUE, halfbit: halfBit]; FlushLoads[uh]; HalfStep[uh: uh, upper: NOT complementUpper[step], data: readData[step], write: FALSE, halfbit: halfBit]; FlushLoads[uh]; ENDLOOP; IF quit THEN EXIT; ENDLOOP; IF connected THEN FinalizeTester[tester]; }; IllinoisChannelControl: PROCEDURE [channelControl: ChannelControlData] = TRUSTED { OPEN channelControl; FOR channel: Channel IN Channel DO channels[channel] _ [FALSE, UnusedPulsePair, UnusedPulsePair]; ENDLOOP; IF NOT HM6116 THEN { channels[PrechargeChannel].outputPulsePair _ PrechargePulsePair; channels[AccessChannel].outputPulsePair _ AccessPulsePair; }; channels[WriteChannel] _ [TRUE, UnusedPulsePair, AccessPulsePair]; channels[ReadChannel] _ [TRUE, UnusedPulsePair, AccessPulsePair]; FOR address: AddressIndex IN AddressIndex DO channels[AddressChannels[address]] _ [TRUE, UnusedPulsePair, AddressPulsePair]; ENDLOOP; FOR data: DataIndex IN [0..LastDataIndex] DO channels[DataChannels[data]] _ [TRUE, DataInPulseLine, DataOutPulsePair]; ENDLOOP; }; IllinoisInitialData: PROCEDURE [initialData: ChannelVector] = TRUSTED { OPEN initialData; FOR channel: Channel IN Channel DO stageData[channel].force _ ALL[T]; stageData[channel].sense _ ALL[FALSE]; ENDLOOP; IF HM6116 THEN stageData[ChipSelectChannel].force _ ALL[L] ELSE FOR stage: OutputStage IN OutputStage DO stageData[PrechargeChannel].force[stage] _ IF stage MOD 2 = 0 AND stage=Size THEN EXIT; ENDLOOP; }; CycleRAM: PROC [uh: UserHandle, address: Address, data: LONG CARDINAL, parity: BOOL, write: BOOL] = TRUSTED { IF currentCycle=LAST[CycleIndex] THEN { FlushLoads[uh] }; SetRAMCycle[vector, currentCycle, address, data, parity, write]; currentCycle _ currentCycle+1; }; FlushLoads: PROC [uh: UserHandle] = TRUSTED { FOR cycle: CycleIndex IN [currentCycle..LAST[CycleIndex]) DO SetCycle[cycle, DefaultAddressState]; ENDLOOP; currentCycle _ 0; FOR channel: Channel IN Channel DO sense[channel] _ vector.stageData[channel].sense; ENDLOOP; IF uh.reportVectors THEN { TerminalIO.WriteLn[]; FOR stage: OutputStage IN OutputStage DO FOR channel: Channel IN Channel DO TerminalIO.WriteChar[SELECT vector.stageData[channel].force[stage] FROM H => 'H, L => 'L, T => 'T, ENDCASE => ERROR]; ENDLOOP; TerminalIO.WriteLn[]; ENDLOOP; TerminalIO.WriteLn[]; }; IF uh.connected THEN { Run[tester, vector]; }; FOR stage: InputStage IN [0..LAST[InputStage]) DO FOR di: DataIndex IN [0..LastDataIndex] DO IF sense[DataChannels[di]][stage] # vector.stageData[ DataChannels[di]].sense[stage] THEN { a: WordAsBool _ ALL[FALSE]; IF vector.stageData[WriteChannel].force[ 2*stage+1]#assertedClock AND vector.stageData[ReadChannel].force[ 2*stage+1]#assertedClock THEN EXIT; FOR ai: AddressIndex IN AddressIndex DO a[ai+FirstAddressBit] _ vector.stageData[ AddressChannels[ai]].force[2*stage]=H; ENDLOOP; PutBit[errorBitmap, LOOPHOLE[a], di, TRUE]; IF uh.reportErrors THEN { TerminalIO.WriteRope["Error at location: "]; TerminalIO.WriteInt[LOOPHOLE[a, CARDINAL]]; TerminalIO.WriteRope[", bit: "]; TerminalIO.WriteInt[di]; TerminalIO.WriteRope[", expected: "]; TerminalIO.WriteInt[LOOPHOLE[sense[DataChannels[di]][stage], CARDINAL]]; IF vector.stageData[WriteChannel].force[ 2*stage+1]=assertedClock THEN TerminalIO.WriteRope[", during a write cycle"] ELSE TerminalIO.WriteRope[", during a read cycle"]; TerminalIO.WriteLn[]; }; }; ENDLOOP; ENDLOOP; Refresh[]; }; SetCycle: PROC [cycle: CycleIndex, addressData: DriveState] = TRUSTED { OPEN vector; thisStage: OutputStage _ 2*cycle; nextStage: OutputStage _ thisStage+1; FOR address: AddressIndex IN AddressIndex DO stageData[AddressChannels[address]].force[thisStage] _ addressData; stageData[AddressChannels[address]].force[nextStage] _ addressData; ENDLOOP; stageData[WriteChannel].force[thisStage] _ unassertedClock; stageData[WriteChannel].force[nextStage] _ unassertedClock; stageData[ReadChannel].force[thisStage] _ unassertedClock; stageData[ReadChannel].force[nextStage] _ unassertedClock; }; <> <<>> ScopeLoop: PROCEDURE [uh: UserHandle] = TRUSTED { OPEN uh; tester: Tester; InitializeTaps[pulseTaps, uh]; ScopeLoopChannelControl[channelControl]; ScopeLoopInitialData[uh, initialData]; IF uh.reportVectors THEN { TerminalIO.WriteLn[]; FOR stage: OutputStage IN OutputStage DO FOR channel: Channel IN Channel DO TerminalIO.WriteChar[SELECT initialData.stageData[channel].force[stage] FROM H => 'H, L => 'L, T => 'T, ENDCASE => ERROR]; ENDLOOP; TerminalIO.WriteLn[]; ENDLOOP; }; IF connected THEN { tester _ InitializeTester[pulseTaps, channelControl, initialData]; FinalizeTester[tester]; }; }; ScopeLoopChannelControl: PROCEDURE [channelControl: ChannelControlData] = TRUSTED { OPEN channelControl; FOR channel: Channel IN Channel DO channels[channel] _ [FALSE, UnusedPulsePair, UnusedPulsePair]; ENDLOOP; IF NOT HM6116 THEN { channels[PrechargeChannel].outputPulsePair _ PrechargePulsePair; channels[AccessChannel].outputPulsePair _ AccessPulsePair; }; channels[WriteChannel].outputPulsePair _ AccessPulsePair; channels[ReadChannel].outputPulsePair _ AccessPulsePair; FOR address: AddressIndex IN AddressIndex DO channels[AddressChannels[address]].outputPulsePair _ AddressPulsePair; ENDLOOP; FOR data: DataIndex IN [0..LastDataIndex] DO channels[DataChannels[data]].outputPulsePair _ DataOutPulsePair; channels[DataChannels[data]].inputPulseLine _ DataInPulseLine; ENDLOOP; }; ScopeLoopInitialData: PROCEDURE [uh: UserHandle, initialData: ChannelVector] = TRUSTED { OPEN initialData; FOR channel: Channel IN Channel DO stageData[channel].force _ ALL[T]; stageData[channel].sense _ ALL[FALSE]; ENDLOOP; IF NOT HM6116 THEN FOR stage: OutputStage IN OutputStage DO stageData[PrechargeChannel].force[stage] _ IF stage MOD 2 = 0 THEN L ELSE H; stageData[AccessChannel].force[stage] _ IF stage MOD 2 = 0 THEN L ELSE H; ENDLOOP; FOR cycle: CycleIndex IN CycleIndex DO SetRAMCycle [initialData, cycle, uh.scopeLoopData[cycle].address, uh.scopeLoopData[cycle].data, uh.scopeLoopData[cycle].parity, uh.scopeLoopData[cycle].write] ENDLOOP; IF HM6116 THEN stageData[ChipSelectChannel].force _ ALL[L]; }; Start[]; END.