{ChipTest.mc, HGM,  4-Nov-84  2:29:05}

{Chip Tester for Dicentra memory.  See FTCS-7 pg 81.}

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

RegDef[bank, R, 0]; {Current bank}
RegDef[highBank, U, 0]; {Highest bank to test}
RegDef[lowBank, U, 1]; {Lowest bank to test}
RegDef[address, R, 1];  {Word within bank}
  RegDef[rhAddr, RH, 1];
RegDef[addres2, R, 2];
  RegDef[rhAdr2, RH, 2];
RegDef[expected, R, 3];
  RegDef[rhEx, RH, 3];
RegDef[found, R, 4];
RegDef[found2, R, 5];
RegDef[found3, R, 6];

RegDef[diff, U, 10];
RegDef[picked, U, 11];
RegDef[dropped, U, 12];

RegDef[rA, R, 0A];
RegDef[rB, R, 0B];
RegDef[rC, R, 0C];
RegDef[passCount, R, 0E]; {number of good passes}
RegDef[test, RH, 0E]; {current test}


Set[Test.Zero, 0];
Set[Test.One, 1];
Set[Test.Two, 2];
Set[Test.Three, 3];
Set[Test.Four, 4];


Trap:	rA ← RRot1 ErrnIBnStkp, ClrIntErr, CANCELBR[$, 0F], c1, at[0];
	Xbus ← rA LRot0, XwdDisp,			c2;
	DISP2[TrapType],				c3;
	
Parity:	GOTO[GoToGo],					c1, at[0,4,TrapType];
Init:	GOTO[GoToGo],					c1, at[1,4,TrapType];
Stack:	GOTO[GoToGo],					c1, at[2,4,TrapType];
IB:	GOTO[GoToGo],					c1, at[3,4,TrapType];

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

Go:	rhAdr2 ← 0,					c1;
	Noop,						c2;
	Noop,						c3;

	addres2 ← 010,					c1;
	addres2 ← addres2 LRot8,			c2;
	addres2 ← addres2 + 018,			c3;

	IO ← [rhAdr2, addres2 + 0],			c1;
	MDR ← 0A, {Disarm 40.96ms int and Watchdog}	c2;
	Noop,						c3;
	
	IO ← [rhAdr2, addres2 + 0],			c1;
	MDR ← 040, {Ack it (in case)}			c2;
	Noop,						c3;

{Give interrupt time to go away.}
	Noop,						c1;
	Noop,						c2;
	Noop,						c3;

	Noop,						c1;
	Noop,						c2;
	Noop,						c3;

	passCount ← 0, test ← Test.Zero, ClrIntErr,	c1;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}		c2;
	addres2 ← 0, GOTO[MainLoop],			c3;

	
{------------------------------------------------------------------------------------}
MainLoop:
	Noop, 						c1;
MainLoop2:
	Noop, 						c2;
MainLoop3:
	bank ← lowBank,					c3;

NewBank:
	Noop, 						c1;
	rhAddr ← bank LRot0, MesaIntBr,			c2;
	rhAdr2 ← bank LRot0, BRANCH[$, MesaInt],	c3;

	Noop,						c1;
	Xbus ← test, XDisp,				c2;
	DISP4[DoIt],					c3;

NextBank:
	Noop,							c2;
	bank ← bank + 1,					c3;
	
	Q ← highBank,					c1;
	Q ← Q - bank, NegBr,				c2;
	BRANCH[NewBank, NextTest],			c3;
 
NextTest:
	ExtCtrl ← 3, {Gets Bumped on rising edge} 	c1;
	ExtCtrl ← 7					c2;
	Xbus ← test, XDisp,				c3;

	RET[NewTest],					c1;
	
	
{------------------------------------------------------------------------------------}
ZeroFinished:
	addres2 ← 0,					c2, at [Test.Zero, 10, NewTest];
	test ← Test.One, GOTO[MainLoop], 		c3;
	
OneFinished:
	addres2 ← addres2 + 1, CarryBr,			c2, at [Test.One, 10, NewTest];
	BRANCH[$, DoTestTwo], 				c3;
	
	GOTO[MainLoop2], 				c1;

DoTestTwo:
	addres2 ← 0, 					c1;
	test ← Test.Two, GOTO[MainLoop3], 		c2;
	
TwoFinished:
	addres2 ← addres2 + 1, CarryBr,			c2, at [Test.Two, 10, NewTest];
	BRANCH[$, DoTestThree], 			c3;
	
	GOTO[MainLoop2], 				c1;

DoTestThree:
	addres2 ← addres2 xor ~addres2, 		c1;
	test ← Test.Three, GOTO[MainLoop3], 		c2;
	
ThreeFinished:
	addres2 ← addres2 - 1, CarryBr,			c2, at [Test.Three, 10, NewTest];
	BRANCH[DoTestFour, $], 				c3;
	
	GOTO[MainLoop2], 				c1;

DoTestFour:
	addres2 ← addres2 xor ~addres2, 		c1;
	test ← Test.Four, GOTO[MainLoop3], 		c2;
	
FourFinished:
	addres2 ← addres2 - 1, CarryBr,			c2, at [Test.Four, 10, NewTest];
	BRANCH[DoTestOne, $], 				c3;
	
	GOTO[MainLoop2], 				c1;

DoTestOne:
	passCount ← passCount + 1, 			c1;
	addres2 ← 0, 					c2;
	test ← Test.One, GOTO[MainLoop]			c3;
	
{------------------------------------------------------------------------------------}
{Initialize whole world to 0.}
WriteZeros:
	expected ← 0,					c1, at[Test.Zero,10,DoIt];
	address ← 0,					c2;
	Noop,						c3;

