%
Page Numbers: Yes First Page: 1
Heading:
memAfio.mcJune 9, 1981 10:19 AM%
title[memAfio];
top level;
beginFIOtest:
* September 19, 1978 4:17 PM
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ROUTINEDESCRIPTION
fioTestEntry point for fio test
fioTestCodeCode that runs in test task
fioStestCode that tests storage
fioTesterResetReset the fio jig, clobbers rmx7
setFIOtesterSet fio jig for t = task num, rscr = subtask
fioSetFIOtesterSet fio jig for current subask, task
iaSubTaskInitialize subtask variable
aNextSubTaskReturn the next subtask value
aGetSubTaskReturn current subtask value
aGetSTvaReturns effective address for a subtask
fioIMemInitialize Storae as required for fio test
fioStorageWrite identity into storage (mem[va] ← va)
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
May 16, 1979 1:49 PM
Another incompatibility: since rstk is wider, the old assumptions about which bits are unchanged by subtasking are incorrect.
May 16, 1979 11:51 AM
Fix more model0/model1 incompatability problems: numberous mem subroutines save their return on the stack & must not be called from non-emulator tasks.
May 15, 1979 4:03 PM
Fix model0/model1 incompatability: stack no longer shared w/ RM means that the initialization code can’t write into RM via stkp manipulations.
May 4, 1979 2:27 PM
Construct model1 version of code from model0 version.
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
here’s how it works:
TIOA 300 stores what the devise believes is its task number and its subtask number.
Top 4 bits task, next 2 subtask, next two magic (see below)
When an IOfetch or IOstore is done by the task and subtask stored in TIOA 300,
The device does the right thing BUT ONLY TWICE, i.e., it is two munches big.

The microcode should first set TIOA 300 to the apprpriate task and subtask number,
then do (in that task and subtask) TWO IOfetches, then two IOstores, and see if
what it got back is the same a s what it sent. All subtasks should be verified.
Bits 06 and 07 of TIOA 300 should be ZERO for now. They are wire-ored
to the parity bits of the FIN bus to inject ST parity errors.

Reminders about the Testing

The emulator can have subtasks, too! First, for every task, make sure
that membase and rbase get the appropriate bits or’d into them by
the current subtask:
(things to do
1) choose addresses other than 0..37B to make sure the subtask bits
arrive early enough for base register arithmetic

2) check all the bits on the fast io bus

3) don’t forget to check rstk bits

4) worry about what portion of te test to run during task switching and
holds. verify w/ dough that taskswitching and holds will be ok.

5) remember, for subtsks, RBase[2:3] ← RBase[2:3] OR Subtask[0:1].

6) subtask[0:1] are or’d w/ memBase[2:3] during memory references.

7) don’t forget to exit with subtask = 0

8) Initialize the Base registers such that when the membase is zero and the subtask bits get or’d into membase, the resulting base register used by the processor will have a unique value in it that enables the test to make sure the subtask bits really got or’d in. In particular, we initialize as follows: BR[i] ← i*1000B. This results in a situation where "vm 0" for subtask i should REALLY be vm (i * 10000B). This fact relates to which bits get or’d into memBase.
* June 5, 1981 4:16 PM

FioControl: TYPE = MACHINE DEPENDENT RECORD[
Task: TaskN,
subTask: SubTaskN
];
TaskN: CARDINAL[0..17];
subTaskN: CARDINAL[0..3];

FOR task IN [0..17] DO
FOR subTask IN subTaskN DO
iMem[];
NOTIFY[task, @fioTestCode];--awaken task to xqt the test
ENDLOOP;-- subTask loop
ENDLOOP;-- Task loop;
ioReset[];
OUTPUT ← fioTester;
END;
fioTestCode: PROCEDURE =
BEGIN
FIOtestRbase[Task, subTask];
FOR i IN Va DO mem[i] ← i;
clearCacheFlags[];
setFIOtester[task, subTask];
IOFetch ← 0;
IOFetch ← 20B;
IOStore ← 0;
IOStore ← 20B;
ioReset[];-- could substitute setFIOtester[0,0];

FOR i IN [0..37B] DO
expectAddr ← i + BITSHIFT[subTask, subTaskMemShift];
IF mem[expect] #NOT(expectAddr)THEN ERROR;
ENDLOOP;

FOR i IN [0..37B] DO
expect ← i + BITSHIFT[subtask, subTaskMemShift]
mem[expectAddr] ← i;
ENDLOOP;
setFIOtester[task, subTask];
IOFetch ← 0;
IOFetch ← 20B;
IOStore ← 0C;
IOStore ← 20B;
ioReset[];

