{ Syzygy.mc, HGM, 29-Apr-83  0:29:24

HGM,  8-Jan-83 19:09:13, add runtime number of banks

 Description: Memory test.  Writes random data in 192k then checks the data against the computed data.  The random number generator was supplied by Bob Garner,
 Author: J. Cucinitti,
 Created: November 14, 1979  7:22 AM, 
 Last Edited: January 21, 1980  10:19 AM}


RegDef[banks,U,9];	{Number of banks to test}
RegDef[rMem,R,0];	{Memory Address, cell location within bank}
RegDef[rhMem,RH,0];	{Memory Address, bank selection}
RegDef[rWData,R,1];
RegDef[rCon,R,2];
RegDef[rRefCnt,R,3];	{Checks for Refresh time}
RegDef[rPassCnt,R,4];	{Number of current pass of the diagnostic}
RegDef[rRData,R,5];
RegDef[rResult,R,6];
RegDef[rBank,R,7];	{Keeps track of memory bank being used}
RegDef[rTempA,R,8];
RegDef[rTempB,R,9];



	Reserve[0F5F, 0FFF]; {section used by the CP Kernel }
	SetTask[0]; StartAddress[Go];

{Initialization}

Trap:	rTempA ← RRot1 ErrnIBnStkp, ClrIntErr, CANCELBR[$, 0F], c1, at[0];
	Xbus ← rTempA LRot0, XwdDisp,			c2;
	DISP2[TrapType],				c3;
	
ControlStoreParityError:	GOTO[GoToGo],		c1, at[0,4,TrapType];
DoubleBitMemoryError:		GOTO[GoToGo],		c1, at[1,4,TrapType];
StackErrorTrap:			GOTO[GoToGo],		c1, at[2,4,TrapType];
IBRefillTrap:			GOTO[GoToGo],		c1, at[3,4,TrapType];

GoToGo:
	Noop,						c2;
	Noop, GOTO[Go],					c3;

Go:	rCon ← 36,					c1, at[0E];
	rCon ← rCon LRot8,				c2, at[0F];
	rCon ← rCon or 19, {rCon ← 3619}		c3;

	MCtl ← 1, {disable error correction}		c1;
	rPassCnt ← 1,					c2;
	rRefCnt ← 8, GOTO[WritePass],			c3;

WritePass:
	rBank ← banks,					c1;
	rBank ← rBank - 1,				c2;
	rMem ← rMem xor ~rMem,				c3;

	rhMem ← rBank LRot0,				c1;
	Noop,						c2;
	Noop, GOTO[WSeed],				c3;
{---------------------------------------------------------------------------------------------}
{ Here we set the seed for the random number using the bank number and the pass number.  Next we generate the random number. We then check to see it is refresh time, if not refresh time we write memory with the random number. After writing memory we check to see if this is the last location of this bank to be written.}


WSeed:	rWData ← rPassCnt LRot8,			c1;
	rWData ← rWData + rBank,			c2;
	rWData ← rWData + rPassCnt, {seed for write is now set}	c3;
CkWRef:	rTempA ← LShift1 rWData,			c1, at[1,2,WBump];
	rTempB ← rWData and 1F,				c2;
	rTempB ← rTempB LRot12,				c3;

	rTempB ← rTempB RRot1,				c1;
	rWData ← rWData + rTempA,			c2;
	rWData ← rWData + rTempB,			c3;

	rWData ← rWData + rCon,				c1;
	rRefCnt ← rRefCnt - 1, ZeroBr,			c2;
	BRANCH[Write,WRef],				c3;

Write:	MAR ← [rhMem,rMem + 0],				c1, at[0,2,WRef];
	MDR ← rWData, rMem ← rMem - 1, CarryBr,		c2;
	BRANCH[WBump,CkWRef],				c3;

WRef:	Refresh,					c1, at[1,2,Write];
	rRefCnt ← 8,					c2;
	Noop, GOTO[Write],				c3;

{---------------------------------------------------------------------------------------------}
{ Here we set the seed for the read pass using the bank number and the pass number.  Next we generate the random number. We then check to see it is refresh time, if not refresh time we read memory and compare the data that is read from memory against the computed random number. After reading memory we check to see if this is the last location of this bank to be written.}

RSeed:	rWData ← rPassCnt LRot8,			c1;
	rWData ← rWData + rBank,			c2;
	rWData ← rWData + rPassCnt,			c3;

