%
*** *** *** *** <D0Diag>Rev-1>EDMemEx.mc Revision 1.1 May 2, 1980 *** *** *** ***

****************************************************************************************
*** EDMemEx.mc : Memory Exerciser microcode
*** Purpose : This test exercises the Memory Map and the 96K Memory Modules.
*** Minimum Hardware : Standard 4 CPU boards and the 96K Memory Modules to be tested.
*** Approximate Run Time : 86 seconds.
*** Obtained from CSL disk by Chuck Thacker, Nov 26,1979
*** Modified by : T. Henning,
Nov 26,1979
Added title page, standardized names, and formatting for readability.
Added capability for all zeros, all ones, and checker patterns.
Added looping capability to repeat error conditions.
*** Modified by : Chuck Thacker, Jan 15, 1980
Replaced Faultxx to read error pipe, and extract it for information such as
crash code, syndrome, and card number for fault diagnosis. Generated syndrome
table to fault isolated down to the 4116 memory chip level.
*** Modified by : T. Henning,
Feb 15, 1980
Added feature to display number of 96K modules found by MapInit.
Added feature to detect any 96K modules that doesn’t have the full 600 pages.
Changed the label RealAddr to RealQuadAddr and corrected the generation of
RealQuadAddr from the Error Pipe. Also displays Block number to user.
Used CurrentPage as the seed in IncMemAddr subroutine so that patterns won’t
repeat every 64K words.
Added routine to find holes in MapInit and to cause memory faults with it
to aid in fault isolation to the chip level.
*** Modified by : C. Thacker,
May 2, 1980
Fixed interaction with Fault Handler. Faults should normally be logged in RM 100-110,
then control should be sent to Midas. Also provided command file MemEx.cm to assemble
and load.

****************************************************************************************

****************************************************************************************
*SubTest Description:
* SubTest 0: No test has been performed yet.
* SubTest 1: Write and read the Memory Map.
* SubTest 2: Read the Memory Map again, after SubTest 1.
* SubTest 3: Initialize the Memory Map, making sure that it maps to real memory correctly.
* SubTest 4: Write and read the Real Memory Storage.
* SubTest 5: Read the Real Memory Storage again, after SubTest 4.

****************************************************************************************
* SUGGESTED TESTING STRATEGY:
*
*
Bring up the 96K Storage Modules with the minimum 4 CPU cards and also
*
put in all the 96K modules to be tested in slots 5 to 12 (maximum of 8).
*
*
a) If EDMemEx finds the correct number of 96K modules as indicated in the
*
breakpoint label, then bug continue.
*
*
b) If breakpoint A96KNOTFULL occurs, then the Map Initialization routine could not
*
find all 600 pages per 96K module. Bug CONTINUE, any memory faults will be
*
indicated on the Alto Midas screen by the label MEMFAULT. CARDNUMBER will
*
tell you which card is the problem (octal!). The SYNDROME and BLOCK can be
*
used with the syndrome table on page 3 to pinpoint which chip may be bad.
*
If that doesn’t cure the problem, or is there no entry in the syndrome
*
table, then use short looping to isolate address and data bits.
*
*
c) If EDMemEx doesn’t find th correct number of 96K modules, then it has not found
*
one or more cards and you must power down, plug the 96K modules one at a
*
time into slot 5, and run EDMemEx starting from FLATBOARD. You can do this
*
by typing FLATBOARD, bug SS, then bug CONTINUE.

****************************************************************************************
*BreakPoints:
* A96KNOTFULL:
The Map Initialization routine could not access all 600 pages of one
of the 96K storage modules.
* FINISHED-MAPINIT:
The Map Initialization routine is done. A breakpoint will be put here
if MapInit.midas uses this to initialize the map.
* FOUND.NO.96K:
The Map Initialization found no 96K storage modules.
* FOUND.ONE.96K:
The Map Initialization found ONE 96K storage modules.
* FOUND.TWO.96K:
The Map Initialization found TWO 96K storage modules.
* FOUND.THREE.96K:
The Map Initialization found THREE 96K storage modules.
* FOUND.FOUR.96K:
The Map Initialization found FOUR 96K storage modules.
* FOUND.FIVE.96K:
The Map Initialization found FIVE 96K storage modules.
* FOUND.SIX.96K:
The Map Initialization found SIX 96K storage modules.
* FOUND.SEVEN.96K:
The Map Initialization found SEVEN 96K storage modules.
* FOUND.EIGHT.96K:
The Map Initialization found EIGHT 96K storage modules.
* FOUND.TOOMANY.96K:
The Map Initialization found TOO MANY 96K storage modules. The number
*
exceeds the eight 96K modules allowed per chasis (not possible).
* MEMFAULT:
A memory fault occured, while reading real storage, use SYNDROME,
*
BLOCK, CARDNUMBER and syndrome table to find bad chip.
* PASSED-EDMAPEX-TEST:
Passed all passes of the Map Test. A breakpoint will be put here
if MapEx.midas uses this to test the map.
* PASSED-EDMEMEX-TEST:
Passed all tests, and all passes.
* WORDBAD:
Read buffer (rbuf) was not equal to write buffer (wbuf) under mask.
*
The SubTest number tells whether it was the map or real storage.

****************************************************************************************
* ShortLoop Logic Analyzer Sync Points at Control Store address:
* A96KNOTFULL:
Control Store address 514 at MAPINIT.
* MEMFAULT:
FOR SUBTEST 4: Control Store address 505 at SWL1.
FOR SUBTEST 5: Control Store address 465 at SRL1.
* WORDBAD:
FOR SUBTEST 1: Control Store address 431 at MWL1.
FOR SUBTEST 2: Control Store address 425 at MRL1.
FOR SUBTEST 4: Control Store address 505 at SWL1.
FOR SUBTEST 5: Control Store address 465 at SRL1.

****************************************************************************************
*Special Register Definition:

* ShortLoop: At any breakpoint, the user has the choice of setting ShortLoop to a 1 to
loop on the current test. During the short loop, the user can modify the address
and data to the Control Store at will by changing CurrentLoc, CurrentPage
and wbuf0-3.
1, the current test will loop repeatedly for trouble shooting
0, no looping in current test

