%
***  ***  ***  ***   <D0Diag>Rev-1>EDCym.mc    Revision 1.1    May 3, 1980   ***  ***  ***  *** 
**********************************************************************************************
*** EDCym.mc:  Cycler Masker Test microcode
*** Purpose:   To Test all of the Cycler Masker functions except FixVA which is tested by EDTNF.mc
*** Minimum Hardware:  Standard 4 CPU boards.
*** Approximate run time: 7 seconds.
*** Written by: Tom Horsley, December 30, 1977
*** Modified by: Bill Kennedy, February 22, 1978 
	To add control store parity.
*** Modified by: Bill Kennedy, March 2, 1978 
	To move code off of Page 0.
*** Modified by: Bill Kennedy, April 24, 1978  
	To add panel increments.
*** Modified by: Chuck Thacker, May 29, 1978 
	To improve readability.                    
	Note: if the FIELD test is run before EDCym, then CYM2  is useless, 
	      since the only difference between it and EDCym is that CYM2 does not 
	      use WFA and WFB to load the control store.  Accordingly, CYM2 should be 
	      eliminated from the set of tests.
*** Modified by: Mike Spaur, January 14, 1980  
	To standardize documentation and install looping capabilities.
*** Modified by: C. Thacker, May 3, 1980  
	To standardize assembly with cym.cm, modify for new d0lang.
***********************************************************************************************

***********************************************************************************************
* SubTest Descriptions:

*   SubTest0: Generate a random number that determines the Cycler Masker mode of
 	operation.
*   SubTest1: Read the control store micro instruction at location 1100 and alter
	the F1 and F2 fields so that they contain an 8 bit random number. Then
	calculate the new parity bit and insert the new instruction back into
	control store location 1100.
*   SubTest2: Calculate what the result of the Cycler Masker operation should be
	and save the answer in the "myResult" register.
*   SubTest3: Allow the cycler masker to execute the control store instruction
 	at location 1100 and save the result in the "Result" register.
*   SubTest4: Compare the result of the hardeware operation (SubTest3) to the 
	calculated result (SubTest2).
*   SubTest5: Examine the contents of the APC to see if it is correct. SubTest5 is only
	executed if the random F fields specify a dipatch type operation.

***********************************************************************************************
* BreakPoints:
*   ResultBad: The hardware result of the Cycler Masker operation (Result) did not equal the
	        calculated result (myResult).
*   APCBad: The contents of the APC (APCResult) did not equal the calculated result (myResult).
*   Passed-EDCym-Test: Passed all tests, and all passes.

***********************************************************************************************
* ShortLoop Logic Analizer Sync Points at Control Store address:
*   ResulBad: Control Store address  1036
*   APCBad:   Control Store address  1036



***********************************************************************************************
* Special Register Definitions:
*   ShortLoop: At any breakpoint the user has the option of changing the value of ShortLoop to 1,
	which will cause Subtest3 to loop endlessly. If ShortLoop is a zero then the program
	will proceed to the next test.
*   InnerLoopCounter: This register contains the number of passes through the mainloop.
	The mainloop is simply the sum of all of the sub tests. When InnerLoopCounter = 2**16
	all of the functions that are tested by EDCym have been tested exactly once.
*   PassCount: This register displays the number of completed passes of the entire EDCym test
	(2**16 iterations of the mainloop).  Also, the contents of this register is the
	octal equivalent of the Maintenance Pannel display.
*   MaxPass: This register can be set by the user. It determines how many repetitions
	of the entire EDCym test will be made.
*   XA: This test is driven by a sequence of 16-bit random numbers. In each iteration of the
	mainloop, the random number is generated. The random number generator has been 
	constructed so that it produces each number in the range of [0-64K] once and only 
	once before repeating any number. Thus it is guaranteed to have exhausted all possible 
	combinations of the fields derived from it when InnerLoopCounter reaches 2**16.
	XA[0:7] is used to define the Cycler Masker function through use of the F1 and F2
	fields of the microinstruction. These fields are built up from XA as follows:
		F1 = XA[0:3]
		F2 = XA[4:7]