CkRRef:	rTempA ← LShift1 rWData,			c1, at[1,2,RBump];
	rTempB ← rWData and 1F,				c2;
	rTempB ← rTempB LRot12,				c3;

	rTempB ← rTempB RRot1,				c1;
	rWData ← rWData + rTempA,			c2;
	rWData ← rWData + rTempB,			c3;

	rWData ← rWData + rCon,				c1;
	rRefCnt ← rRefCnt - 1, ZeroBr,			c2;
	BRANCH[Read,RRef],				c3;

Read:	MAR ← [rhMem,rMem + 0],				c1, at[0,2,RRef];
	Noop,						c2;
	rRData ← MD,					c3;

	rResult ← rRData,				c1;
	rResult ← rResult xor rWData, ZeroBr,		c2;
	BRANCH[Error,RCont],				c3;

RCont:	Noop,						c1;
	rMem ← rMem - 1, CarryBr,			c2;
	BRANCH[RBump,CkRRef],				c3;

RRef:	Refresh,					c1, at[1,2,Read];
	rRefCnt ← 5,					c2;
	Noop, GOTO[Read],				c3;

{---------------------------------------------------------------------------------------------}
{During this loop we check to see if this is the last bank of memory to be written.}

WBump:	rMem ← rBank - 1, NegBr,			c1, at[0,2,CkWRef];
	rBank ← rMem, BRANCH[$, RStart],		c2;
	rhMem ← rMem LRot0,				c3;

	rMem ← rMem xor ~rMem,				c1;
	rRefCnt ← 8,					c2;
	Noop, GOTO[WSeed],				c3;

{---------------------------------------------------------------------------------------------}
{This is the initialization of the memory address registers for the read pass.}

RStart:	rBank ← banks,					c3;

	rBank ← rBank -1,				c1;
	rMem ← rMem xor ~rMem,				c2;
	rhMem ← rBank LRot0,				c3;

	Refresh,					c1;
	rRefCnt ← 5,					c2;
	Noop, GOTO[RSeed],				c3;

{---------------------------------------------------------------------------------------------}
{During this loop we check to see if this is the last bank of memory to be read.}

RBump:	rMem ← rBank - 1, NegBr,			c1, at[0,2,CkRRef];
	rBank ← rMem, BRANCH[RSetAdd,ShowY],		c2;
RSetAdd:
	rhMem ← rMem LRot0,				c3, at[0,2,ShowY];

	rMem ← rMem xor ~rMem,				c1;
	rRefCnt ← 5,					c2;
	Noop, GOTO[RSeed],				c3;


{---------------------------------------------------------------------------------------------}
{This loop will put the pass count on the Ybus, unless a break point has been set.}

Error:	Ybus ← rPassCnt,				c1, at[0,2,RCont];
	Ybus ← rPassCnt,				c2;
	Ybus ← rPassCnt, GOTO[Error],			c3;


{---------------------------------------------------------------------------------------------}
{This loop displays the Pass Count on the Ybus and uses the small display box. While diagnostic is running you should see the pass count for approximately four seconds interrupted by scintillating 8s.}

ShowY:	Ybus ← rPassCnt,				c3, at[1,2,RSetAdd];
	Ybus ← rPassCnt, rTempA ← 0FF,			c1;
	Ybus ← rPassCnt, rTempB ← 0A,			c2;
	Ybus ← rPassCnt,				c3;

MDel:	Ybus ← rPassCnt,				c1;
	Ybus ← rPassCnt,				c2;
	Ybus ← rPassCnt,				c3;

MDelA:	Ybus ← rPassCnt,				c1;
	Ybus ← rPassCnt, rTempA ← rTempA - 1, ZeroBr,	c2;
	Ybus ← rPassCnt, BRANCH[MDelA, $],		c3;

	Ybus ← rPassCnt,				c1;
	Ybus ← rPassCnt, rTempB ← rTempB - 1, ZeroBr,	c2;
	Ybus ← rPassCnt, BRANCH[MDel, $],		c3;

	Ybus ← rPassCnt,				c1;
	Ybus ← rPassCnt,				c2;
	rPassCnt ← rPassCnt + 1, GOTO[WritePass],	c3;

{---------------------------------------------------------------------------------------------}

WriteScopeLoop:  {No refreshing}

	MAR ← [rhMem, rMem + 0],			c1;
	MDR ← rWData, rMem ← rMem - 1,			c2;
	Noop, GOTO[WriteScopeLoop],			c3;


ReadWriteScopeLoop:  {No refreshing}

	MAR ← [rhMem, rMem + 0],			c1;
	MDR ← rWData, rMem ← rMem - 1,			c2;
	Noop,						c3;
	
	MAR ← [rhMem, rMem + 0],			c1;
	Noop,						c2;
	rRData ← MD, GOTO[ReadWriteScopeLoop],		c3;



{---------------------------------------------------------------------------------------------}