//**************************************************************************************
//ALU3.TST
//By F. Itami and M. Thomson  							October 6, l978
//Sub Test Program for D0 ALU Module
//**************************************************************************************
get "alu.d"

//Edge pin signal busses used by ALU module:

//{ALUA: ALUA.00,  ALUA.01,ALUA.02,ALUA.03,  ALUA.04,ALUA.05,ALUA.06,  ALUA.07,ALUA.08,ALUA.09,  ALUA.10,ALUA.11,ALUA.12,  ALUA.13,ALUA.14,ALUA.15}

//{aluf: ALUF.0,  ALUF.1,ALUF.2,ALUF.3}

//{clkbus: LT,LR,  Abort',LoadMIR,Cycle0Feed'}

//{CTask: CTask.0,  CTask.1,CTask.2,CTask.3}

//{F1F2: F1.0,F1.1,  F1.2,F1.3,F2.0,  F2.1,F2.2,F2.3}

//{H2: H2.08,H2.09,  H2.10,H2.11,H2.12,  H2.13,H2.14,H2.15}

//{MASK: MASK.00,  MASK.01,MASK.02,MASK.03,  MASK.04,MASK.05,MASK.06,  MASK.07,MASK.08,MASK.09,  MASK.10,MASK.11,MASK.12,  MASK.13,MASK.14,MASK.15}

//{MC1SA: BSEL.0,BSEL.1,  F1.0,F1.1,F1.2,  F1.3,LR,LT}

//{mcbus: MC1WriteR,  MC2AllowWrite,MC1NeedsR,MC2WillGetR}

//{mirbus: MemInst/d,MemInst/d',  RMOD/d,RMOD/d',RSEL.0/d',  RSEL.1/d',RSEL.2/d,RSEL.3/d,  RSEL.4/d,RSEL4and5/d,RSEL.5/d}

//{rbus: R.00,  R.01,R.02,R.03,  R.04,R.05,R.06,  R.07,R.08,R.09,  R.10,R.11,R.12,  R.13,R.14,R.15}

//{TA: TA.0,  TA.1,TA.2,TA.3}

//**************************************************************************************
//TEST 9: Test the ADD function of the ALU using operands that should completely check
//        each ALU chip with all combinations of ALUA, ALUB, and input carry.
//        Check END CARRY, OVERFLOW and the UseCoutAsCin logic (page 10)