*   Fnum: This register is used to Load the F1 & F2 fields. Fnum[0:7] = 0, and Fnum[10:17] = XA[0:7]
	This register is then used to decide which Cycler Masker function has been defined.
	There are six possible functions that are tested by the mainloop:
		Fnum = 0 to 206 	The Load Field function (LDFTest)
		Fnum = 207 to 300	The Dispatch function (DispatchTest)
		Fnum = 301 to 317	The LeftShift function (LSHTest)
		Fnum = 320 to 336	The Left Cycle function (LCYTest)
		Fnum = 337		The Left Hand Mask function (LHMaskTest)
		Fnum = 340		The Zero function (ZeroTest)
*   Operand: This is a random 16 bit word that is used to simulate the operation of the Cycler
	Masker using adds and carries.  Operand = XA + PassCount.

************************************************************************************************
%




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

TITLE[CyclerMaskerTester];

SET[MainPage, 3]; 		* Set page number for main part of program
SET[SubPage1, 1];	 	* Set page number for first sub-part of program
SET[SubPage2, 2]; 		* Set page number for first sub-part of program


********* R-registers *********
 

RV[PassCount,20,0]; 		* number of passes of the EDCym test executed  
RV[MaxPass,21,2]; 		* number of times EDCym is to repeat before breakpointing
RV[InnerLoopCounter,22]; 	* number of passes of the mainloop (subtests 0 to 5)

RV[ShortLoop,23,0]; 		* 0 = continue on next test, 1 = loop on Subtest 3
RV[SubTest,24]; 		* current location of test
RV[CheckAPC,25]; 		* flag indicating whether the APC result is to be checked

RV[CA,26]; 			* used in random number generation, A*XA + CA
RV[XA,27]; 			* random number generated via A*XA + CA

RV[Fnum,30];	 		* current cycle mask function being tested
RV[Operand,31]; 		* word to be cycle masked
RV[NBits,32]; 			* number of bits to be cycled or shifted
RV[LeftBit,33]; 		* first bit of field to be operated on
RV[bitNum,34]; 			* loop counter in simulated shifts

RV[CS0,35]; 			* temporary storage for first word of a control store location
RV[CS1,36]; 			* temporary storage for second word of a control store location
RV[CS2,37]; 			* temporary storage for third word of a control store location
RV[CSP,40]; 			* temporary register for control store parity calculations
RV[Address,41]; 		* location of CS instruction to be stuffed

RV[LDFTest,42]; 		* number of times LDF test has been executed
RV[DispatchTest,43]; 		* number of times Dispatch test has been executed
RV[LSHTest,44]; 		* number of times LSH test has been executed
RV[LCYTest,45]; 		* number of times LCY test has been executed
RV[LHMaskTest,46]; 		* number of times LHMask test has been executed
RV[ZeroTest,47]; 		* number of times Zero test has been executed

RV[myResult,50]; 		* result of simulated function
RV[Result,51]; 			* result of hardware function
RV[APCResult,52]; 		* contents of APC&APCTASK after test

RV[StuffTmp,53]; 		* used in the stuff operations
RV[tmp,54]; 			* temporary register
RV[tmp2,55]; 			* temporary register
RV[tmp3,56]; 			* temporary register

RV[Revision,57,1];		* current revision of EDCym
RV[Run-Time,60,7];		* the octal number of seconds it takes 
				* to complete two passes of the EDCym test





***************************************************************************************************
*** MAIN routine

ONPAGE[MainPage];

go:
start:	XA ← AND[0377, 123]C;
	XA ← (XA) OR (AND[177400, 123]C);

	CA ← AND[0377, 33031]C;
	CA ← (CA) OR (AND[177400, 33031]C);

	CLEARMPANEL;
	InnerLoopCounter ← 0C;
	PassCount ← 0C;
	LDFTest ← 0C;
	DispatchTest ← 0C;
	LSHTest ← 0C;
	LCYTest ← 0C;
	LHMaskTest ← 0C;
	ZeroTest ← 0C;
	Address ← AND[0377, 1100]C;
	Address ← (Address) OR (AND[177400, 1100]C);
	GOTO[mainLoop];