* PatternChoice:
Bit 15 - all zeros pattern, enable by 1, disable by 0
Bit 14 - all ones pattern, enable by 1, disable by 0
Bit 13 - checker pattern, enable by 1, disable by 0
Bit 12 - random pattern, enable by 1, disable by 0
Example: PatternChoice=2 enables the all ones pattern only
PatternChoice=10 enables the random pattern only
PatternChoice=17 enables all four of the patterns
PatternChoice=11 enables the random and all zeros patterns

* ControlReg:
bit 00 NO INCREMENT for CurrentLoc in MapTest
1 INCREMENT CurrentLoc by 1 in MapTest
bit 10 use VARYING DATA for MapTest
1 use CONSTANT DATA for MapTest
bit 20 NO INCREMENT for CurrentLoc in StorageTest
1 INCREMENT CurrentLoc by 4 in StorageTest
bit 30 use VARYING DATA for StorageTest
1 use CONSTANT DATA for StorageTest
bit 14bit 15
0 0read real storage using PFETCH4
0 1read real storage using PFETCH4
1 0read real storage using PFETCH2
1 1read real storage using PFETCH1
bit 16bit 17
0 0store real storage using PSTORE4
0 1store real storage using PSTORE4
1 0store real storage using PSTORE2
1 1store real storage using PSTORE1
Example:
Initial value of 120000 means increment currentloc in MapTest using varying
data, increment CurrentLoc in StorageTest using varying data and use PFetch4
and PStore4 operations.

* FFAULT:
bit 00 kernel does not go to the User Fault Handling routine
1 kernel goes to the User Fault Handling routine
bit 160 User Fault Handling routine branches to Midas on memory fault
1 User Fault Handling routine returns to user program on memory fault
Example:
Initial value of 100002 means fault handling by the user’s routine
and will return to user program and not Midas upon a fault.

****************************************************************************************
*Subroutine Description:
*
* BlockSet:
BlockSet fills wbuf0-3 with the contents of T.
* CheckData:
CheckData compares rbuf with wbuf under the mask.
PCF indexing is used to access the appropriate word of the buffers.
* Faultxx:
Faultxx is resident at location 120 and handles memory faults.
* FillBuf4:
Fillbuf4 places 4 16-bit pseudorandom numbers (masked by StorMask0-3) in wbuf0-3.
* GetRealPage:GetRealPage extracts the real page information from wbuf1-3 and stores it
*
into RealPage.
* IncMapAddr:
IncMapAddr increments CurrentLoc by 1 or 0 depending on ControlReg[0].
It returns 100000c in rlink0 if CurrentLoc = HighMapAddr (after incrementing).
* IncMemAddr:
IncMemAddr increments the storage address by 0 or 4, based on ControlReg[2].
It returns 100000c if a pass is done.
* NextPattern:NextPattern finds the next data pattern to use, increments the PassCount,
and returns it in the T register.
* Rand:
Rand produces a pseudorandom number in t and xa.
The formula is: xa← 4005*xa + ca mod 2**16.
* ReadMap:
ReadMap reads one entry from map location CurrentLoc into rbuf0,
then compares it with wbuf0 under mask0.
* ReadMem:
ReadMem reads a quadword from location CurrentPage,,CurrentLoc into rbuf0-3,
then compares the results with wbuf0-3 under the mask mask0-3.
On error, the difference is in T. The memory operation used to read
the data is determined by ControlReg[14,15].
* SetBase:
SetBase sets up base pair BaseL,BaseH to point to CurrentPage.
* WriteMap:
WriteMap writes the data in wbuf0 into the map at CurrentLoc


****************************************************************************************
*
*
Syndrome Table:

On a fault, the SYNDROME and BLOCK on the Alto Midas screen will point to the possibly
faulty memory chip. If the SYNDROME is not in the table, then it is not a single error
and therefore the SYNDROME could not point to a particular chip. The chip locations are
for the 96K storage card.

Syn-bitblock0block1block2
dromein
(octal)error
(decimal)
(0-63)

1c.7U082U143U143
2c.6U104U165U165
4c.5U103U164U164
70U003U003U065
10c.4U081U142U142
1316U005U005U067
1532U065U126U126
1648U067U128U128
20c.3U020U020U082
268U011U011U073
3224U013U013U075
3440U073U134U134
3756U075U136U136
40c.2U042U042U104
464U007U007U069
5220U009U009U071
5436U069U130U130
5752U071U132U132
6712U015U015U077
7328U017U017U079
7544U077U138U138
7660U079U140U140
100c.1U041U041U103
1062U026U026U088
11218U028U028U090
11434U088U149U149
11750U090U151U151
12710U034U034U096
13326U036U036U098
13542U096U157U157
13658U098U159U159
1476U030U030U092
15322U032U032U094
15538U092U153U153
15654U094U155U155
16614U038U038U100
17230U040U040U102
17446U100U161U161
17762U102U163U163
200c.0U019U019U081
2061U025U025U087
21217U027U027U089
21433U087U148U148
21749U089U150U150
2279U033U033U095
23325U035U035U097
23541U095U156U156
23657U097U158U158
2475U029U029U091
25321U031U031U093
25537U091U152U152
25653U093U154U154
26613U037U037U099
27229U039U039U101
27445U099U160U160
27761U101U162U162
3073U004U004U066
31319U006U006U068
31535U066U127U127
31651U068U129U129
32611U012U012U074
33227U014U014U076
33443U074U135U135
33759U076U137U137
3467U008U008U070
35223U010U010U072
35439U070U131U131
35755U072U133U133
36715U016U016U078
37331U018U018U080
37547U078U139U139
37663U080U141U141

****************************************************************************************
*
*
Crash Code Table: (CrashCode is displayed on the Midas screen.)

200R or CS parity error
201Supposed to be an impossible situation
202Map Out of Bounds
203H4PE (input bus) parity error
204Map Out of Bounds and H4PE (input bus) parity error
205got an unexpected MC2 error (probable memory chip failure)
2062 MC2 errors
207MC1 fault when emulator couldn’t accept it
210Fault from the instruction following a LoadPage
211Stack over/underflow
%

****************************************************************************************
*INITIALIZATION:

Title[EDMemEx];

