% *** *** *** *** 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 0 0 NO INCREMENT for CurrentLoc in MapTest 1 INCREMENT CurrentLoc by 1 in MapTest bit 1 0 use VARYING DATA for MapTest 1 use CONSTANT DATA for MapTest bit 2 0 NO INCREMENT for CurrentLoc in StorageTest 1 INCREMENT CurrentLoc by 4 in StorageTest bit 3 0 use VARYING DATA for StorageTest 1 use CONSTANT DATA for StorageTest bit 14 bit 15 0 0 read real storage using PFETCH4 0 1 read real storage using PFETCH4 1 0 read real storage using PFETCH2 1 1 read real storage using PFETCH1 bit 16 bit 17 0 0 store real storage using PSTORE4 0 1 store real storage using PSTORE4 1 0 store real storage using PSTORE2 1 1 store 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 0 0 kernel does not go to the User Fault Handling routine 1 kernel goes to the User Fault Handling routine bit 16 0 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- bit block0 block1 block2 drome in (octal) error (decimal) (0-63) 1 c.7 U082 U143 U143 2 c.6 U104 U165 U165 4 c.5 U103 U164 U164 7 0 U003 U003 U065 10 c.4 U081 U142 U142 13 16 U005 U005 U067 15 32 U065 U126 U126 16 48 U067 U128 U128 20 c.3 U020 U020 U082 26 8 U011 U011 U073 32 24 U013 U013 U075 34 40 U073 U134 U134 37 56 U075 U136 U136 40 c.2 U042 U042 U104 46 4 U007 U007 U069 52 20 U009 U009 U071 54 36 U069 U130 U130 57 52 U071 U132 U132 67 12 U015 U015 U077 73 28 U017 U017 U079 75 44 U077 U138 U138 76 60 U079 U140 U140 100 c.1 U041 U041 U103 106 2 U026 U026 U088 112 18 U028 U028 U090 114 34 U088 U149 U149 117 50 U090 U151 U151 127 10 U034 U034 U096 133 26 U036 U036 U098 135 42 U096 U157 U157 136 58 U098 U159 U159 147 6 U030 U030 U092 153 22 U032 U032 U094 155 38 U092 U153 U153 156 54 U094 U155 U155 166 14 U038 U038 U100 172 30 U040 U040 U102 174 46 U100 U161 U161 177 62 U102 U163 U163 200 c.0 U019 U019 U081 206 1 U025 U025 U087 212 17 U027 U027 U089 214 33 U087 U148 U148 217 49 U089 U150 U150 227 9 U033 U033 U095 233 25 U035 U035 U097 235 41 U095 U156 U156 236 57 U097 U158 U158 247 5 U029 U029 U091 253 21 U031 U031 U093 255 37 U091 U152 U152 256 53 U093 U154 U154 266 13 U037 U037 U099 272 29 U039 U039 U101 274 45 U099 U160 U160 277 61 U101 U162 U162 307 3 U004 U004 U066 313 19 U006 U006 U068 315 35 U066 U127 U127 316 51 U068 U129 U129 326 11 U012 U012 U074 332 27 U014 U014 U076 334 43 U074 U135 U135 337 59 U076 U137 U137 346 7 U008 U008 U070 352 23 U010 U010 U072 354 39 U070 U131 U131 357 55 U072 U133 U133 367 15 U016 U016 U078 373 31 U018 U018 U080 375 47 U078 U139 U139 376 63 U080 U141 U141 **************************************************************************************** * * Crash Code Table: (CrashCode is displayed on the Midas screen.) 200 R or CS parity error 201 Supposed to be an impossible situation 202 Map Out of Bounds 203 H4PE (input bus) parity error 204 Map Out of Bounds and H4PE (input bus) parity error 205 got an unexpected MC2 error (probable memory chip failure) 206 2 MC2 errors 207 MC1 fault when emulator couldn't accept it 210 Fault from the instruction following a LoadPage 211 Stack 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(1270)\6778u5U86u5U69u5U94u5U77u6U1u6U174u6U1u6U7970v7V