bigLoop: INCMPANEL;
	PassCount ← (PassCount) + 1;
	t ← (MaxPass);
	LU ← (PassCount) - (t);
	GOTO[Passed-EDCym-Test, ALU >= 0];
	GOTO[mainLoop];

Passed-EDCym-Test:	BREAKPOINT;
	PassCount ← 0C;

*** SUBTEST 0
mainLoop:
	SubTest ← 0C;
	CheckAPC ← 0C;

	InnerLoopCounter ← (InnerLoopCounter) + 1;
	GOTO[bigLoop, CARRY];


	t ← XA;				* This is the psuedo random number algorythm
	t ← (LSH[XA, 2]) + t;		* XA (new) = [ [ 4005 * XA(old) ] + CA ] modulo 2**16
	t ← (LSH[XA, 13]) + t;
	t ← (CA) + t;
	XA ← t;

*** SUBTEST 1
SetVars: SubTest ← 1C;
	t ← LDF[XA, 0, 10];
	Fnum ← t;

	t ← PassCount;
	t ← (XA) + t;
	Operand ← t;

	t ← (Address);			* use CS2 for a temporary register until end
	CS2 ← t;

GetCS:	t ← 0C;				* These lines of code read the control store data
	APCTASK&APC ← (CS2);		* at adress 1100 into the variables CS0,CS1 & CS2.
	READCS;
	t ← CSData;
	CS0 ← t;
	t ← 1C;
	APCTASK&APC ← (CS2);
	READCS;
	t ← CSData;
	CS1 ← t;
	t ← 3C;
	APCTASK&APC ← (CS2);
	READCS;
	t ← CSData;
	CS2 ← t;
	CS2 ← RSH[CS2, 14]; 

ChangeFields:
	t ← LDF[Fnum, 10, 4];		* Extract the F1 field from Fnum
	Tmp ← t;

	StuffTmp ← OR[LSHIFT[14, 4], SUB[4, 1]]C;
	CYCLECONTROL ← StuffTmp;
	t ← WFA[Tmp];			* These four lines of code change the F1 field in CS0
	CS0 ← WFB[(CS0) OR t];		* so that it is identical to Fnum[10:13]

	t ← LDF[Fnum, 14, 4];		* Extract the F2 field from Fnum
	Tmp ← t;

	StuffTmp ← OR[LSHIFT[2, 4], SUB[4, 1]]C;
	CYCLECONTROL ← StuffTmp;
	t ← WFA[Tmp];			* These four lines of code change the F2 field in CS1
	CS1 ← WFB[(CS1) OR t];		* so that is is identical to Fnum[14:17]

CalcPar: t ← CS0;			* Calculate the new control store parity
	CSP ← t; 			* put CS0 in the temp. reg.
	t ← CS1; 			* get CS1
	CSP ← t ← (CSP) XOR (t); 	* exclusive or the first two CS words
	t ← (LDF[CS2,14,4]) XOR (t); 	* now exclusive or the third CS word with the result
	CSP ← t ← (LDF[CSP,0,10]) XOR (t); * now start halfing process to get parity
	CSP ← t ← (LDF[CSP,10,4]) XOR (t);
	CSP ← t ← (LDF[CSP,14,2]) XOR (t);
	CSP ← t ← (LDF[CSP,16,1]) XNOR (t);  * Do last part and complement it
	t ← (LDF[CSP,17,1]); 		* put parity bit in the t-register
	CS1 ← (CS1) XOR (t); 		* exclusive or the parity bit into bit 31 of CS (15 of CS1)

WriteCS: t ← (CS2);			* Put the new instruction back into the control Store
	LU ← (CS0);			* writeCS -- write control store location
	APCTASK&APC ← (Address);
	WriteCS0&2;
	LU ← (CS1);
	APCTASK&APC ← (Address);
	WriteCS1;

	LOADPAGE[SubPage1];		* Page (change to page SubPage1)
	GOTOP[.+1];
	ONPAGE[SubPage1];

