%
*** Revision 1.1 May 3, 1980 ***
****************************************************************************************
***   EDField.mc : microcode to test the Mesa field selection operations RF, WFA, WFB
***   Purpose  : This test simulates the RF, WFA, and WFB operations without
		using the cycler-masker and then compares the results with
		the actual executions of the corresponding operations.
***   Hardware Configuration : Standard 4 CPU boards.
***   IMPORTANT NOTE :  ON VIRGIN SYSTEMS RUN EDFIELD BEFORE EDCYM.
		This EDField test checks hardware that must work properly
		for EDCym to be useful.
***   Approximate run time : twenty seconds.
***   Written by  :  Tom Horsley,	Dec. 13, 1977
***   Modified by :  Bill Kennedy,	March 10, 1978
		Took code off of Page 0.
***   Modified by :  Bill Kennedy,	April 24, 1978
		Now uses Maintenance Panel.
***   Modified by :  C. Thacker,	(date unknown)
		Improved readability.
***   Modified by :  C. Thacker,	August 22, 1978
		Made XB = -1 always.
***   Rewritten by : J. Kellman,	March 6, 1980
		Eliminated all cycler-masker functions from both the
		simulated field selection operations and random number
		generators, as well as standardizing the program format.
***   Modified by :  C. Thacker,	
		Use cym.cm to assemble, converted for new d0lang.
****************************************************************************************   



****************************************************************************************
* SubTest Description:
*  SubTest 0: (not really a test) generates and decodes a Mesa Field descriptor.
*  SubTest 1: simulates and then executes the RF operation (Mesa Read-Field)
		and compares the results.
*  SubTest 2: simulates and then executes the WFA operation (Mesa Write-Field A)
		and compares the results.
*  SubTest 3: simulates and then executes the WFB operation (Mesa Write-Field B)
		and compares the results.

****************************************************************************************
* Subroutine Description:
*  LeftCycle:  uses ALU additions to simulate the LCycle function
		without using the cycler-masker.
*  LeftShift:  uses ALU additions to simulate the LShift function
		without using the cycler-masker.

****************************************************************************************
* Breakpoints:
*  RFBAD:   actual RF result failed to agree with simulated RF result
*  WFABAD:  actual WFA result failed to agree with simulated WFA result
*  WFBBAD:  actual WFB result failed to agree with simulated WFB result
*  Passed-EDField-Test:  the system passed thru all the passes of EDField

****************************************************************************************
* Breakpoint Logic Analyzer Sync Points:
*  RFBAD:		Control Store address 457
*  WFABAD:		Control Store address 451
*  WFBBAD:		Control Store address 441
*  Passed-EDField-Test:	Control Store address 401

****************************************************************************************

****************************************************************************************
* Special Register Definitions:

*   LoopWithin: At any breakpoint the user may change the value of LoopWithin.
		Setting LoopWithin to the nonzero value N will cause EDField to loop
		endlessly within the subtest N (when it gets to this subtest).
		If LoopWithin is zero (the default) then the program goes straight 
		through all the tests as normal.

*   RandFlag: At any breakpoint the user may change the value of RandFlag
		to 1, which will cause CurrentPattern to take on random values.
 		If RandFlag is zero (the default) then CurrentPattern will be set to
		a 16-bit word of all ones during each execution of subtest 0.

*   XA and XB: The two random numbers held in these registers XA and XB are used to
		choose field descriptor (FDescr) and CurrentPattern values
		as follows:		FDescr  ←  XA[0:7]
				 CurrentPattern ←  XB  (only if RandFlag = 1)

*   InnerLoopCounter: This register contains the number of passes through the mainloop.
		The mainloop is simply the set of all of the subtests. When
		InnerLoopCounter = (2**16) - 1, all of the possibilities that are tested
		by EDField have been tested exactly once.

*   PassCount: This register displays the number of the current pass of the entire
		EDField test (2**16 iterations of the mainloop). The maintenance
		panel shows the number of the currently running pass.

*   MaxPass: This register determines how many times the entire EDField test will repeat.

****************************************************************************************
%

****************************************************************************************
* INITIALIZATION:

TITLE[MesaFieldTest];

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

RV[Revision,1,1];	* revision number is 1 for this program
RV[Run-Time,2,24];	* run time for this test is twenty seconds
RV[PassCount,3];	* pass count for this program
RV[MaxPass,4,2];	* maximum number of passes for this run
RV[SubTest,5];		* current location of test
RV[InnerLoopCounter,6]; * inner loop counter

RV[LoopWithin,10,0];	* set to N to loop on subtest n
RV[RandFlag,11,0];	* 0 => CurrentPattern always 177777, 1 => random pattern

