CrossRAMTest.mesa
Last edited by Barth, July 3, 1985 12:17:08 pm PDT
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;
Common to all patterns
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;
};
Control Panel
CycleData: TYPE = RECORD [
write: BOOLFALSE,
address: Address ← 0,
parity: BOOLFALSE,
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: BOOLFALSE,
reportErrors: BOOLFALSE,
quit: BOOLFALSE,
dicentraName: Rope.ROPE ← "Grumpy",
connected: BOOLFALSE,
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.WriteReadPatternWriteReadPattern;
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 {
SageRpcControl.ImportInterface[interfaceName: [NIL, uh.dicentraName]];
uh.connected ← TRUE;
};
};
Bit map
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] = {
the low order bits address left to right
the high order bits address from top to bottom
the data bits are in order from left to right
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;
};
Illinois pattern
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[];
write zero to all locations
divide RAM by columns instead of rows
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<LAST[OutputStage]-1 THEN L ELSE H;
stageData[AccessChannel].force[stage] ← IF stage MOD 2 = 1 AND stage<LAST[OutputStage] THEN H ELSE L;
ENDLOOP;
FOR channel: Channel IN Channel DO
vector.stageData[channel].force ← ALL[T];
ENDLOOP;
SetCycle[LAST[CycleIndex], IF HM6116 THEN DefaultAddressState ELSE T];
IF HM6116 THEN vector.stageData[ChipSelectChannel].force ← ALL[L];
};
HalfStep: PROC [uh: UserHandle, upper: BOOL, data: BOOL, write: BOOL, halfbit: INT] = {
address: CARDINALIF upper THEN halfbit ELSE 0;
addressMod: CARDINAL;
DO
CycleRAM[uh, address, IF data THEN 0FFFFFFFFH ELSE 0, IF data THEN TRUE ELSE FALSE, write];
address ← address + 1;
addressMod ← address MOD (2*halfbit);
IF (upper AND addressMod=0) OR (NOT upper AND addressMod=halfbit) THEN address ← address + halfbit;
IF address>=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;
};
Scope loop
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.