//MXTALL.BCPL

get "mx.d"

//TestAll() sequentially tests all the registers and memories in the
//microprocessor using the selected data pattern and a full-sized
//mask for data comparison.  On failure the results are left in
//DATA-WAS, SHOULD-BE, and BITS-CHECKED.  The testing consists of
//250 iterations for each register and four passes through each memory.

//RepeatGo() starts the microprocessor at an address in IMA (setup by
//MCMD.BCPL), waits for it to halt, then loops endlessly.

//RepestSS() repeatedly single-steps at the selected address.

static [ TAllState; T40; T36; T20; T18; TARM; T12; T9; T8; T4; T3
	TestAborted; FirstAct ]


let TestAll() = valof
[	GetPattern(NREALREGS+NREALMEMS-2); TAllState = 0
	T40 = table [ 177777B; 177777B; 177400B ]
	T36 = table [ 177777B; 177777B; 170000B ]
	T20 = table [ 177777B; 170000B; 0 ]
	T18 = table [ 177777B; 140000B; 0 ]
	TARM = table [ 0; 7777B; 170000B ]
	T12 = table [ 177760B; 0; 0 ]
	T9 = table [ 177600B; 0; 0 ]
	T8 = table [ 177400B; 0; 0 ]
	T4 = table [ 170000B; 0; 0 ]
	T3 = table [ 160000B; 0; 0 ]
	resultis TAllMenu
]


and TAllMenu(S,Nix) be
[	if QuitF eq -2 do
	[ QuitF = AddToEveryTimeList(TAllRM,0)
	  Resets(CmdCommentStream)
	]
	WsMarkA(QUITact)
	if QuitF eq -1 do
	[ for I = 0 to NPATS-1 do WsMarkA(PATACT!I) ]
]


and RTest(RegX,DataVec) be
[	TestWidth = REGWID!RegX
	WssCSS(REGNAM!RegX); Puts(CmdCommentStream,$ )
	UpdateDisplay()
	MoveBlock(DMASK,DataVec,3)	//Set up comparison mask
	XctMic(CLRARM); XctMic(INTRETN)	//For P1
	Zero(ITRCNT+3,2)
	for I = 0 to 250 do
	[ PutRegData(RegX,GOODD); GetRegData(RegX,ACTD)
	  if CheckData() then ErrorStop(REGNAM!RegX," failed")
	]
	TAllState = TAllState+1
]


and MTest(MemX,DataVec) be
[	let SaveRX,SaveRD,SaveGD,AddrVec = nil,nil,vec 3,vec 1
	TestWidth = MEMWID!MemX; AddrVec!0 = 0
	if (TAllState & 3) eq 0 do
	[ WssCSS(MEMNAM!MemX); Puts(CmdCommentStream,$ )
	  UpdateDisplay()
	]
	MoveBlock(DMASK,DataVec,3)	//Set up comparison mask
	Zero(ITRCNT+3,2)
	SaveRX = RANDIX; SaveRD = RANDATA
	MoveBlock(SaveGD,GOODD,3)
	LoadDone = false
	for J = 0 to (MEMLEN!MemX)-1 do
	[ AddrVec!1 = J; PutMemData(MemX,AddrVec,GOODD); NextGDATA() ]
	MoveBlock(GOODD,SaveGD,3); RANDIX = SaveRX; RANDATA = SaveRD
	for J = 0 to (MEMLEN!MemX)-1 do
	[ AddrVec!1 = J; GetMemData(MemX,AddrVec,ACTD)
	  if CheckData() do [ ErrorStop(MEMNAM!MemX," failed") ]
	]
	TAllState = TAllState+1
]