IMRESERVE[0,0,100];
*Reserve space in page 0, from 0 to 77, used by the kernel
IMRESERVE[0,100,20];
*Reserve space in page 0, from 100 to 117, used by the kernel
IMRESERVE[0,377,1];
*Reserve space in page 0, location 377, used by the kernel

SetTask[0];

********** Macros and Set Values: **********

*Error Codes for Fault Handler
MC[RCSCrash,200];
*R or CS parity error
MC[CantHappenCrash,201];
*Supposed to be an impossible situation
MC[MOBCrash,202];
*Map Out of Bounds (MOB)
MC[H4PECrash,203];
*H4PE (input bus) parity error
MC[MOB&H4PECrash,204];
*MOB and H4PE
MC[MC2Crash, 205];
*got an MC2 error when unable to handle it by RETURNing
MC[MC22Crash,206];
*2 MC2 errors
MC[MC1Crash,207];
*MC1 fault when emulator couldn’t accept it
MC[LPCrash,210];
*Fault from the instruction following a LoadPage
MC[StkCrash,211];
*Stack over/underflow

SET[H4Disp,240];
SET[Mc2ErDisp,260];
SET[Cards,1400];

********** R-Registers: **********

RV[CardCount,12,0];
*number of 96K storage modules
RV[SixHundred,13,600];
*600 pages per 96K storage module

RV[zbuf0,14];
*register used during MapInit
RV[zbuf1,15];
RV[zbuf2,16];
RV[zbuf3,17];

RV[MaxMapPass,20,10];
*Number of passes to run the map test
RV[MaxMemPass,66,10];
*Number of passes to run the main memory test
RV[PassCount,21];
*Number of passes the current test has run

RV[LowMapAddr,22,0];
*bounds for map test
RV[HighMapAddr,23,37777];

RV[LowMemAddr,24,0];
*bounds for memory test - address within each page
RV[HighMemAddr,25,377];
*last word address in page
RV[LowMemPage,26,0];
*bounds for memory test - page number
RV[HighMemPage,27,1];

RV[SubTest,30,0];
*number of the current test
RV[CurrentLoc,31];
*current location in memory being tested (word address in memory test)
RV[CurrentPage,32];
*page being tested in memory test

RV[BaseL,34];
*base register pair
RV[BaseH,35];

RV[xa,33,123];
*RNG registers
RV[ca,36,33031];
RV[savedXA,37];

RV[rbuf0,40];
*Quadword Read Buffer
RV[rbuf1,41];
RV[rbuf2,42];
RV[rbuf3,43];

RV[wbuf0,44];
*Quadword Write Buffer
RV[wbuf1,45];
RV[wbuf2,46];
RV[wbuf3,47];

RV[mask0,50,177777];
*Data compare masks
RV[mask1,51,177777];
RV[mask2,52,177777];
RV[mask3,53,177777];

RV[PageCount,61];
*count of available real pages in system
* NOTE:*** location RM 61 is used in MemAbort.mc to pass page count info ***
*** therefore do not change R register number assignment ***

RV[RealPage,54];
RV[OldRealPage,67];
RV[rlink0,56];
*subroutine return link
RV[Rtemp,57];

RV[StorMask0,60,177777];
*Store masks
RV[StorMask1,55,177777];
RV[StorMask2,62,177777];
RV[StorMask3,63,177777];

RV[LogSEFlag,64,107777];
*107777b to enable SE faults, 7777 to disable them
RV[PatternChoice,65,17];
*Enable all four pattern at program initialization
RV[PatternTry,2,1];
*Initialize to all zeros pattern
RV[CurrentPattern,1,1];
*Initialize to all zeros pattern
RV[Ones,70,177777];
*define ones to be 177777
RV[Checker1,71,125252];
*checker pattern register
RV[Checker0,3,052525];
*checker pattern register
RV[Toggle,0,0];
*checker toggle register
RV[ControlReg,74,120000];
*Controls test
RV[ShortLoop,75,0];
*initialize program at no short looping

RV[Revision,76,1];
*REVISION 1
RV[Run-Time,77,126];
*run time is about 126b or 86D seconds

SetTask[17];
RV[RXALU,76];
*ALU result and SALUF
RV[RXAPC,75];
*APCTask&APC
RV[RXCTASK,74];
*CTASK.NCIA
RV[RXPPB,73];
*Page, parity, bootreason register in kernel
RV[RData,67];
*Register holding data to be sent to Midas (we use it as a temp)
RV[FFAULT,66,100000];
*bit0: 1 enables Fault Handling routine, 0 disables
*bit16: 1 Fault Handling routine return to program on fault
*NOTE: this should NOT be changed by the user. MapInit sets this
*bit only when it expects a fault. Normally, faults go to Midas.
* 0 Fault Handling routine goes to Midas on fault
RV[RXSTK,72];
*stackpointer save in kernel
RV[RTMP,71];
*temporary

RV[PipeReg,60];
*Pipe Ram Entry goes here
RV[PipeReg1,61];
RV[PipeReg2,62];
RV[PipeReg3,63];
RV[PipeReg4,64];
RV[PipeReg5,65];

SetTask[4];
RV[MapEntryNumber,0];
RV[TaskNumber,1];
RV[RefType,2];
RV[CrashCode,3];
RV[CardNumber,4];
RV[MapFlags,5];
RV[RealQuadAddr,6];
RV[Syndrome,7];
RV[Block,10];

SetTask[0];

****************************************************************************************
*** MAIN routine:

Set[TestPage,1];
OnPage[TestPage];

START:
GO:
CLEARMPANEL;
PassCount ← (0C);
MapTest:
LoadPage[2];
CallP[NextPattern];*get next pattern
lu ← (MaxMapPass) - (T);
goto[Passed-EDMapEx-Test,alu=0];*done with map test?

*** SubTest 1
SubTest ← 1C;
INCMPANEL;
t←xa;*save RNG
savedxa←t;
t←LowMapAddr;*set address
CurrentLoc←t;

