//**************************************************************************************
//ALU8.TST
//By F. Itami and M. Thomson  							January 23, l979
//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 19: Test the H2 register input control logic

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

	//{H2INbus: MemInst/d,RMOD/d',  BBFA',BSEL.0,BSEL.1}

	let t19sb = table [ #21;#10400;-1;-1;  #21;#10400;#21;#10400;
	                    #21;#10400;-1;-1;  #21;#10400;#21;#10400;
	                     -1;    -1;-1;-1;    1;     1;  1;     1;
	                      1;     1; 1; 1;    1;     1;  1;     1 ]

//Set up initial conditions:

	{Cycle0Feed'}=1; //for TWrite and rbus←H3P

	//Load R (RA=Stkp=0) with 0's (for "R+T" = "0+T" when MemInst=1 during loop)
	{MC1WriteR}=1
	RClock() //R←(rbus=H3P=0 (from SpeakTest)) (T←0 - don't care)
	{MC1WriteR}=0

	//Load T (TA=0) with -1
	ClockCycle0() //H3P←(ALUOUT=-1 (from SpeakTest))
	RClock() //T←(rbus=H3P=-1)

	//prevent BBFA from setting EnableMask during loop (page 6)
	{BBFA'}=0; //for EnableMask←1 (MA'=0 from SpeakTest)
	ClockCycle0() //EnableMask←1 (for H2=MASK)
	{MASK}=#200
	{SALUF←H2'}=0
	EClock() //MA'←1 (MASK.08=1)
	{SALUF←H2'}=1; //keep MA'=1
	ClockCycle0() //EnableMask←0 (since MA'=1)

	{aluf}=0; //for ALUOUT←ALUB
	{F1F2}=#21; //Bmux operand
	{mirbus}=#1340; //MemInst=0, RMOD=0, RSEL=00 00 00 (set to zero)

	for i = 0 to 31 do
	[
		{H2INbus} = i xor #14
		ClockMIR() //MemInst←i[0], RMOD←i[1], RSEL[0:5]←0's
		           //RSA,B←(1,4 if i[0:1] not =01, or 1,0 if i[0:1] =01)
		ClockCycle0() //load H2, H1←(rbus=R=0; RA=0)
		              //If MemInst=1: the cycler/masker BYPASS sets, and ALUF()←"R+T"
		ClockCycle0() //H3P←(ALUOUT = H2 or 0+H2)
		{MemInst/d}=0
		ClockMIR() //MemInst←0 for rbus←H3P
		WCompare({rbus},t19sb!i,19100,i)
	]
]

//**************************************************************************************
//Test 20: Test the logic on the top half of page 16:
//         f2 prom, g2 and h2 flip-flops, QWO

and Test20() be
[
	SpeakTest(20) //set initial conditions (see notes at end of ALU.TST)

	//{promf2bus: R.14,R.15, F2.2,F2.3, LT, ALUF.2,ALUF.3}

	{MC1WriteR}=1; //keep EnableR=0 when Suspend=1 for open rbus

//Test the g2 ff's: loading (partially),  left-cycling (completely)
//Test the QWO gate (partially)
//Test the h2 ff's: loading (completely), left-cycling (completely)

	//Set up the f2 prom address to 0011 0010 (#62) for 1010 output
	{promf2bus}=#31; //R[14:15]←0, F2[2:3]←3
	                 //LT←0, (for SRC/DEST=0' =0)
	                 //ALUF[2:3])←1, (address pin 15 is grounded)
	EClock() //H1[14:15]←(R[14:15]=0), H2[14:15]←(F2[2:3]=3)

	ClockAd()  //g2 ff's ← (prom f2 outputs = 1010)
	WCompare({QWO},1,20000) //QWO=1 since g2 ff's = 101x

	{ALUF.2}=1; //for prom f2 output = 1111 to cause error if g2 ff's load by accident

	for i = 0 to 2 do
	[
		{MC1NeedsR} = (i rshift 1) % i; //enable left-cycle g2's if i>0
		EClock() //left-cycle g2's if i=1,2

		//g2's should = 1010 if i=0,2 or 0101 if i=1
		WCompare({QWO},(not i)&1,20000+i) //QWO=1 when g2 ff's = 101x

		//Vary control terms to check the e2 gates (page 16); avoid left-cycle g2 ff's
		{MC1NeedsR} = i; //1 if i=1
		{MC2WillGetR} = not (i rshift 1); //1 if i=0,1

		ClockMC2() //h2 ff's ← (g2 ff's = 1010 if i=0,2 or 0101 if i=1)
		           //g2 ff's should NOT change
		WCompare({QWO},(not i)&1,20002+i) //confirm g2 ff's did not change

		{MC2WillGetR}=1; //MC2WillGetR'←0 for left-cycle h2 ff's
		                 //ShiftMC1XW'←1 for DON'T left-cycle g2 ff's 

		for j = 1 to 5 do
		[
			WCompare({MC2XferWord},(i xor j)&1,20010+i,j)
			EClock() //left-cycle h2 ff's (but not g2 ff's) (Suspend←MemNeedsR)
		]

		{MC2WillGetR}=0; //return to inactive state
	]

	EClock() //Suspend←0 for next test

//Test the f2 prom via the g2,h2 flip-flops; completely test QWO (page l6)

	let t20sb1 = table [

		0;0;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0; 0;1;0;0; 0;0;0;0;
		0;0;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0; 0;1;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0;
		0;0;0;0; 0;0;0;0; 0;1;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0;
		0;1;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0; 0;0;0;0 ]

	let t20sb2 = table [

		1;0;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1; 1;0;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1;
		0;1;0;0; 0;1;1;0; 1;1;1;1; 1;1;1;1; 0;1;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1;
		0;0;1;0; 0;0;1;1; 1;1;1;1; 1;1;1;1; 0;0;1;0; 0;0;1;1; 1;1;1;1; 1;1;1;1;
		0;0;0;1; 1;0;1;0; 1;1;1;1; 1;1;1;1; 0;0;0;1; 0;0;1;1; 1;1;1;1; 1;1;1;1;

		0;1;0;0; 0;1;1;0; 1;1;1;1; 1;1;1;1; 0;1;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1;
		0;0;1;0; 0;0;1;1; 1;1;1;1; 1;1;1;1; 0;0;1;0; 0;0;1;1; 1;1;1;1; 1;1;1;1;
		0;0;0;1; 1;0;1;0; 1;1;1;1; 1;1;1;1; 0;0;0;1; 0;0;1;1; 1;1;1;1; 1;1;1;1;
		1;0;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1; 1;0;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1;

		0;0;1;0; 0;0;1;1; 1;1;1;1; 1;1;1;1; 0;0;1;0; 0;0;1;1; 1;1;1;1; 1;1;1;1;
		0;0;0;1; 1;0;1;0; 1;1;1;1; 1;1;1;1; 0;0;0;1; 0;0;1;1; 1;1;1;1; 1;1;1;1;
		1;0;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1; 1;0;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1;
		0;1;0;0; 0;1;1;0; 1;1;1;1; 1;1;1;1; 0;1;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1;

		0;0;0;1; 1;0;1;0; 1;1;1;1; 1;1;1;1; 0;0;0;1; 0;0;1;1; 1;1;1;1; 1;1;1;1;
		1;0;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1; 1;0;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1;
		0;1;0;0; 0;1;1;0; 1;1;1;1; 1;1;1;1; 0;1;0;0; 1;1;0;0; 1;1;1;1; 1;1;1;1;
		0;0;1;0; 0;0;1;1; 1;1;1;1; 1;1;1;1; 0;0;1;0; 0;0;1;1; 1;1;1;1; 1;1;1;1 ]

	for i = 0 to 127 do
	[
		let k = i lshift 2

		{promf2bus}=i; //R[14:15]←i[9:10], F2[2:3]←i[11:12]
		               //LT←i[13], (SRC/DEST=0' =1 if LT=1)
		               //ALUF[2:3])←i[14:15]
		EClock() //H1[14:15]←(R[14:15]=i[9:10]), H2[14:15]←(F2[2:3]=i[11:12])

		//the f2 prom address now = i*2 (the lsb is grounded)

		ClockAd() //g2 ff's ← (prom f2 outputs)
		WCompare({QWO},t20sb1!i,20100,i)

		ClockMC2() //h2 ff's ← (g2 ff's = prom f2 outputs)

		{MC2WillGetR}=1; //MC2WillGetR'←0 for left-cycle g2 flip-flops

		for j = 0 to 3 do
		[
			WCompare({MC2XferWord},t20sb2!(k % j),20110+j,i)
			EClock() //left-cycle h2 flip-flops, (Suspend←MemNeedsR)
		]

		{MC2WillGetR}=0; //MemNeedsR←0
		EClock() //Suspend←0 for next load of H1,H2
	]
]

//**************************************************************************************
//Test 21: Test the 14 ALU functions using random numbers

and Test21() be
[
	SpeakTest(21) //set initial conditions (see notes at end of ALU.TST)

	Ws("*nTesting ALUF's for 6.46 seconds using random numbers...")

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

	for funct = 0 to 13 do //for each ALU function
	[
		for j = 0 to 99 do //100 random numbers per test
		[
			let vr = Random() 
			let vt = Random()
			let sb = selecton funct into
			[
				case  0: vt
				case  1: vr
				case  2: vr & vt
				case  3: vr % vt
				case  4: vr xor vt
				case  5: vr & (not vt)
				case  6: vr % (not vt)
				case  7: vr xor (not vt)
				case  8: vr+1
				case  9: vr+vt
				case 10: vr+vt+1
				case 11: vr-1
				case 12: vr-vt
				case 13: vr-vt-1
			]

			{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}=funct
			{rbus}=vr
			EClock() //H1←(rbus=vr), H2←(T=vt), ALUF()←"funct"
			{rbus}=###

			EClock() //H3P←(ALUOUT = (vr: "ALU funct" :vt))
			{Cycle0Feed'}=1; //for rbus←H3P (result)

		//Special comparison routine peculiar to this test

			let was = {rbus}
			if was eq sb then loop

			Ws(FORMATN("*nTest 21: aluf=<D>, R=<B>, T=<B>, H3P should be <B>, but was <B>",funct,vr,vt,sb,was))

			while Endofs(keys) do [ ]
			Gets(keys) 
			break //go on to next ALUF
		]
	]
]