RV[CurrentPattern,12];  * holds the argument for the RF, WFA, and WFB operations
RV[CA,13];		* used in random number generation, A*XA + CA
RV[XA,14];		* random number generated via A*XA + CA
RV[CB,15];		* used in random number generation, A*XB + CB
RV[XB,16];		* random number generated via A*XB + CB
RV[FDescr,17];		* Mesa field descriptor
RV[StartBit,20];	* start field of mesa field descriptor (first 4 bits)
RV[EndBit,21];		* last bit of mesa field
RV[Length,22];		* actual length of mesa field from descriptor (last 4 bits plus 1)
RV[ShiftIndex,23];	* index register in LeftCycle and LeftShift
RV[ShiftSize,24];	* number of bits to be shifted in simulated shift (or cycle)
RV[ShiftValue,25];	* holds word to be shifted in simulated shift (or cycle)
RV[Mask,26];		* the mask used in simulating the RF, WFA, and WFB operations
RV[SimResult,27];	* result of simulated operations
RV[Result,30];		* holds the hardware result of current operation


****************************************************************************************
*** MAIN routine:

	SET[MainPage,1];	* set label for Main Program page
	ONPAGE[MainPage];

go:
start:
* Initialize random generator registers: XA ← 123, CA ← 33031
	XA ← AND[0377, 123]C;
	XA ← (XA) OR (AND[177400, 123]C);

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

* Initialize random generator registers: XB ← 456, CB ← 33035
	XB ← AND[0377, 456]C;
	XB ← (XB) OR (AND[177400, 456]C);

	CB ← AND[0377, 33035]C;
	CB ← (CB) OR (AND[177400, 33035]C);

	CLEARMPANEL;
	InnerLoopCounter ← 0C;	* Initialize inner loop counter
	PassCount ← 0C;		* Initialize outer loop counter

bigLoop: t ← PassCount ← (PassCount) + 1;
	LU ← (MaxPass) - (t);
	GOTO [.+2, ALU >= 0];