mwl0:
call[FillBuf4];*generate data into write buffer
mwl1:
call[WriteMap],AT[431];*write it
call[ReadMap];*read and compare
ShortLoop ← ShortLoop, goto[.+2, R EVEN];*ShortLoop for debugging?
goto[mwl1];
nop;
call[IncMapAddr];*returns 1 in rlink0[0] if done
lu ← rlink0, goto[MapReadSetup,R<0];
lu ← ldf[ControlReg,1,1];*change data if ControlReg[1] = 0
dblgoto[mwl0,mwl1,ALU=0];

*** SubTest 2
MapReadSetup:
SubTest ← 2C;
Toggle ← 0C;*reset checker pattern toggle
t←LowMapAddr;*reset address
CurrentLoc ← t;
t←savedxa;*reset RNG
xa←t;

mrl0:
call[FillBuf4];*fill buffer
mrl1:
call[ReadMap],AT[425];*read and compare
ShortLoop ← ShortLoop, goto[.+2, R EVEN];*ShortLoop for debugging?
goto[mrl1];
nop;
call[IncMapAddr];*returns 1 in rlink0[0] if done
lu ← rlink0, goto[MapTest,R<0];
lu ← ldf[ControlReg,1,1];*change data if ControlReg[1] = 0
dblgoto[mrl0,mrl1,ALU=0];
Passed-EDMapEx-Test:
nop;*dummy instruction for EDMapEx test label
*EDMapEx.midas will put a breakpoint here
*to terminate the Map Test

*** SubTest 3
MapInit:
SubTest ← 3C;
RealPage ← (10000C),AT[514];*max real page +1
CurrentLoc ← 140000C;*carries beyond max VM cause ALUCY
PageCount ← 0C;
CardCount ← 0C;
rlink0 ← 366C;*location in fault handler (Stkp = 366 from now on)
stkp ← rlink0;
stack ← 100000c;*set FFAULT so that Kernel will send control through
*location 120 on all faults.

*First, fill first 5 quadwords of each real page with their page numbers and complements
*and some constants selected to make all the check bits 1 and 0.
*go through real memory backwards so that hole in 96k modules will not screw up non-hole banks.
imFloop:
RealPage ← T ← (RealPage)-1;
goto[.+2,ALU>=0];
T ← RealPage ← 170000C, goto[imTloop];
wbuf0 ← T;
call[WriteMap]; *does not change T

loadpage[3];
gotop[.+1];

OnPage[3];
call[BlockSet]; *stores T into wbuf0-3
PStore4[BaseL,wbuf0,0];
T ← (zero)-(T)-1, call[BlockSet];
PStore4[BaseL,wbuf0,4];
T ← 0c, call[BlockSet];
wbuf0← 100000c;
nop;
PStore4[BaseL,wbuf0,10];
wbuf0 ← 0c;
wbuf1 ← 1c;
nop;
PStore4[BaseL,wbuf0,14];
wbuf1 ← 0c;
wbuf2 ← 40000c;
T ← 20c;
loadpage[TestPage];
PStore4[BaseL,wbuf0],gotop[imFloop];
OnPage[TestPage];

*we sweep upward through real storage and the map, and use any real pages discovered.
imTloop:
t ← (LogSEFlag) and (t);
wbuf0 ← T, call[WriteMap];*set up map, set base register
call[TryPage], stack ← (Stack) or (2c);*set fault handler to return to program
*by setting FFAULT[16] to 1
*FFAULT[16] ← 1. This informs the fault handler that the test program is willing
*to take the fault. The fault handler RETURNs rather than sending control to Midas.
imFault:
goto[imPageBad];*get here on a fault
TryPage:
PFetch4[BaseL,rbuf0,0];*fetch. Will cause fault if page is bad
T ← rbuf0;
lu ← (ldf[RealPage,4,14]) xor (T);
skip[ALU = 0];

PError:
goto[imPageBad];*page number didn’t compare
PFetch4[BaseL,rbuf0,4];
lu ← (rbuf0) xnor (T);*check page complement
skip[ALU=0];

PCError: goto[imPageBad];
PFetch4[BaseL,rbuf0,10];*fetch from the other 3 quadwords
lu ← rbuf0;*to provoke a fault
PFetch4[BaseL,rbuf0,14];
lu ← rbuf0;
T ← 20c;
PFetch4[BaseL,rbuf0];
lu ← rbuf0;

imPageGood:
CurrentLoc ← (CurrentLoc) + 1;*go to the next map location
PageCount ← (PageCount) + 1;

imPageBad: T ← RealPage ← (RealPage) + 1;
*go to the next real page
Stack ← (stack) and not (2c), goto[imTloop, nocarry];*done with all of real memory?
nop;

imMarkVacant:
wbuf0 ← 60000C;*this loop marks that portion of the map
Call[WriteMap];*with no corresponding storage vacant.
CurrentLoc ← (CurrentLoc) + 1;
t ← PageCount, goto[imMarkVacant, nocarry];*done with all map entries?

imCoreZap:
CurrentPage ← t;*clear memory from page PageCount-1 to zero
wbuf0 ← 0c;*zeros destined for memory
wbuf1 ← 0C;
wbuf2 ← 0c;
wbuf3 ← 0c;

imZapLoop:
CurrentPage ← (CurrentPage) -1;
goto[imDone, ALU<0];
nop;
call[SetBase];*set up a base register for the page
CurrentLoc ← 400C, call[imZPloop];
imZPloop:
CurrentLoc ← T ← (CurrentLoc) - (4C);
goto[imZapLoop, ALU<0];
PStore4[BaseL, wbuf0], return;

imDone:
ShortLoop ← ShortLoop, goto[.+2, R EVEN];*short loop for trouble-shooting?
goto[MapInit];

loadpage[3];
gotop[.+1];

OnPage[3];
lu ← (PageCount) -1;*don’t try to run with less than one page
goto[FullModule, ALU>=0];
goto[Found.No.96K];