let Test9() be
[
	SpeakTest(9) //set initial conditions (see notes at end of ALU.TST)

//PART 1: Test the ALU using "R+T" and "R+T+1" with all possible
//        data input configurations to each hex digit

	//SpeakTest sets up conditions to enable clkResult" during Cycle 0 (page 15)
	//also, Restore'=1 for SavALUCyOut←ALUCyOut when clkResult' is active (page 10)

	//Set up conditions for J-TestResult'←SavALUCyOut' (page 10)
	//(BranchShift'=1 from SpeakTest initialization)
	{JA.7}=1; //for mux address inputs = 001

	{BSEL.0}=1; //EnableT (for H2 ← T file)

	//The operands (hex notation) generated in the loops to follow are:
	//       ALUA input       ALUB input
	//i=0 => (vr = j,0,j,0) + (vt = k,0,k,0)
	//i=1 => (vr = 0,j,0,j) + (vt = 0,k,0,k)
	//i=2 => (vr = j,8,j,8) + (vt = k,8,k,8)     (Carry=1 into each (j+k))
	//i=3 => (vr = 0,j,8,j) + (vt = 0,k,8,k) + 1 (Carry=1 into each (j+k))

	for i = 0 to 3 do
	[
		//Set up ALU control for "R+T" if i<3 and "R+T+1" if i=3
		let a = (-(i<<w.b14 & i<<w.b15))&3 //3 if i=3, else 0

		//Set up scaling factors
		let b = (i lshift 2) & 4 //4 if i is odd,  else 0 (for scale d right)
		let c = (not b) & 4      //4 if i is even, else 0 (for scale f,g,y left)

		//Set up carry generation constants
		let d = #4010 & (-i<<w.b14) //hex 0808 if i>1, else 0
		let e = d rshift b // hex 0808 if i=2, hex 0080 if i=3, else 0

		for j = 0 to 15 do
		[
			let f  = (j lshift 8) & j //hex 0,j,0,j
			let vr = (f lshift c) % e //for ALUA input

			//Calculate partial sum (to be completed in k loop (see y))
			let x = f + (d rshift 3) //hex (0,j,0,j) + (0,1,0,1 if i>1, else 0)

			for k = 0 to 15 do
			[
				let g  = (k lshift 8) & k //hex 0,k,0,k
				let vt = (g lshift c) % e //for ALUA input

				{Cycle0Feed'}=0
				{aluf}=1; //for ALUOUT=ALUA
				{rbus}=vt
				EClock() //H1←(rbus=vt), ALUF()←"R"
				{rbus}=###
				EClock() //H3P←(ALUOUT=ALUA=H1=vt)

				{Cycle0Feed'}=1; //for rbus←H3P and TWrite=1
				RClock() //T←(H3P=vt)

				{Cycle0Feed'}=0
				{aluf} = #11 xor a; //#11 if i<3, #12 if i=3
				{rbus}=vr
				EClock() //H1←(rbus=vr), H2←(T=vt), ALUF() ← ("R+T" or "R+T+1")
				{rbus}=###

				EClock() //H3P←(ALUOUT = vr + vt +(1 if i=3))
				{Cycle0Feed'}=1; //for rbus←H3P (sum)

				//Calculate unscaled sum (right-justified)
				let y = x + g //hex ((0,j,0,j)+(0,1,0,1 if i>1, else 0))+(0,k,0,k)

				let sum = y lshift c //y lshift 4 if i is even, else y
				let EndCarry = y<<w.b3 & (not i) //0 when i is odd
				let overflow = (y<<w.b3 xor y<<w.b4) & (not i) //0 when i is odd
 
				let drive = (j lshift 6) % k //for "drive" argument in WCompares 
				//NOTE: j is left shifted two octal positions,
				//so that the hex digits of the operands are readily
				//identifiable (i.e. jj,kk)
				//Example: 714 means hex 7c or 0111 1100

				WCompare({rbus},sum,9000+i,drive) //see TABLE below
				WCompare((not {J-TestResult'})&1,EndCarry,9010+i,drive)
				WCompare((not {Overflow'})&1,overflow,9020+i,drive)
			]
		]
	]

	//TABLE of ALUA and ALUB operands (hex notation):
	//       ALUA input       ALUB input
	//i=0 => (vr = j,0,j,0) + (vt = k,0,k,0)
	//i=1 => (vr = 0,j,0,j) + (vt = 0,k,0,k)
	//i=2 => (vr = j,8,j,8) + (vt = k,8,k,8)     (Carry=1 into each (j+k))
	//i=3 => (vr = 0,j,8,j) + (vt = 0,k,8,k) + 1 (Carry=1 into each (j+k))


//PART 2: Test the arithmetic overflow and UseCoutAsCin logic (pages 9 and 10)

	//{t9drive: ALUF.1,R.00,  R.01,F1.0,F1.1}

	let t9sb = table [ 1;1;1;1;1;0;1;1; 1;1;0;0;1;1;0;1; 1;1;1;1;1;1;0;1; 0;0;1;1;1;0;1;1 ]

	//Initialize:
	{Cycle0Feed'}=0
	{rbus}=0
	{BSEL.0}=0
	{BSEL.1}=1; //up-align F1F2 for H2[0:1]←F1[0:1]
	{aluf}=9; //for "R+B" (modified later by i[11])

	for i = 0 to 31 do
	[
		{t9drive}=i
		EClock() //ALUF()←("R+B" if i[11]=0 or "R-B-1" (i.e. R+T') if i[11]=1)
		         //H1[0:1]←R[0:1]←i[12:13], H2[0:1]←F1[0:1]←i[14:15]
		EClock() //clkResult
		WCompare({Overflow'},t9sb!i,9200,i)
	]

	{rbus}=###
	{MASK}=#177777; //for ALUA=0
	{F1F2}=0
	{aluf}=12; //for "R-B" (0+#177777+1) for END CARRY =1
	EClock() //H2←0's, ALUF()←"R-B"

	{UseCoutAsCin'}=0
	{aluf}=9; //for "R+B" + saved END CARRY
	EClock() //clkResult (SavALUCyOut←1), ALUF()←"R+B"
	EClock() //clkResult (SavALUCyOut←0), H3P←(ALUOUT=0+0 +1)

	{Cycle0Feed'}=1; //display H3P
	WCompare({rbus},1,9300)

	ClockCycle0() //H3P←(ALUOUT=0+0 +0)
	WCompare({rbus},0,9301)
]

//**************************************************************************************
//Test 10: Test the R file write-read functions (pages 1-4,6,11,13-15,18,20)

let Test10() be
[
	SpeakTest(10) //set initial conditions (see notes at end of ALU.TST)

	//{RPIn: RPByte0In,RPByte1In}
	//{RPOut: RPByte0,RPByte1}

	{ALUF.2}=1; //for prom f2 address = xxxx x1x0 and output = 1111 (page 16)
	            //to keep MC1XferWord=1 when ClockAd. (for Suspend←(MC1NeedsR=1))
	{LoadAd'}=0; //all clocks (except RClock) will be ClockAd's for loading MC1Ad
	{Stkp←ALUA'}=1; //keep Stkp=0 during ClockMIR (all other clocks are Cycle0's)
	{MemInst/d}=1; //enable b13 prom (page 11) for MC1Ad←Stkp+0 when SRC/DEST=0 (i.e. when j=0)
	{MC1NeedsR}=1; //select MC1Ad for R address (i.e. RA←MC1Ad)
	ClockMIR() //MemInst←1, Suspend←1, RSA,B←4,6, MC1Ad←({MC1SA}=1 (from SpeakTest))

//Preliminary data path test (R address is constant: RA=MC1Ad=1)

	for i = 0 to 15 do
	[
		{MC1WriteR}=1; //RWrite←1, EnableR←0 (open rbus) (page 6)
		{rbus} = 1 lshift i
		RClock() //R←rbus
		{rbus}=###; //open rbus
		{MC1WriteR}=0; //RWrite←0, EnableR←1 (rbus←←R) (page 6)
		WCompare({rbus},1 lshift i,10000+i)
	]

//Main R file test: involves storing both 1's and 0's in every cell of every address

	for i = 0 to 3 do
	[
		let a =  (i lshift 3)&8 //0 if i even; 8 if i odd
		let b = -(i&1) //0 if i even; #177777 if i odd
		let c = -(i rshift 1) //0 if i = 0,1; #177777 if i = 2,3
		[
		{MC1WriteR}=1; //RWrite←1, EnableR←0 (open rbus) (page 6)
		
		for j = 0 to 255 do // Write all R locations
		[
		
			//operand for j = 0,1
			let d = j lshift a //j if i even; j lshift 8 if i odd

			//operand for j = 2,3
			let e = ((j*15) rshift 4)&#17 //"non-synchronous hex"
			let f = (a*#10421) xor b //e in all hexes, inverted if i odd

			//data to be stored and retrieved
			let g = (d & (not c)) % (f & c) //d if i = 0,1; f if i = 2,3

			//set up R and RP addresses to =j
			{MC1SA}=j
			EClock() //MC1Ad←((Stkp+0)=0 if j=0 or {MC1SA}=j if j>0)
			         //RA=(MC1Ad=j) since RSA,B=4,6
			EClock() //RPaddr←(RA=MC1Ad=j), RPWrite←(RWrite=1)

			//write into R[0:15] and RP[0:1] (page 18)
			{rbus}=g
			{RPIn}=g
			RClock() //R←(rbus=g), RP←({RPIn}=g[14:15])
		]
		//] repeat
		{rbus}=###
		{MC1WriteR}=0; //RWrite←0, EnableR←1 (rbus←R) (page 6)

		for j = 0 to 255 do //Read all R locations
		[
			//operand for j = 0,1
			let d = j lshift a //j if i even; j lshift 8 if i odd

			//operand for j = 2,3
			let e = ((j*15) rshift 4)&#17 //"non-synchronous hex"
			let f = (a*#10421) xor b //e in all hexes, inverted if i odd

			//data to be stored and retrieved
			let g = (d & (not c)) % (f & c) //d if i = 0,1; f if i = 2,3

			//set up R addresses to =j and check contents
			{MC1SA}=j
			EClock() //MC1Ad←((Stkp+0)=0 if j=0 or {MC1SA}=j if j>0)
			         //RA=(MC1Ad=j) since RSA,B=4,6
			//WCompare({rbus},g,10100+i,j) //see NOTES below

			//set up RP addresses to =j and check contents (page 18)
			EClock() //RPaddr←(RA=MC1Ad=j)
			EClock() //RPByte[0:1]←RP[0:1]
			//WCompare({RPOut},g&3,10110+i,j)
		]
		] repeat
	]

	//NOTES: failure analysis information in case of error stop (i is ls digit of test no.)
	//   i=0: R address (RA) should = rbus[8:15] =j
	//   i=1: R address (RA) should = rbus[0:7]  =j
	//   i=2,3: All hexes on the rbus should be the same as one another
	//      a) if same, R addressing has problems 
	//      b) if different, the hex digit that disagrees with the other hexes has data
	//         path problems, assuming the other hexes match "should be" 

] //repeat

//**************************************************************************************
//Test 11: Test the cycler/masker BYPASS logic (page 6)
//         Check the ALU control prom d5 (page 9)

let Test11() be
[
	SpeakTest(11) //set initial conditions (see notes at end of ALU.TST)

	{Stkp←ALUA'}=1; //keep Stkp=0
	{MASK}=#177777; //for ALUA=0 (give error if BYPASS fails)
	{MC1WriteR}=1; //enable RWrite

	for i = 0 to 15 do
	[
		let a = 1 lshift i
		{rbus}=a
		RClock() //write a into R (RA=Stkp=0)
		{rbus}=###

		{mirbus}=#2540; //MemInst=1, RMOD=1, RSEL=00 00 00
		ClockMIR() //RSA,B←1,4, RA←(CTask,RSEL[2:5]=0), rbus←R, set TComing
		WCompare({rbus},a,11000+i) //check R (RA=0)

		EClock() //H1←(rbus=a), H2←0's, set BYPASS (b5b flip-flop, page 6)
		         //d5 prom out = 0011 0010: ALUF()←"R+B"
		EClock() //H3P←ALUOUT=(ALUA.IN=H1=val)+(ALUB=H2=0)

		{mirbus}=#1537; //MemInst=0, RMOD=1, RSEL=01 11 11
		ClockMIR() //RSA,B←3,3, open rbus, reset TComing

		{Cycle0Feed'}=1; //rbus←H3P
		WCompare({rbus},a,11100+i) //a+0, using BYPASS
		{Cycle0Feed'}=0
	]

//Check that all values of the ALUF field cause an "R+T" when MemInst=1
//Verify d5 prom control of EnableRDlyd2 when MemInst=1 (parity check logic on page 18)

	{rbus}=2
	RClock() //write 2 in R (RA=Stkp=0)
	{rbus}=###
	{F2.2}=1; //for H2←2

	for i = 0 to 15 do
	[
		{mirbus}=#2540; //MemInst=1, RMOD=1, RSEL=00 00 00
		ClockMIR() //RSA,B←1,4, RA←(CTask,RSEL[2:5]=0), rbus←R, set TComing

		{aluf}=i
		EClock() //H1←(rbus=2), H2←(F1F2=2), set BYPASS (b5b flip-flop, page 6)
		         //d5 prom out = 0011 0010: ALUF()←"R+B"
		EClock() //H3P←ALUOUT=(ALUA.IN=H1=2)+(ALUB=H2=2)
		         //set EnableRDlyd2 since CheckRParity'=0
		WCompare({EnableRDlyd2},1,11200,i)

		{mirbus}=#1537; //MemInst=0, RMOD=1, RSEL=01 11 11
		ClockMIR() //RSA,B←3,3, open rbus, reset TComing

		{Cycle0Feed'}=1; //rbus←H3P
		WCompare({rbus},4,11201,i) //2+2=4, using BYPASS
		{Cycle0Feed'}=0
	]

//Verify d5 prom (page 9) control of EnableRDlyd2, (parity check logic on page 18)
//The CheckRParity' signal should =0 except when (ALUF[0:3] =0,14,15) and MemInst=0

	let t11sb = table [ 0;1;1;1;1;1;1;1; 1;1;1;1;1;1;0;0; 1;1;1;1;1;1;1;1; 1;1;1;1;1;1;1;1 ]

	{MC1WriteR}=0
	{MC1NeedsR}=1
	EClock() //set Suspend for EnableR=1

	for i = 0 to 31 do
	[
		{MemInst/d}= i rshift 4; //for MemInst←i[11]
		{aluf}=i; //ALUF[0:3]←i[12:15]
		ClockMIR() //c16b flip-flop ←(EnableR'=0) (page 18), MemInst←i[11]
		EClock() //set EnableRDlyd2 if EnableRParity'=0
		WCompare({EnableRDlyd2},t11sb!i,11300,i)
	]
]