Passed-EDField-Test: BREAKPOINT, goto[go];

	INCMPANEL;


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

	LU ← (LoopWithin);
	GOTO [ExtractFDescr, ALU # 0];	* Do next pattern value?

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

	* Random (4005*XA + CA mod 2**16)
	t ← XA;
	ShiftValue ← t;
	ShiftSize ← 2C;		* left shift old XA by 2 bits
	CALL [LeftShift];
	t ← ShiftValue;
	XA ← (XA) + t;		* add shifted value to XA
	ShiftSize ← 11C;	* left shift original old XA by a total of 13C bits
	CALL [LeftShift];
	t ← ShiftValue;
	t ← (XA) + t;		* add shifted value to subtotal
	t ← (CA) + t;		* add CA
	XA ← t;			* result is new XA

	* Random (4005*XB + CB mod 2**16)
	t ← XB;
	ShiftValue ← t;
	ShiftSize ← 2C;		* left shift old XB by 2 bits
	CALL [LeftShift];
	t ← ShiftValue;
	XB ← (XB) + t;		* add shifted value to XB
	ShiftSize ← 11C;	* left shift original old XB by a total of 13C bits
	CALL [LeftShift];
	t ← ShiftValue;
	t ← (XB) + t;		* add shifted value to subtotal
	t ← (CB) + t;		* add CB
	XB ← t;			* result is new XB

	LU ← RandFlag;
	DBLGOTO [PatternAllOnes, PatternRandom, ALU = 0];
PatternAllOnes:  CurrentPattern ← (ZERO) - 1, goto[ExtractFDescr];
PatternRandom:  CurrentPattern ← t, goto[ExtractFDescr];

ExtractFDescr:  t ← XA;		* XA will yield the field descriptor for this test
	ShiftValue ← t;		* we extract all our descriptor values by 
				*     ALU-simulated cycling and masking
				*     (to avoid using the cycler-masker)

	ShiftSize ← 10C;	* simulate an eight-bit left cycle
	CALL [LeftCycle];

	t ← ShiftValue;
	FDescr ← t;
	FDescr ← (FDescr) and (377C); * mask to get entire field descriptor

DecodeFDescr:  t ← FDescr;	* now decode this FDescr
	ShiftValue ← t;

	ShiftSize ← 14C;	* simulate a twelve-bit left cycle
	CALL [LeftCycle];

	t ← ShiftValue;
	StartBit ← t;
	StartBit ← (StartBit) and (17C); * mask to get field start bit index

	ShiftSize ← 4C;		* simulate a further four-bit left cycle
	CALL [LeftCycle];		

	t ← ShiftValue;
	Length ← t;
	Length ← (Length) and (17C); * mask to get length field
	Length ← (Length) + 1;	* adjust length value to actual length

	t ← (Length) - 1;
	t ← (StartBit) + t;
	EndBit ← t;		* proper end bit index calculated

	LU ← (EndBit) - (20C);	* check if end bit makes sense
	GOTO [EndBitPastEnd, ALU >= 0];
	GOTO [RFTest];
EndBitPastEnd:  GOTO [mainLoop];


*** SUBTEST 1 ***
RFTest:	SubTest ← 1C;		 * first simulate RF

	ShiftValue ← (ZERO) - 1; * form Mask

	t ← Length;
	ShiftSize ← t;
	CALL [LeftShift];

	t ← (ShiftValue) xnor (0C);
	Mask ← t;

	t ← CurrentPattern;	 * left cycle current pattern by (Startbit + Length) bits
	ShiftValue ← t;
	t ← Length;
	t ← (StartBit) + t;
	ShiftSize ← t;
	CALL [LeftCycle];

	t ← Mask;		 * apply Mask to left-cycled CurrentPattern
	t ← (ShiftValue) and t;
	SimResult ← t;

	CYCLECONTROL ← FDescr;	 * now do real RF
	t ← RF[CurrentPattern];
	Result ← t;

	lu ← (LoopWithin) - (1C); * loop within this test?
	GOTO [.+2, ALU # 0];
	GOTO [RFTest];

	LU ← (SimResult) - (t);	 * compare RF results
	GOTO[WFATest, ALU = 0];
RFBAD:	BREAKPOINT, goto[RFTest];


*** SUBTEST 2 ***
WFATest:  SubTest ← 2C;		 * first simulate WFA

	ShiftValue ← (ZERO) - 1; * form Mask

	t ← Length;
	ShiftSize ← t;
	CALL [LeftShift];

	ShiftValue ← (ShiftValue) xnor (0C);

	t ← (StartBit) - (20C);
	t ← (Length) + t;
	ShiftSize ← (ZERO) - t;
	CALL [LeftShift];

	t ← ShiftValue;
	Mask ← t;

	t ← CurrentPattern;	 * left cycle CurrentPattern by 20C - (StartBit + Length) bits
	ShiftValue ← t;
	CALL [LeftCycle];

	t ← Mask;		 * apply Mask to left-cycled CurrentPattern
	t ← (ShiftValue) and t;
	SimResult ← t;

	CYCLECONTROL ← FDescr;	 * now do real WFA
	t ← WFA[CurrentPattern];
	Result ← t;

	lu ← (LoopWithin) - (2C); * loop within this test?
	GOTO [.+2, ALU # 0];
	GOTO [WFATest];

	LU ← (SimResult) - (t);	 * compare WFA results
	GOTO[WFBTest, ALU = 0];
WFABAD:  BREAKPOINT,goto[WFATest];


*** SUBTEST 3 ***
WFBTest:  SubTest ← 3C;			* first simulate WFB

	ShiftValue ← (ZERO) - 1;	* form Mask

	t ← Length;
	ShiftSize ← t;
	CALL [LeftShift];

	ShiftValue ← (ShiftValue) xnor (0C);

	t ← (StartBit) - (20C);
	t ← (Length) + t;
	ShiftSize ← (ZERO) - t;
	CALL [LeftShift];

	t ← ShiftValue;
	Mask ← t;

	t ← CurrentPattern;		* apply inverse Mask to CurrentPattern
	SimResult ← t;

	t ← Mask;
	SimResult ← (SimResult) andnot t;

	t ← Mask;			* insert masked CurrentPattern into XB's pattern
	t ← (XB) and t;
	SimResult ← (SimResult) or t;

	CYCLECONTROL ← FDescr;		* now do real WFB
	t ← (WFB[CurrentPattern]) OR t;	* register t still holds  XB and Mask
	Result ← t;

	lu ← (LoopWithin) - (3C);	* loop within this test?
	GOTO [.+2, ALU # 0];
	GOTO [WFBtest];

	LU ← (SimResult) - (t);		* compare WFB results
	GOTO[.+2, ALU = 0];
WFBBAD:  BREAKPOINT,goto[wfbtest];

	GOTO[mainLoop];



*********   SUBROUTINE:  LeftCycle   *********
*
*	(to simulate LCycle without using the cycler-masker)
*	This subroutine left cycles  ShiftValue  by  ShiftSize  bits.

LeftCycle: ShiftIndex ← 1C;
CycleLoop: t ← (ShiftSize);
	LU ← (ShiftIndex) - (t) -1;
	GOTO[CycleEnd, ALU >= 0];	* done with cycles yet?

	t ← ShiftValue;			* ShiftValue holds the value to be left cycled
	ShiftValue ← (ShiftValue) + t;  * simulate a left shift by adding to self

	GOTO[.+2, NOCARRY];		* bit shifted out left comes back into right side
	ShiftValue ← (ShiftValue) + 1;

	ShiftIndex ← (ShiftIndex) + 1;
	GOTO[CycleLoop];

CycleEnd: RETURN;


*********   SUBROUTINE:  LeftShift   *********
*
*	(to simulate LShift without using the cycler-masker)
*	This subroutine left shifts  ShiftValue  by  ShiftSize  bits.

LeftShift: ShiftIndex ← 1C;
ShiftLoop: t ← (ShiftSize);
	LU ← (ShiftIndex) - (t) - 1;
	GOTO[ShiftEnd, ALU >= 0];	* done with shifts yet?

	t ← ShiftValue;			* ShiftValue holds the value to be left cycled
	ShiftValue ← (ShiftValue) + t;  * simulate a left shift by adding to self

	ShiftIndex ← (ShiftIndex) + 1;
	GOTO[ShiftLoop];

ShiftEnd: RETURN;



	END;