%
****************************************************************************************
*** EDtimex.mc : Timer Exerciser microcode *** Revision 1.1 ***
*** Purpose : This test exercises timers 0 - 15d.
It replaces the page 16d portion of standard KERNEL.
*** Minimum Hardware : Standard 4 CPU boards.
*** Approximate Run Time : 6d seconds.
*** Written by : C. Thacker, Feb. 25, 1979
*** Modified by : K. Mayekawa, Feb. 28, 1980
*** Standardize title page and code format.
*** Modified by : C. Thacker, May 3, 1980
Standardized assembly with timex.cm, fixed for new d0lang.
****************************************************************************************
****************************************************************************************
*SubTest Description:
* SubTest 0: Timer Initilization (Task 14)
Clears the timers and sets up the refresh timer.
* SubTest 1: Timer Wakeup routine (Task 14)
Timer wakeups come here.
If the timer 15d expires, memory is refreshed and a new value
is added to the timer, then Mouse halt is checked.
If any of the timers 0-14d expires, it is restarted and timeout
counter for that timer is set to TimeOut.
* SubTest 2: Check Timeout routine (Task 0)
Loads the timers 0-14d, sets a timeout value for these timers
to TimeOut, then checks for timeouts.
****************************************************************************************
*BreakPoints:
* Fail : The timer was not restarted (timeout register was not set
to TimeOut) when it expired.
* Passed-EDtimex-Test: Passed all tests, and all passes.
* WrongSlotExpired : Wrong timer slot expired. Timer slots should expire from
14d to 0 sequentially.
*Note: The program also breaks at MouseHalt.
****************************************************************************************
*BreakPoint Logic Analyzer Sync Points:
* There is no short looping capability for this exerciser.
****************************************************************************************
*Loading and Reading Timers:
* Timers are loaded from the ALUA bus by functions LOADTIMER and ADDTOTIMER.
* Also they can be read as an external R source(TIMER).
* When loading or adding to timers, bits are divided as follows:
* Bits 0 - 3 : new state (loaded by both LOADTIMER and ADDTOTIMER)
* Bits 4 - 11 : new data to be loaded (by LOADTIMER) or new data to be added
* to the current data (by ADDTOTIMER)
* Bits 12 - 15 : slot number to be loaded
****************************************************************************************
*Special Reg. Definition:
* RM[20b] - RM[36b]: contains timeout values for each slot.
set to TimeOut(=40b) when timers are started initially.
Each time through the BigLoop, these timeouts are decremented.
If one of the timeouts becomes zero, a breakpoint occurs.
The maintenance panel is also incremented, so if you kill the
breakpoint at FAIL, you will see if any errors occur by noting
a nonzero panel.
Whenever a timer expires normally, it is restarted and its associated
timeout register is set to TimeOut. Thus, we should never see a zero
value in any of the timeout registers.
* InnerCount: incremented each time through the BigLoop, i.e. each time
TimeOuts for all slots 0 through 14d are decremented by one.
* MaxInnerCount: contains the maximum value for InnerCount.
When InnerCount=MaxInnerCount, the program completes one
pass, resets InnerCount, and goes back to the start of the
program if PassCount<MaxPass.
****************************************************************************************
*Subroutine Description:
* StartTimer: loads the timer whose slot is in Tslot0 and sets RM[Tslot0 + 20b]
to TimeOut(=40b).
It sets the state of the timer to 5 (Simple Timer).
Value loaded is (112d - (slot# x 4)), loading timer 14d
with the smallest value and timer 0 with the largest value.
Thus the timers should expire from slot 14d through 0 sequentially.
Slot number State loaded Value loaded TimeOut
(decimal) (decimal) stored at
14 5 56 RM[36b]
13 5 60 RM[35b]
12 5 64 RM[34b]
11 5 68 RM[33b]
10 5 72 RM[32b]
9 5 76 RM[31b]
8 5 80 RM[30b]
7 5 84 RM[27b]
6 5 88 RM[26b]
5 5 92 RM[25b]
4 5 96 RM[24b]
3 5 100 RM[23b]
2 5 104 RM[22b]
1 5 108 RM[21b]
0 5 112 RM[20b]
****************************************************************************************
%
****************************************************************************************
*INITIALIZATION:
TITLE[Timer Exerciser];
Set[TTask,16];
Set[TimerPage,2];
Set[TimerInitLoc,add[lshift[TimerPage,10],20]];
MC[TimerInitlocL,and[TimerInitLoc,377]];
MC[TimerInitLocH,add[160000,and[TimerInitLoc,177400]]]; *Notify to task 16, location TimerInitLoc
Set[TimerTable,add[lshift[TimerPage,10],100]];
MC[TimerValue,53400]; *State 5, Value 112d
MC[TimeOut,40];
********** R-Registers: **********
* Task 0 Registers
SETTASK[0];
RV[SubTest, 60];
RV[Rlink0, 61];*subroutine return link
RV[Revision, 62, 1];*Revision 1
RV[Run-Time, 63, 6];*Run-Time is 6d seconds
RV[PassCount, 64, 0];
RV[MaxPass, 65, 5000];
RV[InnerCount, 66];
RV[MaxInnerCount, 67, 100];
RV[Tslot0, 70];*slot number for timers
RV[Temp, 71];
RV[Temp1, 72];
* Task 14 Registers
SETTASK[TTask];
RV[Tslot,40];
RV[ExpectedSlot,41];*slot number which should expire next
RV[TimerTemp,42];*temporary register
RV[RTimer,43];*constant for memory refresh timer
RV[REFR,44];*refresh address
****************************************************************************************
*** MAIN routine:
*SubTest 0 (Timer Initialization)
SETTASK[TTask];
ONPAGE[TimerPage];
InitTimers: TimerTemp ← (100000C), AT[TimerInitLoc];
ClrTimers: LOADTIMER[TimerTemp];*clear out all Timers
NOP;*Timers can be loaded only once
NOP;*every 7 microinstructions
NOP;
NOP;
TimerTemp ← (TimerTemp) + 1, ResetMemErrs;*clear any pending memory errors
LU ← (TimerTemp) AND (17C);*there are 16d timers
REFR ← (0C), DBLGOTO[InitDone, ClrTimers, ALU=0];
InitDone: LU ← TIMER;*clear all wakeups
RTimer ← (50000C);*set up the Refresh timer
RTimer ← (RTimer) OR (257C);*simple timer, value 10d, slot 15d
LOADTIMER[RTimer];
ExpectedSlot ← 16c;*insist that the timers expire in order
CALL[TimerRet];*returns to task 0
*SubTest 1 (Timer Wakeup routine)
TimerWakeup: DISPATCH[TIMER,14,4];*Timer wakeups come here
DISP[Timers];*initialize base register
*Timer dispatch table for task 14 (Timers are read in complemented form.)
Timers: REFRESH[REFR], GOTO[RefreshNext], AT[TimerTable,00]; *slot 15d(used as a refresh timer)
Tslot ←T ← 16c, GOTO[RestartTimer], AT[TimerTable,01]; *slot 14d
Tslot ←T ← 15c, GOTO[RestartTimer], AT[TimerTable,02]; *slot 13d
Tslot ←T ← 14c, GOTO[RestartTimer], AT[TimerTable,03]; *slot 12d
Tslot ←T ← 13c, GOTO[RestartTimer], AT[TimerTable,04]; *slot 11d
Tslot ←T ← 12c, GOTO[RestartTimer], AT[TimerTable,05]; *slot 10d
Tslot ←T ← 11c, GOTO[RestartTimer], AT[TimerTable,06]; *slot 9d
Tslot ←T ← 10c, GOTO[RestartTimer], AT[TimerTable,07]; *slot 8d
Tslot ←T ← 7c, GOTO[RestartTimer], AT[TimerTable,10]; *slot 7d
Tslot ←T ← 6c, GOTO[RestartTimer], AT[TimerTable,11]; *slot 6d
Tslot ←T ← 5c, GOTO[RestartTimer], AT[TimerTable,12]; *slot 5d
Tslot ←T ← 4c, GOTO[RestartTimer], AT[TimerTable,13]; *slot 4d
Tslot ←T ← 3c, GOTO[RestartTimer], AT[TimerTable,14]; *slot 3d
Tslot ←T ← 2c, GOTO[RestartTimer], AT[TimerTable,15]; *slot 2d
Tslot ←T ← 1c, GOTO[RestartTimer], AT[TimerTable,16]; *slot 1d
Tslot ←T ← 0c, GOTO[RestartTimer], AT[TimerTable,17]; *slot 0d
*Refresh has been started.
RefreshNext: ADDTOTIMER[RTimer];*load the refresh timer
*Check for Mouse halt
CheckMouse: T ← 10000C;*check for mouse halt
LU ← (PRINTER) AND (T);
DBLGOTO[MouseHalt,TimerRet,ALU#0];
TimerRet: RETURN;*for task switching
*Mouse halt, Midas breakpoint
MouseHalt: GOTO[.], SETFAULT;*timers cannot be restarted.
RestartTimer: LU ← (ExpectedSlot) - (T);*insist that the slots expire in order 14..0
SKIP[ALU=0];
WrongSlotExpired: BREAKPOINT;
ExpectedSlot ← (ExpectedSlot)-1;
SKIP[ALU>=0];*reset expectedslot if negative
ExpectedSlot ← 16c;
T ← (Tslot) OR (TimerValue);
TimerTemp ← T;
ADDTOTIMER[TimerTemp];
*Set RM[20b + Tslot] to TimeOut - if this register ever becomes zero,
*the main program will restart the timer and cause an error.
Tslot ← (Tslot) + (20c);*Array of count words is in RM[20b]-RM[36b]
T←STKP;
Tslot ← T, STKP ← Tslot;
Tslot ← (Tslot) XOR (377C);
STACK ← TimeOut;
STKP ← Tslot, RETURN;*restore stackpointer
*SubTest 2 (Check Timeout routine)
SETTASK[0];
ONPAGE[1];
start:
go: SubTest ← 2C;
InnerCount ← 0C;*reset InnerCount
CLEARMPANEL, CALL[SwitchTo14];*Notify timer initialization stuff
*come back here after timer initialization
SetTimers: SubTest ← 2C;
Tslot0 ← T ← (16C), GOTO[StartTLoop];
*switch to Task 14, InitTimers
SwitchTo14: SubTest ← 0C;
Tslot0 ← TimerInitlocL;
Tslot0 ← (Tslot0) OR (TimerInitLocH);
APC&APCTask ← TSlot0;
RETURN;
StartTLoop: CALL[StartTimer];*start timer, set count to TimeOut
Tslot0 ← T ← (Tslot0)-1;
GOTO[BigLoop, ALU<0];
GOTO[StartTLoop];
BigLoop: Tslot0 ← T ← (16C);
MainLoop: Temp ← T;
NOP;*make the loop longer
Temp ← (Temp) + (20c);
SubTest ← 1C, TASK;
CheckTimeout: SubTest ← 2C;
STKP ← Temp;
STACK ← (STACK) - (1C), GOTO[NoFail,R>=0];*slot Tslot0 got restarted in time
Fail: BREAKPOINT,INCMPANEL;
GOTO[go];
NoFail: Tslot0 ← T ← (Tslot0) - (1C);
GOTO[MainLoop, ALU>=0];
InnerCount ← T ← (InnerCount) + (1C);*increment InnerCount
LU ← (MaxInnerCount) - (T);
GOTO[OnePassFinished, ALU=0];*finished one pass ?
GOTO[BigLoop];
OnePassFinished: PassCount ← T ← (PassCount) + (1C);*increment PassCount
LU ← (MaxPass) - (T);
GOTO[Passed-EDtimex-Test, ALU=0];*finished all passes ?
GOTO[go];
Passed-EDtimex-Test: PassCount ← 0C, GOTO[go], BREAKPOINT;
********** SUBROUTINE: StartTimer **********
*
* to load the timer whose slot is in Tslot0 and
* to set RM[Tslot0 + 20b] to TimeOut
StartTimer: USECTASK;
T ← APC&APCTASK;
Rlink0 ← T;
T ← Tslot0;*Tslot0 has the slot number
Temp ← T;
Temp ← (Temp) OR (TimerValue);
T ← lsh[Tslot0,6];
Temp ← (Temp) - (T);*subtract (slot number x 4) from TimerValue
LoadTimer[Temp];
T ← Tslot0;
Temp ←T;
Temp ← (Temp) + (20c);
STKP ← Temp;*set count to TimeOut
STACK ← TimeOut;
Temp ← T;*restore the slot number
APC&APCTASK ← Rlink0;
RETURN;
END;