FOR i IN [0..37] DO
expectAddr ← i + BITSHIFT[subTask, subTaskMemShift];
IF mem[expectAddr] #NOT(expectAddr)THEN ERROR;
ENDLOOP;
END


FIOtestRbase: PROCEDURE[Task: TaskN, subTask:subTaskN] =
BEGIN
-- subTask.0 gets or’d into RBASE.3 while subTask.1 gets or’d
-- into subtask.1. If RBASE = 0, rstk = 0 then
--
subtask 0 refs effective RBASE[0]
--
subtask 1 refs effective RBASE[1]
--
subtask 2 refs effective RBASE[2]
--
subtask 3 refs effective RBASE[3]
-- To test the fio tester we must set the first 20B RM locations to known
-- values then, reference and store from RM while under the influence of
-- the task/subtask mechanism of the fastio tester.

ioReset[];
FOR xRM in [0..77B] DO RM[xRM]← xRM; ENDLOOP;

setFIOtester[task, subTask];
T ← R0;
R0 ← 100C;
ioReset[];

expect← LSHIFT[subTask, 4];
IF t # expect THEN ERROR;
RBASE← subTAsk;
t← r0;
RBASE← RBASE[defaultRegion];
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

* June 9, 1981 10:19 AM
mc[
fioWaitC, 60]
rvrel[rmx11, 11];
rvrel[rmx12, 12];rvrel[rmx13, 13];rvrel[rmx14, 14];
rvrel[rmx15, 15];
rvrel[rmx16, 16];rvrel[rmx17, 17];
fioTest:
call[fioTesterReset];* perform full init incase we’re running

call[getMemState];
t AND (memState.FIOtest);* see if our test is enabled
branch[FIOtestDone, ALU=0];
noop;

call[EcOn];* remove this when nolonger debugging fio jig
call[iSboard];* this test from Midas & interrupting at
* arbitrary places.

call[initBrs];