WriteZeroLoop:
	MAR ← [rhAddr, address + 0],			c1;
	MDR ← expected, address ← address + 1, CarryBr,	c2;
	BRANCH[WriteZeroLoop, $],			c3;
	
	GOTO[NextBank],					c1;
{------------------------------------------------------------------------------------}
{Do Up transition in forward scan.}
PassOne:
	expected ← 0, GOTO[Forward],			c1, at[Test.One,10,DoIt];

{Do Down transition in forward scan.}
PassTwo:
	expected ← expected xor ~expected, GOTO[Forward], c1, at[Test.Two,10,DoIt];
	
Forward:
	address ← addres2,				c2;
	[] ← 0, ZeroBr,					c3;
	
{Check [addres2..FFFF].}
ForwardA:
	MAR ← [rhAddr, address + 0], BRANCH[BugFA1, $],	c1;
	address ← address + 1, CarryBr,			c2;
	found ← expected xor MD, ZeroBr, BRANCH[ForwardA, $], c3, LOOPHOLE[stw];
	
	BRANCH[BugFA2, $],				c1;
	expected ← ~expected,				c2;
	Noop,						c3;
	
ForwardStore:
	MAR ← [rhAdr2, addres2 + 0],			c1;
	MDR ← expected,					c2;
	Noop,						c3;
	
	address ← addres2,				c1;
	Noop,						c2;
	[] ← 0, ZeroBr,					c3;
	
{Check [0..addres2] (scanning backwards).}
ForwardB:
	MAR ← [rhAddr, address + 0], BRANCH[BugFB1, $],	c1;
	address ← address - 1, CarryBr,			c2;
	found ← expected xor MD, ZeroBr, BRANCH[$, ForwardB], c3, LOOPHOLE[stw];
	
ForwardEnd:
	BRANCH[BugFB2, $],				c1;
	Noop,						c2;
	Noop,						c3;
	
	GOTO[NextBank],					c1;
	
{------------------------------------------------------------------------------------}
{Do Up transition in reverse scan.}
PassThree:
	expected ← 0, GOTO[Reverse],			c1, at[Test.Three,10,DoIt];
	
{Do Down transition in reverse scan.}
PassFour:
	expected ← ~expected xor expected, GOTO[Reverse], c1, at[Test.Four,10,DoIt];
	
Reverse:
	address ← addres2,				c2;
	[] ← 0, ZeroBr,					c3;
	
{Check [0..addres2] (scanning backwards).}
ReverseA:
	MAR ← [rhAddr, address + 0], BRANCH[BugRA1, $],	c1;
	address ← address - 1, CarryBr,			c2;
	found ← expected xor MD, ZeroBr, BRANCH[$, ReverseA], c3, LOOPHOLE[stw];
	
	BRANCH[BugRA2, $],				c1;
	expected ← ~expected,				c2;
	Noop,						c3;
	
ReverseStore:
	MAR ← [rhAdr2, addres2 + 0],			c1;
	MDR ← expected,					c2;
	Noop,						c3;
	
	address ← addres2,				c1;
	Noop,						c2;
	[] ← 0, ZeroBr,					c3;
	
{Check [addres2..FFFF].}
ReverseB:
	MAR ← [rhAddr, address + 0], BRANCH[BugRB1, $],	c1;
	address ← address + 1, CarryBr,			c2;
	found ← expected xor MD, ZeroBr, BRANCH[ReverseB, $], c3, LOOPHOLE[stw];
	
ReverseEnd:
	BRANCH[BugRB2, $],				c1;
	Noop,						c2;
ReverseEnd3:
	Noop,						c3;
	
	GOTO[NextBank],					c1;
	
{------------------------------------------------------------------------------------}
BugFA1:	found ← found xor expected, CANCELBR[Retreat],	c2;
BugFA2:	found ← found xor expected, CANCELBR[Retreat],	c2;
BugFB1:	found ← found xor expected, CANCELBR[Advance],	c2;
BugFB2:	found ← found xor expected, CANCELBR[Advance],	c2;

BugRA1:	found ← found xor expected, CANCELBR[Advance],	c2;
BugRA2:	found ← found xor expected, CANCELBR[Advance],	c2;
BugRB1:	found ← found xor expected, CANCELBR[Retreat],	c2;
BugRB2:	found ← found xor expected, CANCELBR[Retreat],	c2;


Advance: address ← address + 1, GOTO[Error],		c3;
Retreat: address ← address - 1, GOTO[Error],		c3;
	

Error:	Noop,						c1;
	Noop,						c2;
	found2 ← MD,					c3, LOOPHOLE[mdok];

	MAR← [rhAddr, address + 0],			c1;
	Noop,						c2;
	found3 ← MD,					c3;

	Q ← found xor expected,				c1;
	diff ← Q,					c2;
	Noop,						c3;

	rA ← Q and ~expected,				c1;
	picked ← rA,					c2;
	Noop,						c3;

	rA ← Q and expected,				c1;
	dropped ← rA,					c2;
	Noop,						c3;

DataMismatch:
	Noop,						c1;
	Noop,						c2;
	GOTO[Go],					c3;
	
{------------------------------------------------------------------------------------}

MesaInt:
	addres2 ← 010,						c1;
	addres2 ← addres2 LRot8,				c2;
	addres2 ← addres2 + 018,				c3;

	IO ← [rhAdr2, addres2 + 0],			c1;
	rB ← ExtStat,					c2;
	rA ← MD,					c3;

MesaIntIsProbablyAParityError:
	Noop,						c1;
	Noop,						c2;
	GOTO[Go],					c3;
	
{------------------------------------------------------------------------------------}