// MemBash.bcpl -- Maxc2 memory contention diagnostic // Assumes a memory diagnostic (e.g., DGMR) running on Maxc // Last modified June 4, 1978 5:51 PM get "streams.d" external [ Ws; Wss; Gets; Puts; Endofs; Resets; Noop; MoveBlock; Zero CreateDisplayStream; ShowDisplayStream; StartIO MemRead; MemWrite; MemRMW InputSMI; OutputSMI; OutputSMIPulse InputSMIErrors; OutputSMITest; ExecuteMicroInstruction; LoadBus; ReadBus LoadRam; SetBLV; USetBLV RamImage; dsp; keys; lvUserFinishProc; adrMTBS ] static [ AltoOperation; NextAdr altoNumber; maxcNumber; numberTyped; altoCode; testAdr displayEnabled = true startAdr = #21 savedUserFinishProc fatalSE = false; fatalPBF = false adrMTBS //external wanted by AltIOUtila.asm ] manifest [ //Maxc processor states (software convention) stateRunning = 0 //processor running stateBreakpoint = 1 //at micro-breakpoint stateLocalMemPE = 2 //local memory parity error stateMainBusPE = 3 //main memory bus parity error stateHalted = 4 //halted for other reason //SMI input addresses smiRUN = #200 //processor run status smiB0 = #203 //processor bus smiB1 = #202 smiB2 = #201 smiJKERRS = #43 //memory errors for quadrants J and K smiLMERRS = #44 //memory errors for quadrants L and M //SMI output addresses smiBR0 = #213 //processor bus smiBR1 = #212 smiBR2 = #211 smiPIR0 = #217 smiPIR1 = #216 //pseudo-instruction register smiPIR2 = #215 smiPIR3 = #214 smiCR = #210 //control register smiPLMR = #40 //physical/logical memory module register smiCONFR = #41 //memory configuration register smiRESR = #42 //memory error reset register ] structure RUN: //processor run status [ blank bit 8 running bit //processor is running notBreakpoint bit //not at micro breakpoint localPE bit //local memory parity error mainPE bit //main memory data bus parity error ] structure QErr↑0,3 byte //memory error register (2 words) manifest //layout assuming byte right-justified [ qeTimeout = #40 qeDIP = #20 qeAPE = #10 qePBF = #4 qeDE = #2 qeSE = #1 ] manifest //processor control register [ crEIC = #100000 //enable instruction controlled changes crEB = #40000 //enable changes to branch conditions crEIMA = #20000 //enable changes to IMA crENPC = #10000 //enable changes to NPC crNOTSS = #4000 //don't single step crSetRun = #2000 //set the run flipflop crReset = #1000 //reset processor-memory interface crEPIR = #400 //execute instructions from PIR rather than IM crRegToB = #200 //put BR register on processor bus crIntOn = #100 //enable micro-interrupts crStrobe = #40 //generate interprocessor signal //normal value sent to CR (e.g., when setting Strobe) crNormal = crEIC+crEB+crEIMA+crENPC+crNOTSS+crIntOn ] structure PLMR: //physical/logical module register [ blank bit 7 disableCorrection bit logicalModule bit 3 physicalModule bit 3 quadrant bit 2 ] structure CONFR: //configuration register [ blank bit 4 eFER bit //enable reporting of fatal errors configuration bit 3 //address/quadrant map jSEF bit //quadrant J single errors fatal jPBFF bit //quadrant J parity bit failures fatal kSEF bit kPBFF bit lSEF bit lPBFF bit mSEF bit mPBFF bit ] manifest allSEF = #252 manifest allPBFF = #125 manifest enableFER = #4000 structure RESR: //error reset register (all bits complemented) [ blank bit 8 jResetErrors bit //reset errors in quadrant J jResetQuadrant bit //completely reset quadrant J kResetErrors bit kResetQuadrant bit lResetErrors bit lResetQuadrant bit mResetErrors bit mResetQuadrant bit ] manifest allResetErrors = #125 manifest allResetQuadrant = #252 structure SMIErr: //SMI error register [ blank bit 11 comb bit //communication strobe B (unused) coma bit //communication strobe A nfer bit //non-fatal error fer bit //fatal error blank bit ] manifest smiErrorMask = #12 //bits that we care about (coma, fer) // --------------------------------------------------------------------------- let MemBash() be // --------------------------------------------------------------------------- [ Ws("MemBash of June 4, 1978") //load the special Ram microcode RamImage!0 = #077376 //run tasks 0, 10, 17 in Ram let res = LoadRam(RamImage, true) //load and boot if res ls 0 then Ws("*nFailed to load Alto Ram -- Ram or Ethernet board broken") if res gr 0 then Ws("*nMicrocode constants wrong, beware!") savedUserFinishProc = @lvUserFinishProc @lvUserFinishProc = MyFinishProc Ws("*nAlto MI State Address Maxc State MAR KMAR Memory State") let ds = vec 15000 ds = CreateDisplayStream(30, ds, 15000) ShowDisplayStream(ds) dsp = ds OutputSMITest(#16) ConfigureMemory(0, 0) let v = vec 2; maxcNumber = v let v = vec 1; testAdr = v; Zero(testAdr, 2) AltoOperation = MemRead NextAdr = IncrementAdr Command() ] // --------------------------------------------------------------------------- and Command() be // --------------------------------------------------------------------------- [ Ws("*n**") let char = GetKeys() switchon char into [ case $G: case $g: [ if Confirm("Go") then DoTest() endcase ] case $A: case $a: [ Ws("Alto operation = ") switchon GetKeys() into [ case $R: case $r: [ Ws("Read"); AltoOperation = MemRead; endcase ] case $W: case $w: [ Ws("Write"); AltoOperation = MemWrite; endcase ] case $M: case $m: [ Ws("Modify"); AltoOperation = MemRMW; endcase ] case $?: [ Ws("? Read, Write, Modify"); loop ] default: [ Oop(); loop ] ] Ws(", address sequence = ") switchon GetKeys() into [ case $S: case $s: [ Ws("Sequential"); NextAdr = IncrementAdr; endcase ] case $R: case $r: [ Ws("Repeat at address: ") test GetNumber() eq $*n & numberTyped ifso MoveBlock(testAdr, maxcNumber+1, 2) ifnot [ Oop(); loop ] NextAdr = Noop endcase ] case $?: [ Ws("? Sequential, Repeat"); loop ] default: [ Oop(); loop ] ] endcase ] case $M: case $m: [ Ws("Maxc start address = ") test GetNumber() eq $*n & numberTyped ifso startAdr = altoNumber ifnot Oop() endcase ] case $D: case $d: [ if Confirm(displayEnabled? "Don't display errors", "Display errors") then displayEnabled = not displayEnabled endcase ] case $Z: case $z: [ if Confirm("Zap memory") then ResetMemory() endcase ] case $Q: case $q: [ if Confirm("Quit") then finish endcase ] case $?: [ Ws("? Alto operation, Maxc start adr, Go, Display, Zap, Quit") endcase ] case $*n: case $*s: endcase default: Oop(char) ] ] repeat // --------------------------------------------------------------------------- and DoTest() be // --------------------------------------------------------------------------- [ Ws("*nTest running, hit any key to stop") StartMaxc(startAdr) [ Zero(maxcNumber, 3) altoCode = AltoOperation(testAdr, maxcNumber) let smiErr = InputSMIErrors() if altoCode ne 0 % smiErr<<SMIErr.fer then [ test displayEnabled ifso DisplayErrors() ifnot Puts(dsp, $?) if smiErr<<SMIErr.fer then StartMaxc(startAdr) ] NextAdr() ] repeatwhile Endofs(keys) StopMaxcForcefully() Gets(keys) ] // --------------------------------------------------------------------------- and IncrementAdr() be // --------------------------------------------------------------------------- [ testAdr!1 = (testAdr!1+#10000) & #170000 if testAdr!1 eq 0 then testAdr!0 = (testAdr!0+1) & #37777 ] // --------------------------------------------------------------------------- and Display20Bit(str,adr) be PrintOctalField(str,adr,0,19) // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- and Display36Bit(str,adr) be // --------------------------------------------------------------------------- [ PrintOctalField(str,adr,0,17) Puts(str,$*s) PrintOctalField(str,adr,18,35) ] // --------------------------------------------------------------------------- and Display40Bit(str,adr) be // --------------------------------------------------------------------------- [ test (adr!2 & #7400) ne 0 ifso PrintOctalField(str,adr,36,39) ifnot Wss(str," ") Puts(str,$*s) Display36Bit(str,adr) ] // --------------------------------------------------------------------------- and PrintOctalField(str,adr,firstBit,lastBit) be // --------------------------------------------------------------------------- [ let r = (lastBit-firstBit) rem 3 firstBit = firstBit+r let mask = (2 lshift r)-1 [ let q,r = firstBit rshift 4, firstBit Puts(str,$0 + ((adr!(q-1) lshift (1+r) + adr!q rshift (15-r)) & mask)) firstBit = firstBit+3 mask = 7 ] repeatuntil firstBit gr lastBit ] // --------------------------------------------------------------------------- and DisplayErrors() be // --------------------------------------------------------------------------- [ Puts(dsp, $*n) Ws(selecton altoCode into [ case 0: " " case 1: "Mem bus PE " case 2: case 3: "Timed out " default: "Impossible " ]) Ws(" ") Display20Bit(dsp, testAdr) Ws(" ") let state = MaxcState() Ws(selecton state into [ case stateRunning: "Running " case stateBreakpoint: "Breakpoint " case stateLocalMemPE: "Local mem PE" case stateMainBusPE: "Mem bus PE " case stateHalted: "Halted " ]) Ws(" ") if state eq stateRunning then StopMaxcForcefully() let maxcData = vec 2 ExecuteMicroInstruction( table // B←MAR [ #040102; #077546; #120001; #000000; #003400 ]) ReadBus(maxcData) Display20Bit(dsp, maxcData+1) Ws(" ") ExecuteMicroInstruction( table // B←KMAR [ #040102; #077546; #160001; #000000; #003400 ]) ReadBus(maxcData) Display20Bit(dsp, maxcData+1) if state eq stateRunning then StartMaxc() Puts(dsp, $*s) let qErr = vec 1 qErr!0 = InputSMI(smiJKERRS) qErr!1 = InputSMI(smiLMERRS) OutputSMI(smiRESR, allResetErrors) for i = 0 to 5 do [ let mask = #401 lshift i if (qErr!0 & mask) ne 0 % (qErr!1 & mask) ne 0 then [ Ws(selecton i into [ case 0: " SE: " case 1: " DE: " case 2: " PBF: " case 3: " APE: " case 4: " DIP: " case 5: " Timeout: " ]) for q = 0 to 3 do if (qErr>>QErr↑q & mask) ne 0 then Puts(dsp,$J+q) ] ] ] // --------------------------------------------------------------------------- and StartMaxc(microAdr; numargs na) be // --------------------------------------------------------------------------- //start Maxc running at the specified micro-address, or just //resume it if microAdr is not specified [ if na gr 0 then [ let maxcData = vec 3 maxcData!0 = 0 maxcData!1 = microAdr rshift 4 maxcData!2 = microAdr lshift 12 LoadBus(maxcData) ExecuteMicroInstruction( // NPC←BR, ENPC table [ #040102; #077546; #000000; #020000; #113600 ]) maxcData!2 = (maxcData!2+#10000) & #170000 if maxcData!2 eq 0 then maxcData!1 = maxcData!1 + 1 LoadBus(maxcData) ExecuteMicroInstruction( // NPC←BR, ENPC, EIMA table [ #040102; #077546; #000000; #020000; #133600 ]) ExecuteMicroInstruction( // IRET, INHINT table [ #040102; #077546; #000152; #000000; #103400 ]) ] ExecuteMicroInstruction( // WRESTART, KWRESTART table [ #040102; #077546; #000110; #160000; #103400 ]) ExecuteMicroInstruction( // FRZBALUBC, EIC, EB, ENPC, EIMA, NOTSS, Strobe table [ #040102; #077546; #000155; #000000; #177140 ]) InputSMIErrors() ] // --------------------------------------------------------------------------- and StopMaxcForcefully() be // --------------------------------------------------------------------------- OutputSMI(smiCR,not (crEIC+crEB+crEIMA+crENPC+crIntOn)) // --------------------------------------------------------------------------- and MaxcState() = valof // --------------------------------------------------------------------------- [ let runReg = InputSMI(smiRUN) if runReg<<RUN.running resultis stateRunning unless runReg<<RUN.notBreakpoint resultis stateBreakpoint if runReg<<RUN.localPE resultis stateLocalMemPE if runReg<<RUN.mainPE resultis stateMainBusPE resultis stateHalted ] // --------------------------------------------------------------------------- and ResetMemory() be // --------------------------------------------------------------------------- [ OutputSMI(smiRESR, 0) //full reset ConfigureMemory(0, 0) ] // --------------------------------------------------------------------------- and ConfigureMemory(map,fatality) be // --------------------------------------------------------------------------- //setup the memory system with the logical-physical mapping //defined by "map", which is in the following form (see Maxc 11.6): // B0: disable error correction for module 0 // B1-3: logical module assignment for module 0 // B4: disable error correction for module 1 // etc. //"fatality" determines whether SE and PBF are fatal: // B0: SE fatal // B1: PBF fatal [ //set standard quadrant configuration (0) and fatality as specified fatalSE = (fatality & #100000) ne 0 fatalPBF = (fatality & #40000) ne 0 OutputSMI(smiCONFR, enableFER+(allSEF&fatalSE)+(allPBFF&fatalPBF)) //set logical-physical map for each module in each quadrant if map eq 0 then map = #040142 //standard configuration for m = 0 to 3 do for q = 0 to 3 do [ let plmr = map rshift (7-4*m) //position ec and log mod number plmr<<PLMR.physicalModule = m plmr<<PLMR.quadrant = q OutputSMIPulse(smiPLMR,plmr) ] OutputSMI(smiRESR, allResetErrors) ] // --------------------------------------------------------------------------- and GetNumber() = valof // --------------------------------------------------------------------------- //inputs an octal number from the keyboard, ignoring spaces. //returns a 16-bit result in altoNumber and a 40-bit result //in maxcNumber. numberTyped will be true iff a number was typed [ altoNumber = 0 Zero(maxcNumber,3) numberTyped = false [ let char = GetKeys() if char eq $*s then [ Puts(dsp,char); loop ] if char ls $0 % char gr $7 then resultis char numberTyped = true Puts(dsp,char) altoNumber = altoNumber lshift 3 + char-$0 let overflow = maxcNumber!0 rshift 13 maxcNumber!0 = maxcNumber!0 lshift 3 + maxcNumber!1 rshift 13 maxcNumber!1 = maxcNumber!1 lshift 3 + maxcNumber!2 rshift 13 maxcNumber!2 = (maxcNumber!2 & #010400) lshift 3 + (char-$0) lshift 12 + overflow lshift 8 ] repeat ] // --------------------------------------------------------------------------- and Confirm(prompt; numargs na) = valof // --------------------------------------------------------------------------- [ if na gr 0 then Ws(prompt) Ws(" [confirm] ") [ switchon GetKeys() into [ case $Y: case $y: case $*n: case $.: [ Ws("Yes."); resultis true ] case $N: case $n: case $*177: [ Ws("No."); resultis false ] ] Oop() ] repeat ] // --------------------------------------------------------------------------- and Oop(char; numargs na) be // --------------------------------------------------------------------------- [ if na gr 0 then Puts(dsp,char) Ws(" ? ") Resets(keys) ] // --------------------------------------------------------------------------- and GetKeys() = Gets(keys) // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- and MyFinishProc() be // --------------------------------------------------------------------------- [ @lvUserFinishProc = savedUserFinishProc USetBLV(#177776) StartIO(#100000) ] // --------------------------------------------------------------------------- and Ws(string) be Wss(dsp, string) // ---------------------------------------------------------------------------