fioIBrL:* init the brs for all the membases so that
call[nextBr];* the BR for memBase i contains i left shifted
skpif[ALU#0];* by fio.subTaskBrShift (= i * 1000C)
branch[fioIBrXit]; * Note: subtask 0 ors no bits into memBase,
noop;* (placement ’cause of branch)
call[setMbase];* subTask 1 or’s 2 into memBase, subTask 2
rscr2 ← t;* or’s 4 into memBase and subTask3 or’s
noop;* 6 into memBase. Thus, for subTask 3, va = 0
rscr2 ← lsh[rscr2, fio.subTaskBrShift];* will really reference 6000B since
call[setBr], rscr ← t-t;* we init base register 6 to contain 6000B.
branch[fioIBrL];

fioIBrXit:
call[iapTestTask];
* June 9, 1981 10:04 AM
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
This is the main loop. Each time the test passes through here, it increments the current test task. Ie., it proceeds to test the next task.
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
call[fioIMem];
fioTaskL:
call[apNextTestTask];* top of task loop
skpif[ALU#0];
branch[fioTaskXit];
noop;

call[iaSubTask];
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
This is the sub-loop. Each time the test passes through here, it increments the current test Sub-Task. Ie., it proceeds to test the next sub-task for the current task.
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fioSubTaskL:
call[aNextSubTask];* top of subtask loop
skpif[ALU#0];
branch[fioSubTaskXit];
noop;* for placement

* initialize first 20B RM locations to be 0..20B BEWARE! This code clobbers RM locations
* used by various subroutines! Use subroutines that change RBASE or store into different
* regions with care.

* Restore first 64K of storage.
call[fioRestoreMem];

* Awaken the task we’re currently testing

rscr ← fioTestLoc0C;
rscr ← (rscr) + (fioTestLoc1C);
call[apGetTestTask];* return t = next task to run = apNextTaskX
taskingOff;
subroutine;
link ← rscr;
top level;
LdTPC ← t;* TPC[apNextTaskX] ← fioTestLoc
taskingOn;
call[notifyTask];* awaken the code that really does the test
fioEmuWait:
noop;* give it time to awaken;
branch[fioSubTaskL];

fioSubTaskXit:
branch[fioTaskL];

fioTaskXit:
branch[afterFIOtest];

* June 5, 1981 4:27 PM
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
This code runs as different tasks and exercises the fio test jig.

The basic idea is to background RM[0..77] w/ [0..77B] ie., each rm location
will contain its address. THEN proceed as follows:
Set fio jig to select current subtask
Set RBASE to 0
(Now, rm references are under influence of subtask logic)
t← rmx0 (rstk=0, rbase = current value or’d w/ subtask)
rmx0← 100c;
Reset fio test jig (get rid of subtask influence)

Check that t contains correct value for rmx0
Check that correct rmx0 contains 100C.
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

fioRmTest:
set[xtask, 1];
top level;
taskingOn, at[fioTestLoc];
call[fioTesterReset];* do it early for paranoia
RBASE ← rbase[defaultRegion];
call[setMbase], t ← a0;* use BR0

call[fioInitRM], t←a0;* background RM Region 0
call[fioInitRM], t←1c;* background RM Region 1
call[fioInitRM], t←2c;* background RM Region 2
call[fioInitRM], t←3c;* background RM Region 3

* Begin by checking the oring of bits into RBASE, RSTK

call[fioSetFIOtester];* Automatically sets tester w/ current
* task, subtask value. When this subroutine returns, the subtask logic is enabled! BEWARE!!!

RBASE ← 0s;

t←rmx0;* read rmx0 and write it while under influence of tester
rmx0 ← 100c;
call[fioTesterReset];* clear out the tester

rscr ← t;* rscr = value from RM during influence of subtask
call[aGetSubTask];
q←t;
RBASE←t;* save SubTask in Q
t← rmx0, RBASE← rbase[defaultRegion];

rscr2← t;* rscr2 = "rmx0" for the rm region

t← q;* selected by the subtask. Compute
t← lsh[t, 4];* expected value = address of "rmx0"
t # (rscr);
skpif[ALU=0];
fioRmRMX0Err:* value we read when performing t←rmx0
error;* doesn’t match what we expect. Subtask
* logic didn’t work????

(rscr2)#(100c);* rscr2=value in RMX0 that should have
skpif[ALU=0];* been written w/ 100c while under the
fioRMRMX0Err2:* the influence of the subtask logic
error;

* June 9, 1981 9:40 AM
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fioStest
Test the use of IOfetch, IOstore. This test depends upon the proper initialization of the base registers and of storage. For a given subtask, specific bits will be or’d into memBase, and that causes known base registers to be used during storage references. (The Default base register is 0.) Each base register that corresponds to a subtask has the unique value, subTaskNumber*10000B. Thus a reference to vm 0 in subtask 0 will reference virtual location 0; however, a reference to vm 0 in subtask 2 will reference vm 20000, etc. This is how the test can check that fetches and stores from a given subtask behave properly.

There are 3 tests. The first test simply checks that IOfetch←0, IOfetch←20, IOstore←0, IOstore←20 leaves storage correct. The second test writes into "subtask location 0" and "subtask location 20". Then it performs the two IOfetch, IOstore operations. Storage must be correct at the end of this operation (it must have the new, dirty values). The third, more complex test performs the two IOfetch operations (which will need to take munches from the cache because they will be dirty), writes into "subtask location 0" and then performs two IOstores. The two IO stores should overwrite the data written into the cache by the processor.
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fioStest:
call[aHaltTask17];* cause task 17 to hit brkpt if it runs
call[fioSetFIOtester];

%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
This is the first test. It merely performs two IOfetches followed by a delay and two IOstores. The program checks the data of both munches.
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fioSdoIO1:
rscr ← 20c;* beware of subtask influence on RBASE!
call[fioIOFetch2],t←a0;* IOfetch & store the first two munches of
* memory, then check that storage is correct.

t ← a0;
IOstore ← t;
IOstore ← rscr;

FETCH ← rscr;
B←MD;* wait for last fastio operation to complete
call[fioTesterReset];* before we change our fastio device!

* now we check that storage is correct
t ← 37c;
cnt ← t;* two munches
call[iSvaCtrl];
fioScheck1L:
noop;
call[nextSva];* returns va in t
skpif[ALU#0];
branch[fioScheck1Xit];
noop;* (placement ’cause of branch)
call[aGetSTva], sva ← t;* t = current, subtask relative va; rtns t = subtask’s real va
FETCH ← T;
rscr ← MD;
t # (rscr);* compare addr w/ value
skpif[ALU=0];
fioSerr1:* current subtask should have referenced & not clobbered word in location t
error;* mem[t] should be t
loopUntil[CNT=0&-1, fioScheck1L];
fioScheck1Xit:
call[aChkPipeFlt];
skpif[alu=0];
fioSerr1b:* there was some sort of error left in the pipe!
error;* examine the pipe using midas

%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
This is the second test. It checks to see that IOfetch gets dirty munches from the cache. It checks only the dirty words in the munch.
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
call[aGetSTva], t ← a0;* in subtask relative locations 0 and 20 store
rscr ← not(t);* NOT( their contents)
STORE←t, DBuf ← rscr;

t ← t + (20c);
rscr ← not(t);
STORE ← t, DBuf ← rscr;

call[fioSetFIOtester];* fetch and store the first two munches of
B ← MD;* hold as required for stores to complete
fioSdoIO2:
rscr←20c;* beware of subtask influence on RBASE !
call[fioIOFetch2], t←a0;* memory. check that our modified words are
* still modified.

t ← a0;
IOstore ← t;
IOstore ← rscr;

FETCH ← rscr;* wait for last fastio op to finish before we
B←MD;* modify our fastio device !
call[fioTesterReset];

call[aGetSTva], t ← a0;
rscr2 ← (FETCH ← t);* save correct address in rscr2
rscr ← (MD);
t ← not(rscr2);* should have read not(address)
t # (rscr);
skpif[ALU=0];* fastio device should have gotten the dirty
fioSerr2a:* munch that was in the cache.
error;* rscr2 = va, rscr = MD, t = expected value
STORE←rscr2, DBuf←rscr2;* fix up our dirty & different location

rscr2 ← t ← (rscr2) + (20c);* check the next munch. save addr in rscr2
FETCH ← t;
rscr ← (MD);
t ← not(t);* should have read not(address)
t # (rscr);
skpif[alu=0];
fioSerr2b:
error;* rscr2 = va, rscr=MD, t = expected value

STORE←rscr2, DBuf←rscr2;* fix up our dirty & different location
call[aChkPipeFlt];
skpif[alu=0];
fioSerr2c:* there was some sort of error left in the pipe!
error;* examine the pipe using midas

%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
This is the third test. Note that munches w/ va0, va20 are dirty! This was caused by fioSDoIO2. The IOfetches below will take data from the cache. The longWait that occurs after the two IOfetches prevents the processor from writing into the munch for Va 0 before the fio jig has fetched the data. Remember it takes a while for the IOfetch to run to completion!
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

fioSDoIO3:

call[fioSetFIOtester];* dirty a munch after fio tester has fetched it.
B ← MD;* hold as required for stores to complete
rscr←20c;* beware of subtask influence on RBASE !
call[fioIOFetch2],t←a0;

RBASE ← 0s;* set word "zero" to -1
t ← cm1;
rmx7 ← t-t;
STORE←rmx7, DBuf ← t;* make word (subtask relative) 0 dirty

IOstore ← rmx7;
t ← 20c;
IOstore ← t;
RBASE ← rbase[defaultRegion];
FETCH ← t;* wait for last fastio op to finish before we
B←MD;* modify our fastio device !
call[FIOtesterReset];

call[aGetSTva], t←r0;
FETCH ← t;
rscr ← MD;
t # (rscr);* see if mem[i] = i
skpif[ALU=0];
fioSerr3:* dirty data in cache interfered w/ storing
error;* proper data in fioTester. rscr = MD, t = expected value,
*
t = address referenced.
call[aChkPipeFlt];
skpif[alu=0];
fioSerr3b:* there was some sort of error left in the pipe!
error;* examine the pipe using midas


fioStestBlock:

block;* RETURN TO EMULATOR!

* June 9, 1981 9:11 AM
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fioTesterReset
setFIOtester
fioSetFIOtester
iaSubTask
aNextSubTask
aGetSTva
fioTesterResetUse rmx17 and reset (zero) FIO tester
setFIOtesterUse rmx17, t, rscr & set FIO tester
fioSetFIOtesterSet FIO tester according to current task, subtask
iaSubTaskInitialize aSubTaskX
aNextSubTaskReturn next value of aSubTaskX
aGetSubTaskReturn current value of aSubTaskX
aGetSTvaReturn "real" va seen by current subtask
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fioTesterReset: subroutine;* use last rm location in this region
* CLOBBERS RMX17!!!!
rmx17 ← fioTestAddrC;
TIOA ← rmx17;
rmx17 ← (rmx17) - (rmx17);* wait 1 instruction after resetting device
OUTPUT ← rmx17;* before returning -- so device has time to
return, RBASE← rbase[defaultRegion];* stop oring bits into membase, rstk, & rbase!

setFIOtester: subroutine;* enter w/ t= task num, rscr = subtask num, both
*
right justified. CLOBBER T, RSCR, RSCR2
q ← link;
top level;
t ← lsh[t, 14];* left justify 4 bit task field (20B-4)
rscr ←lsh[rscr, 12];* position 2 bit subtask next to task field
t ← t or (rscr);
rscr ← fioTestAddrC;
TIOA ← rscr;
OUTPUT ← t;* t = task, subt task control for fio tester
subroutine;
link ← q;
return;

fioSetFIOtester: subroutine;
q ← link;* beware subtask RM addressing influence
top level;
call[aGetSubTask];
call[apGetTestTask], rscr ← t;

* expand setFIOtester because once we’ve started subtasking, we can’t access any return links we store into an rm location.

t ← lsh[t, 14];* left justify 4 bit task field (20B-4)
rscr ←lsh[rscr, 12];* position 2 bit subtask next to task field
t ← t or (rscr);
rscr ← fioTestAddrC;
TIOA ← rscr;
OUTPUT ← t;* t = task, subt task control for fio tester
subroutine;
link ← q;
return;

iaSubTask: subroutine;
t ← cm1;
return, aSubTaskX ← t;

aNextSubTask: subroutine;
saveReturn[aRlink];
RBASE ← rbase[aSubTaskX];
t ← aSubTaskX ← (aSubTaskX) + 1;
RBASE ← rbase[defaultRegion];
rscr ← t - (maxSubTaskC);
returnAndBranch[Arlink, rscr];

aGetSubTask: subroutine;
RBASE ← rbase[aSubTaskX];
return, t ← aSubTaskX, RBASE ← rbase[defaultRegion];

aGetSTva: subroutine;* given t = va & aGetSubTask returns the current subtask number, construct the va (and return it in T) as seen by the subTask, also given fioTest’s initialization of the base registers.
saveReturnAndT[Arlink, rscr2];* save the va in rscr2
call[aGetSubTask];* get the current subtTask number into T
noop;* wait for rm to settle down
t ← lsh[t, fio.subTaskMemShift];* position subtask number properly
t ← t OR (rscr2);* construct the proper va
returnUsing[Arlink];

* May 4, 1979 2:30 PM
fioIMem: subroutine;
saveReturn[fioIMemRtn];
call[setMbase], t←r0;
call[fioIStorage];* do it twice to make sure clearing cache flags
call[fioIStorage];* doesn’t leave dirty munches in cache
call[clearCacheFlags];* clear cache for first test
waitOnMapBusy[rscr2];
call[sUseDefaultMcr];

rscr2 ← t-t;
call[setBr], rscr ← t-t;
t ← not(FaultInfo’[]);* clear out any pipe faults
returnUsing[fioIMemRtn];

* June 9, 1981 9:40 AM
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fioIStorage
Initialize memory to contain "self". Ie., mem[i] = i. This routine may be called twice in a row to force all the data munches to storage (required if, for example, clearCacheFalgs gets called immediately after calling this routine).
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fioIStorage: subroutine;
saveReturn[fioIStorageRtn];
call[iSvaCtrl];

fioIMemL:
call[nextSva];
skpif[alu#0];
branch[fioIMemXit];
branch[fioImemL], STORE ← t, DBuf ← t;

fioIMemXit:
returnUsing[fioIStorageRtn];

fioRestoreMem: subroutine;
t← 177777C;
cnt←t;
loopUntil[CNT=0&-1,.], t← (Store←t)-1, DBuf←t;
return;


fioIOFetch2: subroutine;* IOFetch←t, IOFetch←rscr, wait a while
rscr2← link;
top level;
IOFetch←t;
IOFetch← rscr;
t← FioWaitC;
call[longWait];
returnUsing[rscr2];

FIOtestDone:
goto[afterFIOtest];


fioInitRM:
subroutine;* enter w/ t= RM region.
* This subroutine initializes an RM region w/ its address. IE. RM 22 has 22, RM 3 has 3, etc.

RBASE←t;* t=rbase.
t← lsh[t, 4];* Now t=high bits of RM address (remember that rstk is four bits wide).

rmx0 ← t; rmx1 ← t+1; rmx2 ← t+(2c); rmx3 ← t+(3c);
rmx4 ← t+(4c); rmx5 ← t+(5c); rmx6 ← t+(6c); rmx7 ← t+(7c);
rmx10 ←t+(10c); rmx11 ← t+(11c);
rmx12 ← t+(12c); rmx13 ← t+(13c);
rmx14 ← t+(14c); rmx15 ← t+(15c);
rmx16 ← t+(16c); rmx17 ← t+(17c);

return, RBASE← rbase[defaultRegion];