//MAIN, MAR, KMAR, KUNIT not tested
and TAllRM() be
[	switchon TAllState into
	[
case 0:	RTest(14,T36); return	//EREG
case 1:	RTest(0,T8); return	//X
case 2:	RTest(1,T4); return	//AC
case 3:	RTest(2,T9); return	//Y
case 4:	RTest(3,T36); return	//P
case 5:	RTest(4,T36); return	//Q
case 6:	RTest(6,T12); return	//NPC
case 7:	RTest(8,T40); return	//MDR
case 8:	RTest(10,T40); return	//KMDR
case 9:	RTest(11,TARM); return	//ARM
case 10:	RTest(12,T12); return	//IMA
case 11:	RTest(15,T20); Resets(CmdCommentStream); return	//BPC
// The memory tests should begin with two low bits of TAllState eq 0
case 12: case 13: case 14: case 15:	MTest(8,T36); return	//LM
case 16: case 17: case 18: case 19:	MTest(7,T36); return	//RM
case 20: case 21: case 22: case 23:	MTest(9,T12); return	//STK
case 24: case 25: case 26: case 27:	MTest(3,T36); return	//SM
case 28: case 29: case 30: case 31:	MTest(5,T18); return	//MP
case 32: case 33: case 34: case 35:	MTest(4,T36); return	//DM
case 36: case 37: case 38: case 39:	MTest(0,T36); return	//IM[0,35]
case 40: case 41: case 42: case 43:	MTest(1,T36); return	//IM[36,71]
case 44:	RTest(5,T36); return	//F
case 45:	RTest(13,T3); return	//KUNIT
case 46:	RTest(16,T36); endcase	//P1
	]
	ErrorStop("Everything AOK","")
]


//Start microprocessor at selected address and repeatedly restart it
//after breakpoints until termination by mouse.
and RepeatGo(Addr; numargs Zot) =
	RepeatX(MGO,Addr,Zot,"Repeating after breakpoints at")


//Similar to RepeatGo, but single-step rather than go
and RepeatSS(Addr; numargs Zot) =
	RepeatX(SINSTP,Addr,Zot,"Repeatedly stepping at")


and RepeatX(Inst,Addr,Zot,String) = valof
[	SetupNPCIMA(Addr,Zot)
	WssCSS(String); Wos(CmdCommentStream,MADDRL)
	QUITact = CreateAction("Abort",lv RepStop,0,0,$C-100B)
	QuitF = AddToEveryTimeList(GoMADDRL,Inst)
	resultis TestMenu
]


//"Abort" is the only menu item--it comes here
and RepStop(S,garb,Buttons,Nix) be
[	@ADREG = RUN
RSLoop:	if (@INREG & 200B) ne 0 then [ XctMic(MSTOP); goto RSLoop ]
	Resets(CmdCommentStream); WssCSS("Repeat halted")
	MaxcStopped(true)
]


//This is called every time through DriverLoop
and GoMADDRL(inst) be
[	@ADREG = RUN
	if (@INREG & 200B) ne 0 then return	//Twice avoiding glitches
	if (@INREG & 200B) ne 0 then return
	RestoreMRegs(2); ResetMaxc(inst)
]

and GetPattern(firstact) be
[	FirstAct = firstact; TestAborted = false
	QUITact = CreateAction("Abort",lv TestStop,firstact,0,$C-100B)
	DefPattern("ZEROES",0); DefPattern("ONES",1)
	DefPattern("CYC1",2); DefPattern("CYC0",3)
	DefPattern("RANDOM",4); DefPattern("ALTZO",5)
	DefPattern("SEQUENTIAL",6); DefPattern("ALT-SHOULD-BE",7)
	QuitF = -1
	Zero(ITRCNT,5)
	WssCSS("Select data pattern:")
]


and DefPattern(str,PatX) be
[	PATACT!PatX = CreateAction(str,lv SetPattern,PatX)
]


and SetPattern(S,garb,Buttons,PatX) be
[	PATTERN = PatX; QuitF = -2
	switchon PatX into
	[
case 0:
case 5:
case 6:	Zero(GOODD,3); endcase
case 1:	SetBlock(GOODD,-1,3); endcase
case 2:	MoveBlock(GOODD,table[ 0; 0; 10000B ] ,3); endcase
case 3:	MoveBlock(GOODD,table[ -1; -1; 160000B ] ,3); endcase
case 4:	NextGDATA(); endcase
case 7:	LeftAdjust(GDATA,GOODD,36); endcase
	]
	FormMenu(CmdMDFS,FormCmdmenuText)
]