*** SUBTEST2
SubTest2:
	SubTest ← 2C;
	t ← 207C; 			* last LDF + 1
	LU ← (Fnum) - (t);
	GOTO[FnumGT206, ALU >= 0];

	LU ← (Fnum) - (20C);		* LDF Tests
	GOTO[FnumGT017, ALU >= 0];

	NBits ← 1C;			* 20 1-bit fields
	t ← Fnum;
	LeftBit ← t;
	GOTO[myLDF];

FnumGT017:
	LU ← (Fnum) - (37C);
	GOTO[FnumGT036, ALU >= 0];

	NBits ← 2C;			* 17 2-bit fields
	t ← (Fnum) - (20C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT036:
	LU ← (Fnum) - (55C);
	GOTO[FnumGT054, ALU >= 0];

	NBits ← 3C;			* 16 3-bit fields
	t ← (Fnum) - (37C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT054:
	LU ← (Fnum) - (72C);
	GOTO[FnumGT071, ALU >= 0];

	NBits ← 4C;			* 15 4-bit fields
	t ← (Fnum) - (55C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT071:
	LU ← (Fnum) - (106C);
	GOTO[FnumGT105, ALU >= 0];

	NBits ← 5C;			* 14 5-bit fields
	t ← (Fnum) - (72C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT105:
	LU ← (Fnum) - (121C);
	GOTO[FnumGT120, ALU >= 0];

	NBits ← 6C;			* 13 6-bit fields
	t ← (Fnum) - (106C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT120:
	LU ← (Fnum) - (133C);
	GOTO[FnumGT132, ALU >= 0];

	NBits ← 7C;			* 12 7-bit fields
	t ← (Fnum) - (121C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT132:
	LU ← (Fnum) - (144C);
	GOTO[FnumGT143, ALU >= 0];

	NBits ← 10C;			* 11 10-bit fields
	t ← (Fnum) - (133C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT143:
	LU ← (Fnum) - (154C);
	GOTO[FnumGT153, ALU >= 0];

	NBits ← 11C;			* 10 11-bit fields
	t ← (Fnum) - (144C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT153:
	LU ← (Fnum) - (163C);
	GOTO[FnumGT162, ALU >= 0];

	NBits ← 12C;			* 7 12-bit fields
	t ← (Fnum) - (154C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT162:
	LU ← (Fnum) - (171C);
	GOTO[FnumGT170, ALU >= 0];

	NBits ← 13C;			* 6 13-bit fields
	t ← (Fnum) - (163C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT170:
	LU ← (Fnum) - (176C);
	GOTO[FnumGT175, ALU >= 0];

	NBits ← 14C;			* 5 14-bit fields
	t ← (Fnum) - (171C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT175:
	t ← 202C; 			* done this way due to sign extend on arithmetic
	LU ← (Fnum) - (t);
	GOTO[FnumGT201, ALU >= 0];

	NBits ← 15C;			* 4 15-bit fields
	t ← (Fnum) - (176C);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT201:
	t ← 205C; 			* done this way due to sign extend on arithmetic
	LU ← (Fnum) - (t);
	GOTO[FnumGT204, ALU >= 0];

	NBits ← 16C;			* 3 16-bit fields
	t ← 202C;
	t ← (Fnum) - (t);
	LeftBit ← t;
	GOTO[myLDF];

FnumGT204:
	NBits ← 17C;			* 2 17-bit fields
	t ← 205C;
	t ← (Fnum) - (t);
	LeftBit ← t;

myLDF:	t ← (Operand);
	tmp3 ← t;

	t ← (1C);
	bitNum ← t;

LDFupperLoop:
 	t ← (LeftBit);
	LU ← (bitNum) - (t) - 1;
	GOTO[LDFReset, ALU >= 0];

	t ← (tmp3);
	tmp3 ← (tmp3) + t;

	bitNum ← (bitNum) + 1;
	GOTO[LDFupperLoop];

LDFReset:
	t ← (NBits);
	tmp2 ← t;
	myResult ← 0C;
	t ← (tmp3);
	tmp ← t;
	t ← (1C);
	bitNum ← t;

LDFlowLoop:
 	t ← (tmp2);
	LU ← (bitNum) - (t) - 1;
	GOTO[DoneWithFakeLDF, ALU >= 0];

	t ← (myResult);
	myResult ← (myResult) + t;
	t ← (tmp);
	tmp ← (tmp) + t;
	GOTO[LDFincBitNum, NOCARRY];
	myResult ← (myResult) + 1;

LDFincBitNum:
	bitNum ← (bitNum) + 1;
	GOTO[LDFlowLoop];

DoneWithFakeLDF:
	LDFTest ← (LDFTest) + 1;
	LOADPAGE[SubPage2];
	GOTOP[hardwareDoIt];

FnumGT206:
	LOADPAGE[SubPage2];		* Page (change to page SubPage2)
	GOTOP[.+1];
	ONPAGE[SubPage2];

	t ← 301C; 			* last DISPATCH + 1
	LU ← (Fnum) - (t);
	GOTO[FnumGT300, ALU >= 0];

	t ← 227C;			* Dispatch Tests
	LU ← (Fnum) - (t);
	GOTO[FnumGT226, ALU >= 0];

	NBits ← 1C;			* 20 1-bit fields
	t ← 207C;
	t ← (Fnum) - (t);
	LeftBit ← t;
	GOTO[myDispatch];

FnumGT226:
	t ← 246C;
	LU ← (Fnum) - (t);
	GOTO[FnumGT245, ALU >= 0];

	NBits ← 2C;			* 17 2-bit fields
	t ← 227C;
	t ← (Fnum) - (t);
	LeftBit ← t;
	GOTO[myDispatch];

FnumGT245:
	t ← 264C;
	LU ← (Fnum) - (t);
	GOTO[FnumGT263, ALU >= 0];

	NBits ← 3C;			* 16 3-bit fields
	t ← 246C;
	t ← (Fnum) - (t);
	LeftBit ← t;
	GOTO[myDispatch];

FnumGT263:
	NBits ← 4C;			* 15 4-bit fields
	t ← 264C;
	t ← (Fnum) - (t);
	LeftBit ← t;

myDispatch:
	t ← (Operand);
	tmp3 ← t;

	t ← (1C);
	bitNum ← t;

DispUpperLoop:
	t ← (LeftBit);
	LU ← (bitNum) - (t) - 1;
	GOTO[DispReset, ALU >= 0];

	t ← (tmp3);
	tmp3 ← (tmp3) + t;

	bitNum ← (bitNum) + 1;
	GOTO[DispUpperLoop];

DispReset:
	t ← (NBits);
	tmp2 ← t;
	myResult ← 0C;
	t ← (tmp3);
	tmp ← t;
	t ← (1C);
	bitNum ← t;

DispLowLoop:
 	t ← (tmp2);
	LU ← (bitNum) - (t) - 1;
	GOTO[DoneWithFakeDisp, ALU >= 0];

	t ← (myResult);
	myResult ← (myResult) + t;
	t ← (tmp);
	tmp ← (tmp) + t;
	GOTO[DispIncBitNum, NOCARRY];
	myResult ← (myResult) + 1;

DispIncBitNum:
	bitNum ← (bitNum) + 1;
	GOTO[DispLowLoop];

DoneWithFakeDisp:
	CheckAPC ← 1C;
	DispatchTest ← (DispatchTest) + 1;
	GOTO[hardwareDoIt];

FnumGT300:
	t ← 320C; 			* last LSH + 1
	LU ← (Fnum) - (t);
	GOTO[FnumGT317, ALU >= 0];

	t ← 300C;			* LSH Tests
	t ← (Fnum) - (t);
	NBits ← t;

	t ← (Operand);
	myResult ← t;

	t ← (1C);
	bitNum ← t;

LSHloop: t ← (NBits);
	LU ← (bitNum) - (t) - 1;
	GOTO[DoneWithFakeLSH, ALU >= 0];

	t ← (myResult);
	myResult ← (myResult) + t;

	bitNum ← (bitNum) + 1;
	GOTO[LSHloop];

DoneWithFakeLSH:
	LSHTest ← (LSHTest) + 1;
	GOTO[hardwareDoIt];

FnumGT317:
	t ← 337C; 			* last LCY + 1
	LU ← (Fnum) - (t);
	GOTO[FnumGT336, ALU >= 0];

	t ← 317C;			* LCY Tests
	t ← (Fnum) - (t);
	NBits ← t;

	t ← (Operand);
	myResult ← t;

	t ← (1C);
	bitNum ← t;

LCYloop: t ← (NBits);
	LU ← (bitNum) - (t) - 1;
	GOTO[DoneWithFakeLCY, ALU >= 0];

	t ← (myResult);
	myResult ← (myResult) + t;
	GOTO[LCYincBitNum, NOCARRY];
	myResult ← (myResult) + 1;

LCYincBitNum:
	bitNum ← (bitNum) + 1;
	GOTO[LCYloop];

DoneWithFakeLCY:
	LCYTest ← (LCYTest) + 1;
	GOTO[hardwareDoIt];

FnumGT336:
	t ← 337C; 			* LHMASK function
	LU ← (Fnum) - (t);
	GOTO[FnumNeq337, ALU # 0];

FnumEq337:
	t ← (operand) AND (177400C);	* LHMASK Test
	myResult ← t;
	LHMaskTest ← (LHMaskTest) + 1;
	GOTO[hardwareDoIt];

FnumNeq337:
	t ← 340C; 			* ZERO function
	LU ← (Fnum) - (t);
	GOTO[FnumNotUseful, ALU # 0];

FnumEq340:
	myResult ← 0C;			* ZERO Test
	ZeroTest ← (ZeroTest) + 1;
	GOTO[hardwareDoIt];

FnumNotUseful:				* untested functions 341 - 377
	LOADPAGE[MainPage];
	GOTOP[mainLoop];

H1:	NOP;				* resolves a branching conflict
H2:	NOP;				* resolves a branching conflict

*** SUBTEST 3
hardwareDoIt:

	TASK;

	SubTest ← 3C;
	t ← (Operand);
	Result ← t;

	Result ← ZERO[Result], AT[1100]; * Does not do the ZERO function because F1
					* and F2 fields of location 1100 have been altered

	t ← APC&APCTASK; 		* save this for dispatch test
	APCResult ← t;

	ShortLoop ← ShortLoop, GOTO[.+2,R EVEN]; * Test for ShortLoop option
	GOTO[hardwareDoIt];		* ShortLoop selected

	NOP;				* resolves a branching conflict

*** SUBTEST 4
SubTest4:
	SubTest ← 4C;
	t ← Result;
	LU ← (myResult) - (t);
	GOTO[SubTest5, ALU = 0];

ResultBad: BREAKPOINT;

	ShortLoop ← ShortLoop, GOTO[.+2,R EVEN]; * Test for ShortLoop option
	GOTO[H1];			* ShortLoop selected

	NOP;				* resolves a branching conflict

*** SUBTEST 5
SubTest5:
	SubTest ← 5C;
	LU ← (CheckAPC);
	GOTO[AllDone, ALU = 0];
	t ← APCResult;
	LU ← (myResult) - (t);
	GOTO[APCOK, ALU = 0];

APCBad:	BREAKPOINT;
	ShortLoop ← ShortLoop, GOTO[.+2,R EVEN]; * Test for ShortLoop option
	GOTO[H2];			* ShortLoop selected

	NOP;				* resolves a branching conflict
APCOK:	NOP; 				* resolves a branching conflict

AllDone: LOADPAGE[MainPage];
	GOTOP[mainLoop];

	END;