FullModule:
T ← (PageCount);*make sure each 96K storage module is full
RTemp ← T;
T ← SixHundred;*each storage module should have 600 pages
RTemp ← (RTemp) - T;
RepeatQ:
goto[.+3, Alu<0];
CardCount ← (CardCount) +1;
RTemp ← (RTemp) - T, goto[RepeatQ];
RTemp ← (RTemp) + T;
goto[A96KNotFull, Alu#0];

Dispatch[CardCount,14,4];*indicate number of 96K storage modules
Disp[Found.No.96K];*found to the MIDAS screen
Found.No.96K:
Breakpoint,goto[Back], AT[Cards,0];
Found.One.96K:
Breakpoint,goto[Finished-MapInit], AT[Cards,1];
Found.Two.96K:
Breakpoint,goto[Finished-MapInit], AT[Cards,2];
Found.Three.96K:
Breakpoint,goto[Finished-MapInit], AT[Cards,3];
Found.Four.96K:
Breakpoint,goto[Finished-MapInit], AT[Cards,4];
Found.Five.96K:
Breakpoint,goto[Finished-MapInit], AT[Cards,5];
Found.Six.96K:
Breakpoint,goto[Finished-MapInit], AT[Cards,6];
Found.Seven.96K:
Breakpoint,goto[Finished-MapInit], AT[Cards,7];
Found.Eight.96K:
Breakpoint,goto[Finished-MapInit], AT[Cards,10];
goto[Found.TooMany.96K], AT[Cards,11];
goto[Found.TooMany.96K], AT[Cards,12];
goto[Found.TooMany.96K], AT[Cards,13];
goto[Found.TooMany.96K], AT[Cards,14];
goto[Found.TooMany.96K], AT[Cards,15];
goto[Found.TooMany.96K], AT[Cards,16];
Found.TooMany.96K:
Breakpoint, AT[Cards,17];
Back:
LoadPage[TestPage];
gotop[MapInit];

Finished-MapInit:
LoadPage[TestPage], AT[1522];
gotop[StorageTest];

A96KNotFull:
breakpoint, AT[1455];
ShortLoop ← ShortLoop, goto[.+3, R EVEN];*short loop for trouble-shooting?
LoadPage[TestPage];
goto[MapInit];
LoadPage[3];*FindHole routine will help trouble shoot it
goto[FindHole];

*** SubTest 4
OnPage[TestPage];
StorageTest:
SubTest ← 4C;
T ← PageCount;
HighMemPage ← T;
ControlReg ← (ControlReg) or (17c);*set read/write operation bits
PassCount ← (0C);

StorTest1:
LoadPage[2];
CallP[NextPattern];*use next pattern
lu ← (MaxMemPass) - (T);
INCMPANEL, goto[Passed-EDMemEx-Test,ALU=0];*done with Storage test?
ControlReg ← (ControlReg) + 1;*increment read/write operation bits
ControlReg ← (ControlReg) and not (20c);*suppress carry
T ← LowMemPage;
CurrentPage ← T;
xa←T;*use CurrentPage as seed for random number
savedxa←t, call[SetBase];*save RNG
T ← LowMemAddr;
CurrentLoc ← T;

swl0:
call[FillBuf4];*generate data into write buffer
swl1:
T ← CurrentLoc,AT[505];
Dispatch[ControlReg,16,2];
Disp[WType0];

SET[WType,Add[Lshift[TestPage,10],20]];
WType0:
PStore4[BaseL,wbuf0], goto[ChkRead],at[Wtype,0];*write using PStore4
WType1:
PStore4[BaseL,wbuf0], goto[ChkRead],at[Wtype,1];*write using PStore4
WType2:
PStore2[BaseL,wbuf0],at[Wtype,2];*write using two PStore2’s
T ← (zero)+(T)+1;
T ← (zero)+(T)+1;
PStore2[BaseL,wbuf2], goto[ChkRead];
WType3:
PStore1[BaseL,wbuf0],at[Wtype,3];*write using four PStore1’s
T ← (zero)+(T)+1;
PStore1[BaseL,wbuf1];
nop;
T ← (zero)+(T)+1;
PStore1[BaseL,wbuf2];
nop;
T ← (zero)+(T)+1;
PStore1[BaseL,wbuf3], goto[ChkRead];

ChkRead:
LoadPage[2];
callP[ReadMem];*read and compare
ShortLoop ← ShortLoop, goto[.+2, R EVEN];*ShortLoop for debugging?
goto[Short];
nop;
call[IncMemAddr];*returns 1 in rlink0[0] if pass complete
lu ← rlink0, goto[MemReadSetup,R<0];
lu ← ldf[ControlReg,3,1];
dblgoto[swl0,swl1,ALU=0];
Short:
call[SetBase];
goto[swl1];

*** SubTest 5
MemReadSetup:
SubTest ← 5C;
t←savedxa;*reset RNG
xa←t;
T ← LowMemPage;
CurrentPage ← T;
call[SetBase];
T ← LowMemAddr;
CurrentLoc ← T;
srl0:
call[FillBuf4];*fill buffer
srl1:
LoadPage[2],AT[465];
callP[ReadMem];*read and compare
ShortLoop ← ShortLoop, goto[.+2, R EVEN];*ShortLoop for debugging?
goto[srl1];
nop;
call[IncMemAddr];*returns 1 in rlink0[0] if pass complete
lu ← rlink0, goto[StorTest1,R<0];
lu ← ldf[ControlReg,3,1];
dblgoto[srl0,srl1,ALU=0];

Passed-EDMemEx-Test:
breakpoint, goto[go], AT[544];


*Start at FLATBOARD if a board is completely dead, or if MapInit could not find all 96K of storage
*on a 96K module. This section of the program sets up the first 600b entries of the map
*to point to slot 5 (which should contain the bad board) without trying to find good memory first.

OnPage[2];
FLATBOARD:
Rtemp ← 366c;
Stkp ← Rtemp;
Stack ← 100000c;*diagnostic gets to look at faults. They are logged in RM 100-107,
*then control is sent to Midas.
wbuf0 ← 100000c;*LogSEFlag is set in the first 600b map entries
Rtemp ← 400c;
Rtemp ← T← (Rtemp) or (177c);
PageCount ← (zero) + (T) + 1;
Currentloc ← 0c;
flatloop:
LoadPage[TestPage];
callP[WriteMap];
CurrentLoc ← (CurrentLoc) + 1;
lu ← (CurrentLoc) and (40000c);*check for all map entries loaded
T ← CurrentLoc, goto[.+3,ALU=0];
LoadPage[TestPage];
gotoP[StorageTest];
lu ← (Rtemp) - (T);
wbuf0 ← (wbuf0) + 1, goto[flatloop,carry];
wbuf0 ← 60000c, goto[flatloop];*pages beyond 577b are marked vacant

OnPage[3];
FindHole:
CurrentLoc ← 140000C;
wbuf0 ← 170000C;
OldRealPage ← 0C;
LoadPage[1];
CallP[WriteMap];*read map entry
Call[GetRealPage];*extract real page number
nop;

ModuleFirstPage:
T ← RealPage;

Zer:
RTemp ← T, goto[VacantTest, alu=0];*is this page zero of the 96K module?
T ← 1000C;
RTemp ← (RTemp) - (T);*RealPage-1000 (1000 pages per 128K space)
T ← RTemp, goto[Zer, alu>=0];

T ← (RealPage) - 1;*get real address of hole
WriteHole:
wbuf0 ← 10C; *enable log single errors bit in map
wbuf0 ← (lsh[wbuf0,14]) OR (T);*new entry points to hole
LoadPage[1];
CallP[WriteMap];*write new map entry
LoadPage[TestPage];
goto[StorageTest];*go generate fault caused by hole

VacantTest:
T ← 6C;*vacant is a 6C in the four MSB of map
lu ← (ldf[wbuf0,0,4]) XOR (T);*test to see if the vacant bits are set
T ← (OldRealPage)+1, goto[RestoreMap, alu#0];
PageCount ← (PageCount)+1, goto[WriteHole];*one more page added, the vacant page

RestoreMap:
T ← RealPage;*not vacant
OldRealPage ← T;*save real page number
LoadPage[1];
CallP[WriteMap];*restore map entry to original
CurrentLoc ← (CurrentLoc)+1;*next map location
LoadPage[1];
CallP[WriteMap];
Call[GetRealPage];

T ← RealPage;
RTemp ← T;
T ← OldRealPage;
RTemp ← (RTemp) - (T);
RTemp ← (RTemp) - 1;*RealPage-OldRealPage=1?
goto[LastPage, alu#0];*no, is this last page of 128K space?
T ← RealPage, goto[RestoreMap];*yes, restore map and read next map location

LastPage:
T ← (OldRealPage) + 1;
T ← (SixHundred) AND (T);
T ← (SixHundred) XOR (T);*last page of 128K space?
goto[ModuleFirstPage, alu=0];*yes,first page of 128K space?

T ← 6C;*vacant?
lu ← (ldf[wbuf0,0,4]) XOR (T);
goto[.+2, alu#0];
PageCount ← (PageCount)+1;*one more page added, the vacant page
T ← (OldRealPage)+1, goto[WriteHole];*hole is at saved real page plus 1

********** SUBROUTINE: BlockSet **********
*
*
BlockSet fills wbuf0-3 with
*
the contents of the T register.
*
OnPage[3];
BlockSet:
wbuf0 ← T;
wbuf1 ← T;
wbuf2 ← T;
wbuf3 ← T, return;

********** SUBROUTINE: CheckData **********
*
*
CheckData compares rbuf with wbuf under the mask.
*
PCF indexing is used to access the appropriate word of the buffers.
*
OnPage[2];
CheckData:
PCF ← Rtemp;
T ← PCF[rbuf0];
T ← (PCF[wbuf0]) xor (t);
T ← (PCF[mask0]) and (t);
goto[.+2, ALU#0];
return;
ShortLoop ← ShortLoop, goto[.+2, R EVEN];*ShortLoop for debugging?
return;
WordBad:
breakpoint,return, AT[1016];

********** FAULT HANDLER: FAULTxx **********
*
*
FAULTxx is resident at location 120 and
*
handles memory faults.
*
*We get to 120 from the Go overlay if PARITY#0 and FFAULT<0. We do a more thorough check,
*looking for a memory error. If there is one, and if FFAULT[14b] = 1, we return.
*If not, we send control to Midas at 7512. Midas will sent #101 to the Kernel.

SetTask[17];

Faultxx: lu ← (RXPPB) and (3000c), AT[120];
*test R & CS parity
lu ← (RXPPB) and (400c), goto[RCSErr, ALU#0];*test memory error
lu ← (RXPPB) and (4000c), goto[MC12Err, ALU#0];*test stack ovf
goto[CantHappen, ALU=0];*get here if PARITY = 0. This case cannot happen,
*since the Kernel will only send control here if PARITY#0.
StkEr:
T ← StkCrash, goto[Crash];

RCSErr:
T ← RCSCrash, goto[Crash];

CantHappen:
T ← CantHappenCrash, goto[Crash];

*Come here to put the contents of the correct error pipe slot into comprehensible form
*before indicating a fault to Midas. NOTE: it is not possible to continue from a fault.

*All crashes come here, but the contents of the pipe registers have meaning only
*if the CrashCode is >204 (i.e. is the result of a memory error).
Crash:

PipeReg5 ← (lsh[PipeReg5,10]) or (T);*save crash code
RTMP ← 117C;*reformat saved Pipe into RM 100-105 for examination by Midas.
Stkp ← RTMP;
T ← ldf[PipeReg,11,7];*map row address
PipeReg1 ← (lsh[PipeReg1,7]) or (T);
T ← ldf[PipeReg1,2,16];*Map location (page number) in bits 2-17b...
Stack&+1 ← T;*goes into location 100 (but the bits are inverted)
Stack ← (Stack) xnor (140000c);*now contains real page number

T ← 17c;
T ← (ldf[PipeReg2,10,4]) xor (T);*task number (upright)...
Stack&+1 ← T;*goes into location 101

T ← 17c;
T ← (ldf[PipeReg2,14,4]) xor (T);*reference type (upright)...
Stack&+1 ← T;*goes into location 102

T ← rhmask[PipeReg5];*Crash code..
Stack&+1 ← T;*goes into 103

T ← 7c;
T ← (ldf[PipeReg5,4,3]) xor (T);*Card number (5..12)
RTMP ← T;
T ← 5C;
T ← (RTMP) + (T);*add 5 to get chasis card number
Stack&+1 ← T;*goes into 104

T ← 17c;
T ← (ldf[PipeReg5,0,4]) xor (T);*Map Flags (4 bits)
Stack&+1 ← T; *go into 105

T ← ldf[PipeReg4,12,6];*Main column address (6 bits)
T ← (lsh[PipeReg3,6]) OR (T);*And Blk.1,,main row address (8 bits)
RTMP ← T;
T ← 140000C;
T ← (RTMP) OR (T);*mask out MSB 2 bits
RTMP ← (ZERO) XNOR (T);*complement each bit
T ← PipeReg5;
PipeReg5 ← (ZERO) XNOR (T);*complement Blk.0
PipeReg5 ← ldf[PipeReg5,7,1];*extract Blk.0
T ← PipeReg5 ← lsh[PipeReg5,16];
T ← (RTMP) OR T;*OR in Blk.0
PipeReg5 ← T;*save RealQuadAddr
Stack&+1 ← T;*go into 106

T ← rsh[PipeReg,10];*the syndrome
Stack&+1 ← T;*goes into 107

T ← ldf[PipeReg5,1,2];*block number extracted from RealQuadAddr
Stack&+1 ← T;*go into 110

lu ← ldf[FFAULT,16,1];*check for return (1) or crash (0)
goto[.+2,ALU=0];
Stkp ← RXSTK, return;*restore entry stackpointer

RTMP ← 177400c;*Notify Midas at 7512b (Go Overlay MidasFault)
RTMP ← (RTMP) OR (112C);
APC&APCTASK ← RTMP;
RETURN;

MC12Err:
Stkp ← RXSTK;* not stack error, restore pointer
ReadPipe[PipeReg];*get A pipe

Dispatch[PipeReg,4,2];*dispatch on H4pe, MapBnd
Dispatch[PipeReg,0,2], Disp[NoH4BndEr];*dispatch on MC2ErA’, MC2ErB’

NoH4BndEr:
Disp[MC2ErAB], lu ← (PipeReg) and (20000c), AT[H4disp,0];*test MC1ErA’ bit

BndEr:
T ← MOBCrash, goto[Crash], AT[H4disp,1];*MOB error only

H4Er:
T ← H4PECrash, goto[Crash], AT[H4disp,2];

H4BndEr:T ← MOB&H4PECrash, goto[Crash], AT[H4Disp,3];
*H4PE & MOB

MC2ErAB:T ← MC22Crash, goto[Crash], AT[MC2ErDisp,0];
*Have both MC2 A & B error - crash
MC2ErA:
T ← lhmask[MemSyndrome], goto[MC2Er], AT[MC2ErDisp,1];*MC2A error
MC2ErB:

ReadPipe[PipeReg], ResetMemErrs, AT[MC2ErDisp,2];*MC2B error - read B pipe entry
T ← lsh[MemSyndrome,10], goto[MC2Er];*The B syndrome is the important one
NoMC2Er:Goto[MC1Er,ALU=0], ResetMemErrs, AT[MC2ErDisp,3];
*Branch if MC1ErA’ = 0
ReadPipe[PipeReg], ResetMemErrs;*MC1B error - read pipe entry
MC1Er:
T ← MC1Crash, goto[Crash];

MC2Er:
ResetMemErrs; *One single or double error. Check whether diagnostic is willing to handle it.
PipeReg ← (rhmask[PipeReg]) or (T); *put the appropriate syndrome in the left byte of PipeReg
T ← MC2Crash, goto[Crash];

********** SUBROUTINE: FillBuf4 **********
*
*
Fillbuf4 places 4 16-bit numbers (masked by StorMask0-3) in wbuf0-3,
*
the numbers can be all zeros, all ones, checker, or random,
*
depending upon the user’s choice.
*
SetTask[0];
OnPage[TestPage];
FillBuf4:
usectask;
t ← apc&apctask;*save return link
rlink0 ← t;

t ← (CurrentPattern) AND (1C);
wbuf0 ← 0C, goto[Try1,alu=0];*want the zeros pattern?
wbuf1 ← 0C;*yes, fill wbuf0-3 with zeros pattern
wbuf2 ← 0C;
wbuf3 ← 0C, goto[fbret];

Try1:
t ← (CurrentPattern) AND (2C);*no, try the ones pattern
t ← Ones,goto[Try2,alu=0];*want the ones pattern?
wbuf0 ← t;*yes, fill wbuf0-3 with ones pattern
wbuf1 ← t;
wbuf2 ← t;
wbuf3 ← t, goto[fbret];

Try2:
t ← (CurrentPattern) AND (4C);*no, try the checker pattern
t ← Checker1, goto[Try3,alu=0];*want the checker pattern?
Toggle ← Toggle, goto[Checker01,R ODD];*yes, fill wbuf0-3 with checker pattern
wbuf0 ← t;*1010101010101010 pattern
wbuf1 ← t;
wbuf2 ← t;
wbuf3 ← t;
Toggle ← (Toggle) + 1, goto[fbret];*toggle checker pattern
Checker01: t ← Checker0;
*0101010101010101 pattern
wbuf0 ← t;
wbuf1 ← t;
wbuf2 ← t;
wbuf3 ← t;
Toggle ← (Toggle) + 1, goto[fbret];*toggle checker pattern

Try3:
t ← (CurrentPattern) AND (10C);*no, try the random pattern
goto[fbret,alu=0];*want the random pattern?
call[Rand];*yes, fill wbuf0-3 with random pattern
t ← (StorMask0) and (t);
wbuf0←t, call[rand];
t ← (StorMask1) and (t);
wbuf1←t, call[rand];
t ← (StorMask2) and (t);
wbuf2←t, call[rand];
t ← (StorMask3) and (t);
wbuf3←t;

fbret:
apc&apctask ← rlink0;
return;

********** SUBROUTINE: GetRealPage **********
*
*
GetRealPage extracts the real page information
*
from wbuf1-3 and stores it into RealPage.
*
OnPage[3];
GetRealPage:
T ← ldf[wbuf1,10,10];*Blk.1,,main row address (8 bits)
T ← (lsh[wbuf3,10]) OR (T);*And Card,,Blk.0 (4 bits)
RealPage ← T;
T ← wbuf0 ← (ZERO) XNOR (T);*complement each bit, and save it in wbuf0
*to restore the map contents
RealPage ← T;*save real page number
T ← 170000C;
T ← (ZERO) XNOR (T);*T register has 7777C
RealPage ← (RealPage) AND (T), return;*mask out 4 MSB bits

********** SUBROUTINE: IncMapAddr **********
*
*
IncMapAddr increments CurrentLoc by 1 or 0 depending on ControlReg[0].
*
it returns 100000c in rlink0 if CurrentLoc = HighMapAddr (after incrementing).
*
OnPage[TestPage];
IncMapAddr:
t ← ldf[ControlReg,0,1];
CurrentLoc ← t ← (CurrentLoc) + (t);
lu ← (HighMapAddr) - (t);
goto[.+2,alu=0];
rlink0 ← 0c, return;
rlink0 ← 100000c, return;

********** SUBROUTINE: IncMemAddr **********
*
*
IncMemAddr increments the storage address by 0 or 4, based on ControlReg[2].
*
It returns 100000c if a pass is done.
*
IncMemAddr:
t ← ldf[ControlReg,2,1];
goto[.+2,ALU=0];
t ← 4c;
t ← CurrentLoc ← (CurrentLoc) + (t);
lu ← (HighMemAddr) - (t);
t ← LowMemAddr, goto[.+2,ALU<0];
rlink0 ← 0c, goto[SetBase];*set base registers and Return
CurrentLoc ← t;
CurrentPage ← t ← (CurrentPage) + 1;
xa ← t;*use page number as seed for random number
lu ← (HighMemPage) - (t);
rlink0 ← 0c, goto[SetBase,ALU#0];
rlink0 ← 100000c, return;*pass done - no need to set base

********** SUBROUTINE: NextPattern **********
*
*
NextPattern finds the next data pattern to use,
*
increments the PassCount, and returns it
*
in the T register.
*
OnPage[2];
NextPattern:
t ← (PatternTry) and not (17C);*what pattern to use?
goto[WhatPattern,alu=0];*exhausted all four pattern types?
PatternTry ← 1C;*yes, select the zero pattern again
Toggle ← 0C;*reset checker pattern toggle
PassCount← t ←(PassCount)+1;*increment pass count
WhatPattern:
t ← PatternChoice;*determine what pattern to use
t ← (PatternTry) AND (t);
goto[Next,alu=0];*do we want to use this pattern?
ThisPattern: CurrentPattern ← t;
*yes, use this pattern
PatternTry ← LSH[PatternTry,1];
T ← PassCount, RETURN;
Next:
PatternTry ← LSH[PatternTry,1], goto[NextPattern];*no, try the next pattern

********** SUBROUTINE: rand **********
*
*
rand produces a pseudorandom number in t and xa.
*
xa← 4005*xa + ca mod 2**16
*
OnPage[TestPage];
rand:
t←xa;
t←(lsh[xa,2])+(t);*t← 5*xa
t←(lsh[xa,13])+(t);*t←4005*xa
t←(ca)+t;
xa←t,return;

********** SUBROUTINE: ReadMap **********
*
*
ReadMap reads one entry from map location CurrentLoc
*
into rbuf0, then compares it with wbuf0 under mask0
*
ReadMap:
usectask;
T ← apc&apctask;
rlink0 ← T, call[WriteMap];
T ← lsh[wbuf3, 10];*flags, card, blk.0 bits
rbuf0 ← T;
T ← (wbuf1) and (377C);
rbuf0 ← (rbuf0) or (T);
t ← rbuf0 ← (rbuf0) xnor (0c);*data is read from the map complemented
Rtemp ← 0c;
LoadPage[2];
callP[CheckData];
apc&apctask ← rlink0;
return;

********** SUBROUTINE: ReadMem **********
*
*
ReadMem reads a quadword from location CurrentPage,,CurrentLoc into rbuf0-3,
*
then compares the results with wbuf0-3 under the mask mask0-3.
*
On error, the difference is in T. The memory operation used to read
*
the data is determined by ControlReg[14,15].
*
OnPage[2];
ReadMem:
usectask;
T ← apc&apctask;
rlink0 ←T;
T ← CurrentLoc, call[Read];*set up to take faults
ShortLoop ← ShortLoop, goto[MemFault, R EVEN];*ShortLoop for debugging?
goto[ChkData];
MemFault:
breakpoint, goto[ChkData], AT[1014];
Read:
Dispatch[ControlReg,14,2];
Disp[Rtype0];

SET[RType,Add[Lshift[2,10],140]];
RType0:
PFetch4[BaseL,rbuf0], goto[ChkData],at[Rtype,0];*read using PFetch4
RType1:
PFetch4[BaseL,rbuf0], goto[ChkData],at[Rtype,1];*read using PFetch4
RType2:
PFetch2[BaseL,rbuf0],at[Rtype,2];*read using two PFetch2’s
T ← (zero)+(T)+1;
T ← (zero)+(T)+1;
PFetch2[BaseL,rbuf2], goto[ChkData];
RType3:
PFetch1[BaseL,rbuf0],at[Rtype,3];*read using four PFetch1’s
T ← (zero)+(T)+1;
PFetch1[BaseL,rbuf1];
nop;
T ← (zero)+(T)+1;
PFetch1[BaseL,rbuf2];
nop;
T ← (zero)+(T)+1;
PFetch1[BaseL,rbuf3], goto[ChkData];
ChkData:
rbuf0 ← rbuf0; *interlock
Rtemp ← 0c, call[CheckData];
Rtemp ← 2c, call[CheckData];
Rtemp ← 4c, call[CheckData];
Rtemp ← 6c, call[CheckData];
apc&apctask ← rlink0;
RETURN;

********** SUBROUTINE: SetBase **********
*
*
SetBase sets up base pair BaseL,BaseH to point to CurrentPage
*
OnPage[TestPage];
SetBase:
T ← lhmask[CurrentPage];
BaseH ← T;
T ← lsh[CurrentPage,10];
BaseL ← T, return;

********** SUBROUTINE: WriteMap **********
*
*
WriteMap writes the data in wbuf0 into the map at CurrentLoc
*
WriteMap:
t ← (CurrentLoc) and (37400c);*map address is 14 bits
BaseH ← t;
t ← lsh[CurrentLoc,10];
BaseL ← t;
XMap[BaseL,wbuf0,0];
T ← wbuf0 ← wbuf0, return;*interlock the XMap, reload T

END;*end main routine