%
Page Numbers: Yes First Page: 1
Heading:
MODEL 1:memSubrsX.mcSeptember 22, 1981 9:51 AM%
title[memSubrsX];
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Table Of Contents
by
Order of Occurence

ROUTINE
DESCRIPTION
iMRowCtrlInitialize map row loop control
iMcolCtrlInitialize map column loop control
iMpatCtrlInitialize map wait loop control
iMwaitCtrlInitialize map wait loop control
iMapPageCtrlInitialize map page loop control
iMpageDownCtrlInitialize map page control for decrementing addresses
nextMcolReturn t=next map column
nextMrowReturn t=next map row
nextMwaitReturn t = next map wait value
nextMpage:Return t = next map page
nextMpageDownReturn t = next map page, decrementing addresses
getMpageReturn t = current map page
nextMpatReturn t = next map pattern, ALU=0 means no more patterns
getMpat:Return t = current map pattern.
resetMapInitialize the hardware map
setTestSynSet testsyndrome from T
presetMapInitialize map beginning at page 0
getXmapBaseReturn t = xMapBase
testMapMidas subroutine for testing the map
resetTagKick start the tag bits
xVacateCacheRowVacate cache row for t = va
readMapRead map entry
writeMapWrite a map entry
waitForMapTwait for mapbuf busy to go away. Clobber T
setBrforMap:Set Br to reference a map entry, given Mrow and Mcol
xSetBRforPageSet BR to point to map page in T
xWriteMapPageWrite an entry into map, t = virtual page index, rscr = real page
xZeroMapZero the entire map
xGetConfigGet current memory system configuration.
xGetMapICsInit xPageEndHi, xPageEndLo, 32bit lastpage val
XgetSnModulesReturn sNmodules
xGetICtypeReturn t = icType = BrHi offset per module
xCountModulesReturn t = num storage modules; set sNmodules, too
getMsubrScrsReturn t = mSubrScr
xGetPipe4:return pipe4 with all inverted bits hi true
xBoardLoopMidas subroutine to exercise map
xRWDmuxWrite and read a dmux value, rtn t=ALUFM value =PD(branches will work)
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
September 22, 1981 9:51 AM
Fix xGetICtype: was returning 16B, 64B for IC descriptors rather than 20B, 100B!
May 14, 1981 4:52 PM
Misc changes to make code smaller.
February 10, 1981 11:30 AM
Fix bugs in setBrForMap; fix bugs in nexMpage, nextMpageDown.
February 9, 1981 9:52 AM
Change map Page iterators to handle 64K, 256K ics, add xGetMapICs to read mufflers and findout map IC size. Change getMPat to keep row,,col in separate bytes rather than a field = size of ras addr.
July 1, 1979 2:50 PM
change xVacateCacheRow to use putCFmem, cause WriteMap to keep its data on Bmux one cycle earlier.
June 28, 1979 11:17 AM
Move sGetConfig into this file -- to centralize location of proceedures required for memory system initialization. Add table of contents
May 29, 1979 2:39 PM
Set mcr w/ disHold, noWake during xZeroMap.
January 26, 1979 3:17 PM
Add B←FaultInfo’ to resetMap to turn off any faults that may have occured.
January 25, 1979 5:41 PM
Add xGetPipe2, xGetNumFlts.
January 12, 1979 5:05 PM
cause presetMap to add xMapBase to the real page number when writing map (handle situation wherein there’s no module 0, etc.)
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SUBROUTINE;

knowRbase[defaultRegion];


iMrowCtrl:
return, MrowX ← t← a1;
iMcolCtrl:
return, Mcolx ← t← a1;
iMpatCtrl:
t←cm1;
Mpatx ← t;
t ← curMpatLow ← t-t;
return, curMPatHi ← t;
iMwaitCtrl:
t ← (r0)-(MwaitIncrC);
return, curMWait ← t;
iMapPageCtrl:
xPageXLo← t← a1;
return, xPageXHi←t;
iMpageDownCtrl:
RBASE← rbase[xEndPageLo];
xPageXLo ← xEndPageLo;
xPageXHi ← xEndPageHi;
return, RBASE←rbase[rscr];

* February 10, 1981 4:24 PM

knowRbase[rmForMapLoops];

nextMcol:
subroutine;* compute next column; return it in T
* Mcol IN [0..McolEndC)

RBASE← rbase[Mcolx];* compute end of columns as branch condition
t←Mcolx←(Mcolx)+1, RBASE← rbase[xChipEndRasCas];
return, t-(xChipEndRasCas), RBASE← rbase[defaultRegion];

nextMrow:
subroutine;* compute next row; return it in T
* MrowX IN [0..MrowEndC). Mrow ← MrowX.
*WRITE DIRECTLY INTO DESTIN REGISTER, Mrow.
* use this hack ’cause we can’t switch rbase and then perform the exit test

RBASE← rbase[rmForMapLoops];* compute end of row as branch condition
t ← Mrowx←(Mrowx)+1;
Mrow ← t;* WRITE DIRECTLY INTO Mrow

t ← Mrowx, RBASE← rbase[xChipEndRasCas];* sigh. put loop ctrl where we can access it.
return, t-(xChipEndRasCas), RBASE← rbase[defaultRegion];

nextMwait:
subroutine;* compute next wait return it in T
* curMWait IN [0..MwaitEndC), incremented by MwaitIncrC

RBASE← rbase[rmForMapLoops];* compute end of columns as branch condition
t← curMWait ← (curMwait) + (MwaitIncrC);
RBASE← rbase[defaultRegion];
return,t-(MwaitEndC);

nextMpage:
subroutine;* compute next map page (increment by 1)
RBASE ← rbase[xPageXLo];
t ← xPageXLo ← (xPageXLo) + 1;* increment page number
t-(xEndPageLo), RBASE← rbase[defaultRegion];
skpif[ALU=0], FreezeBC;
return, FreezeBC;* return w/ fast branch condition

RBASE← rbase[xPageXHi];* must increment hi value.
t← xPageXHi← (xPageXHi)+1;* check for done, too.
t-(xEndPageHi);
t← xPageXLo, FreezeBC;
skpif[ALU=0], RBASE← rbase[defaultRegion];
return, PD← a1;* more to do, alu#0
return, PD← a0;* done. alu=0

nextMpageDown:
subroutine;* rtn w/ ALU=0 => no more pages.
RBASE ← rbase[xPageXLo];
t ← xPageXLo ← (xPageXLo) - 1;
t # (cm1);* stop when underflow taskes us to -1??
skpif[ALU=0];
return, PD← a1, RBASE ← rbase[defaultRegion];

knowRbase[xPageXLo];
xPageXHi← (xPageXHi)-1, RBASE← rbase[defaultRegion];
skpif[alu<0];
return, PD← a1;
return, PD← t-t;* rtn ALU=0 => no more pages to write


getMpage:
subroutine;* return current map page without incrementing
RBASE ← rbase[xPageXLo];
return, t ← xPageXLo, RBASE ← rbase[defaultRegion];

* February 9, 1981 10:20 AM
nextMpat: subroutine;* compute next pattern index; return in t
* pattern1 IN [0..pat1EndC)
= cycled 1
* pattern2 IN [Mpat1EndC..Mpat2EndC)
= function of current Mrow, Mcol

pushReturn[];* compute end of patterns as branch condition
RBASE ← rbase[MpatX];
t←Mpatx←(Mpatx)+1;
t-(Mpat1EndC);* see if IN [0..pat1EndC)
branch[nxtMPat2, alu>=0],t←t;* goto[nextPat2, ~IN [0..pat1EndC)]

* IN [0..pat1EndC)
skpif[alu#0];* see if just initialized
skip, t ← curMPatLow ← 1c;* patX=0 ==> begin with one
t ← curMPatLow ← (curMPatLow) lsh 1;
MpatLow ← t;
(MpatX) - (20c);* see if we’ve overflowed into hi bits
skpif[ALU#0], t ← curMpatHi ← (curMpatHi) lsh 1;* left shift current MpatHi
t ← curMpatHi ← 1c;* we’ve been left shifting zero. set it to 1
MpatHi ← t;
branch[nxtMPatXit], t ← MpatX;

nxtMPat2:* see if IN[pat1EndC..pat2EndC)
t-(Mpat2EndC);
branch[nxtMPat3, alu>=0];* goto[nextPat3, ~IN[pat1EndC..pat2EndC)]

* IN [Mpat1EndC..Mpat2EndC)
curMPatHi ← t-t;
branch[nxtMPatXit], curMPatLow ← t-t;* Zero it

nxtMPat3:* code for next patter goes here
branch[nxtMPatXit];

nxtMPatXit:
link ← stack&-1;* restore return link, fix up rbase,
subroutine;
RBASE← rbase[defaultRegion];
return,t-(MlastPatC);* return w/ proper branch condition

* December 13, 1978 1:16 PM
MAP Test General Subroutines

getMPat:
* compute current pattern; return low bits in T
%
Currently there are two sets of patterns. The first set consists of a cycled one. The secod pattern produces unique values based on row and column.

pattern1: maintained by the nextPattern code -- it changes when "next pattern"
is called. pattern2 changes more frequently (for every column!)

pattern2: OR the quantity (row lshift 3) + column into curPattern.
Eg., if curPattern = 0, row = 22, col = 3 THEN result = 223
%
pushReturn[];
RBASE ← rbase[MpatX];
(Mpatx)-(Mpat1EndC);* see which pattern we are using
branch[getMP2,alu>=0];
t ← curMpatHi;
MpatHi ← t;
t ← curMpatLow;
branch[getMPxit], MpatLow ← t;

getMP2:* return pattern 2 or greater
(Mpatx)-(mpat2EndC);
branch[getMP3, alu>=0];
t ← curMpatHi;

RBASE ← rbase[defaultRegion];* fetch value of Mrow, Mcol from defaultRegion
MpatHi ← t;
t ← Mrow;
MsubrScr ← t;
t ← Mcol, RBASE ← rbase[rmForMapLoops];

MsubrScr ← lsh[MsubrScr, 10];* Mrow, Mcol separate bytes
t←t OR (curMpatLow);* curPattern,,column
t←t OR (MsubrScr);* curPattern,,row,,column
branch[getMPxit], MpatLow ← t;

getMP3:* add code for pattern 3 here
branch[getMPXit];

getMPXit:
link ← stack&-1;
subroutine;
return, RBASE← rbase[defaultRegion];

getMwait:* return current value of map Wait in T
RBASE ← rbase[rmForMapLoops];
return, t ← curMwait, RBASE ← rbase[defaultRegion];

* January 26, 1979 3:18 PM
resetMap:* when the machine powers up, the
* map may be in an arbitrary state.
* kick-start the automata by performing two fetches. Cope w/ "tag" bit by
* performing a reference that hits and then punch on the map 8 times to wake it up.

pushReturn[];
set[xmcrv, OR[mcr.fdMiss!, mcr.disHold!, mcr.disCF!, mcr.disBR!, mcr.noWake!]];

t←AND[xmcrv, 177400]C;* init MCR w/ virtually everything turned off
t ← t OR (AND[xmcrv, 377]C);
call[setMCR];

fetch ← r0;* perform the two fetches, separated by waits
t ← 40C;
call[longWait];
fetch ← r0;
t ← 40C;
call[longWait];

call[resetTag], t←r0;* reset our tag bit. use va=0

cnt ← 10s;* punch on the map a bunch of times
resetML:
noop;
rscr ← t-t;
call[writeMap], rscr2 ← t-t;
loopWhile[cnt#0&-1, resetML];

t ← mcr.disHold;* reset mcr for further map testing:
t ← t OR (mcr.noWake);* use disHold, noWake
call[setMCR];
B←FaultInfo’;

returnP[];

* January 1, 1979 3:11 PM
setTestSyn:
saveReturnAndT[Drlink, rscr];

t ← 62c;
call[longWait];
t ← mcr.noWake;
call[setMCR];
t ← rscr;* retrieve original value of t
rscr ← t-t;
rscr2 ← t-t;
call[setBR];
STORE ← r0, DBuf ← t;
loadTestSyndrome[t];
t ← 62c;
call[longWait];
t← FaultInfo’;
returnUsing[Drlink];

* February 9, 1981 9:50 AM
presetMap:* initialize map beginning at page 0
pushReturn[];
call[resetMap];
t ← FaultInfo’;* clear any pending wakeups
call[clearCacheFlags];* assure beingLoaded not set in cache
call[setMCR], t←t-t;* clear mcr

call[iMapPageCtrl];
pmL:
call[nextMpage];* get next page number
branch[pmLxit, alu=0];
noop;

call[xSetBRforPage];* expects t = page number
call[getMpage];* get page number in t
call[getXmapBase], rscr2 ← t;
rscr2 ← t + (rscr2);* Construct offset for situation where
rscr ← t-t;* there’s no module 0. xMapBase is set by
call[writeMap];* sGetConfig. Write map w/ page number.
branch[pml];

pmLxit:
returnP[];

getXmapBase: subroutine;
RBASE ← rbase[xMapBase];
return, t ← xMapBase, RBASE ← rbase[defaultRegion];

* February 9, 1981 9:43 AM
testMap:* Mcol = column, Mrow = row, Mpat = pattern,
* RSCR = cycles to wait, RSCR2 #0 => call resetMap
pushReturn[];* params and return link are saved. proceed...

q ← rscr;* save cycles to wait in Q for a while
rscr2 ← rscr2;
skpif[alu=0];* see if we should call resetMap
call[resetMap];* reset and write the map
call[setBRforMap];
rscr ← MpatHi;
rscr2 ← MpatLow;
call[writeMap];

rscr2 ← q;* now wait if required. retrieve wait count
rscr2 ← (rscr2) - (120C);* subtract 80 cycles for cost of readMap
skpif[alu>=0];
branch[testMapChk];

rscr2 ← (rscr2) + 1;* fast branch might be zero -- fix it
branch[., alu#0],rscr2 ← (rscr2) -1;* WAIT LOOP

testMapChk:
call[readMap];
t ← MpatLow;
t ← t # (rscr);
skpif[alu=0];
xTestMapErr3:* Mrow,Mcol = address. Q = time waited
error;* Mpat = expected, rscr = pipe3

t ← ldf[rscr2, 2, pipe4.dirtyShift];* rt justify the diry, wprotect bits from
t#(MpatHi);* the copy of Pipe4 that is in rscr2.
skpif[ALU=0];* T= wprotect,dirty from pipe4, MpatHi
xTestMapErr4:* is value of those bits as we wrote them.
error;* rscr2 contains a copy of pipe4, w/ low
* true bits inverted.

returnP[];

resetTag:* kick start the tag bit for our task.
* T = address to reference.

pushReturn[];
rscr ← t;
set[xmcrv, OR[mcr.noRef!, mcr.disHold!, mcr.disCF!, mcr.disBR!, mcr.noWake!]];
t ← AND[xmcrv,177400]C;
t←t or (AND[xmcrv, 377]C);* set MCR w/ noRef, disHold, disCF, disBR
call[setMCR];

DBuf ← rscr, STORE ← rscr;* write and read to cause a hit
call[longWait], t ← 10C;
fetch ← rscr;

returnP[];

* July 1, 1979 2:47 PM

xVacateCacheRow:* T = va. Cause all the columns of the cache entry for va to be vacant by setting the vacant bit. Use useMcrV to write each column in succession by using CFLAGS←.
pushReturnAndT[];
cnt ← 3s;
xVacateCacheRowL:
rscr ← cflags.vacant;
rscr2 ← cnt;
call[putCFmem], t ← stack;
loopUntil[CNT=0&-1, xvacateCacheRowL];
pReturnP[];

* May 14, 1981 3:12 PM
%
Read the map for position row, column and return with rscr = pipe3 and rscr2 = pipe4.

To read the map, vacate the cache entiries for the cache row that the va represents. There is one bit of overlap, va[15] , between the va bits that address the map column, va[9:15] and the bits that address the cache row, va[15:19]. Pass that bit as a parameter to the vacate CachRow procedure. Set the BR appropriately?

READ MAP TAKES ABOUT 80 CYCLES

%
readMap:
pushReturn[];
t ← mcr.disHold;
call[setMcr],t←t OR (mcr.noWake);* no wakeups please

call[setBrforMap];* read map for current row, column
RMap ← r0, call[waitForMapT];* don’t try to get data until it’s stable.

rscr ← not(Pipe3’);
call[xGetPipe4];* use subroutine since pipe4’ is complicated

rscr2 ← t;
returnP[];

writeMap: subroutine;* ENTER w/ rscr = 2 bits for tio, rt justified, rscr2 = MapBuf data
pushReturn[];
call[waitForMapT];
rscr ← lsh[rscr, 16];
tioa ← rscr;
t ← t-t;
writeMapX:
B←rscr2;* keept it on bmux early
map←t, MapBuf←rscr2;
call[waitForMapT];

returnP[];

waitForMapT: subroutine;* wait for mapbuf busy to go away.
noop;
t← pipe5;* clobber T
t← t and (pipe5.MbufBusy);
branch[.-2, alu#0];
return;

* February 10, 1981 5:18 PM
setBrforMap:* given Mrow and Mcol, construct a va and put it in the current base register. note that Mrow and Mcol contain up to 9 bits of VA apiece. This code is so arbitraryk because the choice of which bits in the VA map into the map ras/cas bits is rather complicated. The code reverses that mapping; ie., given ras and cas it generates the va. Naturally as the page size changes the mapping of the bits changes, too. See the diagram "Dorado Addressing" by Clark and McDaniel. Use a color printer.

mc[
storagePageSize, 400];
mc[
pageIs256C, 400];
mc[
pageIs1KC, 1000];
mc[
pageIs4KC, 4000];
mc[
Mrow.b0, b7];
mc[
Mrow.b1, b8];
mc[
Mrow.2thru8, b7,377 ];
mc[
Mcol.b0, b7];
mc[
Mcol.b1, b8];
mc[
Mcol.b5, b12];
mc[
Mcol.b6, b13];
mc[
Mcol.b7, b14];
mc[
Mcol.b8, b15];
mc[
Mcol.78, b14,b15 ];
mc[
Mcol.2thru8, 177 ];
mc[
Mcol.2thru4, b9,b10,b11 ];
mc[
Mcol.2thru6, b9,b10,b11,b12,b13 ];
set[
ras.b0justify, 10];
set[
ras.b1justify, 7];

pushReturn[];* with a drawing of the correspondance
t ← storagePageSize;* between various Dorado addresses, this
t - (pageIs256C);* might be understandable.
skpif[ALU=0];
branch[setBrForMap2];

* This code works for 256K map chips. Mrow.b0 and Mcol.b0 are always 0 unless we are using 256K map chips. Mrow.b1 and Mcol.b1 are always 0 unless we’re using 64Kk map chips. Mrow.b2thru8, Mcol.b2thru8 always contain legitimate map ras/cas values.

t← ldf[Mrow, 1, ras.b0justify];* bit 0 of map row for 256K chips
rscr← lsh[t, 11];* position in BrHi.
t← ldf[Mrow, 1, ras.b1justify];* bit 1 of map row for 256K and 64K chips
t← lsh[t, 7];* position it correctly and add to BrHi
rscr← (rscr) or t;* value we are constructing

t← ldf[Mrow, 6, 1];* all map chips use this range of values
rscr← t or (rscr);

t← ldf[Mcol, 1, ras.b0justify];* 256K chips’s cas contributes this bit
t← lsh[t, 10];
t← t or (rscr);
t← ldf[Mcol, 1, ras.b1justify];* bit 1 of map row for 256K and 64K chips
t← lsh[t, 6];* position it correctly and add to BrHi
t← t or (rscr); * BrHi is done. Whew!

rscr2 ← t-t;* compute BrLo
skpif[r even], Mrow;* add va[16] if required
rscr2 ← 100000C;
t ← (Mcol) and (Mcol.2thru8);* isolate low 6 bits of column
t ← lsh[t, 10];* correspnd to va[17:23];
branch[setBrForMapDoIt], rscr2 ← t or (rscr2);

setBrForMap2: * February 10, 1981 10:20 AM I don’t believe this works.
t ← storagePageSize;
t - (pageIs1Kc);
skpif[ALU=0];
branch[setBrForMap3];
t ← (Mrow) and (Mrow.b0);
rscr ← lsh[t, 3];* corresponds to va[4]
t ← (Mrow) and (Mrow.b1);
rscr ← (rscr) or t;* correspondsk to va[8];
t ← ldf[Mrow, 6, 1];
rscr ← (rscr) or t;* correspond to va[10:15]
t ← (Mcol) and (Mcol.b0);
t ← lsh[t, 2];* corresponds to va[5];
rscr ← (rscr) or t;
t ← (Mcol) and (Mcol.78);
t ← lsh[t, 10];* correspond to va[6:7]
rscr ← (rscr) or t;
t ← (Mcol) and (Mcol.b1);
t ← t rsh 1;
rscr ← (rscr) or t;* corresponds to va[9]

rscr2 ← t-t;
skpif[r even], Mrow;
rscr2 ← 100000c;* corresponds to va[16]
t ← (Mcol) and (Mcol.2thru6);
t ← lsh[t, 10];* correspond to va[17:21]
branch[setBrForMapDoIt], rscr2 ← (rscr2) or t;

setBrForMap3:
t ← storagePageSize;
t - (pageIs4Kc);
skpif[ALU=0];
error;* impossible configuration (neither 256 wd nor 1k nor 4k)

t ← ldf[Mrow, 6, 1];
rscr ← t;* correspond to va[10:15]
t ← (Mrow) and (Mrow.b1);
rscr ← (rscr) or t;* corresponds to va[8]
t ← (Mcol) and (Mcol.b8);
t ← lsh[t, 13];* corresponds to va[4]
rscr ← (rscr) or t;
t ← (Mcol) and (Mcol.b5);
t ← lsh[t, 7];* corresponds to va[5]
rscr ← (rscr) or t;
t ← (Mcol) and (Mcol.b7);
t ← lsh[t, 10];* corresponds to va[6]
rscr ← (rscr) or t;
t ← (Mcol) and (Mcol.b6);
t ← lsh[t, 6];* corresponds to va[7]
rscr ← (rscr) or t;
t ← (Mcol) and (Mcol.b1);
t ← t rsh 1;* corresponds to va[9]
rscr ← (rscr) or t;

t ← (Mcol) and (Mcol.2thru4);
rscr2 ← lsh[t, 10];* correspond to va[17:19]
skpif[r even], Mrow;
rscr2 ← (rscr2) or (100000c);* corresponds to va[16]
noop;

setBrForMapDoIt:
call[setBR];
returnP[];

* December 13, 1978 6:40 PM
xSetBRforPage:* given t = page number, set BR so that va=0
* will reference that virtual page. Assume 256 words/ page. CLOBBER T, rscr, rscr2
pushReturn[];
rscr ← t;
rscr2 ← t;
rscr ← rsh[rscr, 10];* rscr ← brHI = top 8 bits of page num
rscr2 ← lsh[rscr2, 10];* rscr2 ← brLO = (low 8 bits of page num) lsh 8
call[setBR];* rscr = brHI, rscr2 = brLO

returnP[];
* December 13, 1978 2:59 PM
%
xWriteMapPage
Write an entry into the map: Enter with t = virtual page index and with rscr = the real page that corresponds to that virtual page.

Clobber BR!
%
xWriteMapPage: subroutine;
pushReturn[];
rscr2 ← t;* move real page into MsubrScr
t ← rscr;
MsubrScr ← t;
%
a virtual page index maps into BR values by performing a left shift of 8. The high order 8 bits of the index shift into BrHi and the low order bits of the index shift into the high order 8 bits of BrLO
%

t ← rsh[rscr2, nBitsInPage];
rscr ← t;
rscr2 ← lsh[rscr2, nBitsInPage];
call[setBR];* setup BR so that addr "0" references virtual page
call[getMsubrScr];
rscr ← t-t;
call[writeMap], rscr2 ← t;

returnP[];

xReadMapPage: subroutine;* enter w/ t = page number, exit w/ t =
pushReturn[];* real page number, rscr = pipe4 (w/ all hi true bits)
call[xSetBrForPage];
call[waitForMapT];
RMap ← r0;
call[waitForMapT];
rscr ← not(Pipe3’);
call[xGetPipe4];
rscr2 ← t;* save pipe 4 till we can get it into rscr
t ← rscr;* t ← real page number
rscr ← rscr2;* rscr ← pipe4 (w/bits properly inverted)
returnP[];

* May 29, 1979 2:39 PM
%
xZeroMapWrite zero into all the entries of the map (ignore wp, dirty)
%
xZeroMap:
pushReturn[];
t ← (OR[mcr.disHold!,mcr.noWake!]C);
B←FaultInfo’[];
call[setMCR];

call[iMapPageCtrl];

xZeroMapL:
call[nextMpage];
skpif[ALU#0];
branch[xZeroMapXit];
rscr ← t-t;
call[xWriteMapPage];
branch[xZeroMapL];
xZeroMapXit:
returnP[];


* June 28, 1979 1:13 PM
xGetConfig: subroutine;* return w/ t = maxBrHi.
%
Set sMaxBrHi, a register that contains the last valid BrHi +1.
Set
xMapBase, a register that contains the offset that PresetMap adds to real page numbers when initializing the map. xMapBase enables the storage diagnostics to run with contiguous storage modules that need not begin with module 0.
%
pushReturn[];

call[xCountModules];
sNmodules ← t;
skpif[alu#0];
error;* no modules!!!
noop;

call[XgetSnModules];* initialize sNmodules
call[xGetICtype];* T: 1=>4K, 4=>16K, 16=>64K
%
Note: the "ic type" is a number that happens to be the correct value for sMaxBrHi, given only one module of that type. Ie., If there are 3 modules, sMaxBrHi ← 3 * icType. Remember that sMaxBrHi is one greater than the last valid value for BrHi in this configuration.
%
xConfigBrHi:
call[XgetSnModules], rscr ← t;* Remember icTyp in rscr.
t ← t-1;* begin w/ nModules-1
cnt ← t;* rscr contains our increment for sMaxBrHi
t ← t-t;
loopUntil[cnt=0&-1, .], t ← t + (rscr);* multiply by adding
sMaxBrHi ← t;* Set sMaxBrHi.
%
(set xMapBase) Now we must find the real page number for the first page in storage. Usually the map initialization code sets map[i] ← i. However, if we are missing modules this won’t work. Furthermore, this code only works when the installed modules are contiguous. Ie., M2, M3 is a valid configuration while M0, M3 is not valid (where Mi referes to memory module i). The restriction to contiguous modules occurs because the presetMap code doesn’t recognize when it crosses a "module boundary" when it writes the map. At module boundaries it should check to see if the module really exists!
%
xConfigMapBase:
t ← rscr;* remember, rscr contains the ictype
rscr2 ← t-t;* now right shift ictype,,0 by the number
t ← rcy[t,rscr2, nBitsInPage];* of address bits in a map page. This gives
rscr ← t;* the "map increment" for missing modules.
rscr2 ← not(Config’);
t ← (rscr2) and (config.m0);
skpif[ALU=0];
branch[xConfigMBxit], t ← r0;* Module 0 is in place

(rscr2) and (config.m1);
skpif[ALU=0];
branch[xConfigMBxit], t ← rscr;* missing only one module

(rscr2) and (config.m2);
skpif[ALU=0];
branch[xConfigMBxit], t ← (rscr) + (rscr);* missing module 0, module 1

(rscr2) and (config.m3);
skpif[ALU=0], t ← (rscr) + (rscr);* t ← 2 * mapIncrement
branch[xConfigMBxit], t ← t + (rscr);* t ← t + mapIncrement

error;* can’t find any modules. There’s been a serious error.

xConfigMBxit:
xMapBase ← t;* Set xMapBase.

RBASE ← rbase[sMaxBrHi];
t ← sMaxBrHi, RBASE ← rbase[defaultRegion];
xGetCLXit:
ReturnP[];

* February 9, 1981 10:14 AM
%
xGetMapICsThis routine initializes the RM locations xPageEndHi,, xPageEndLo so that the loop routines will work properly for the current map ic size.

Assume 1510=DMUX address for three consecutive muffler values that define the signals, MapIs16K, MapIs64K, MapIs256K.

EXIT w/
xEndPageHi,,xEndPageLoIC size
0,,4000016K
1,,064K
4,,0256K
%

set[MapIs16K, 1510];
* assume this address muffler correctly.

xGetMapICs:
pushReturn[];
t← AND[MapIs16K, 177400]C;
call[xRWDmux], rscr2← t← t or (AND[MapIs16K, 377]C);
branch[xMapIs16K, ALU<0];
noop;* for placement
call[xRWDmux], rscr2← t← (rscr2)+1;
branch[xMapIs64K, ALU<0];
noop;* for placement
call[xRWDmux], rscr2← t← (rscr2)+1;
skpif[alu<0];
xGetMapICErr:* none of the muffler values we
error;* tried was non-zero.

* Map is 256K
xEndPageLo←a0;
t←4c;
xEndPageHi←t;
t← 1000c;
xChipEndRasCas← t;

xGetMapICRtn:
returnP[];

xMapIs16K:
xEndPageHi← a0;
t← 40000c;
xEndPageLo← t;
t← 200C;
branch[xGetMapICRtn], xChipEndRasCas← t;

xMapIs64K:
t← xEndPageLo← a0;
xEndPageHi← t+1;
t← 400C;
branch[xGetMapICRtn], xChipEndRasCas← t;
* September 22, 1981 9:51 AM
%
XgetSnModulesreturn sNmodules
xGetICtypereturn t = icType = BrHi offset per module
xCountModulesreturn t = num storage modules, set sNmodules, too.
%
XgetSnModules: subroutine;
RBASE ← rbase[rmForStoreLoops];
return, t ← sNmodules, RBASE ← rbase[defaultRegion];
%
This routine uses Config to determine the chip size used in the storage boards. The value it returns describes the maximum BrHi +1 for a single module of the storage boards, given the chip size. Ie., If there are 3 modules, 3 * (number returned in T from calling this routine) is the maximum BrHi +1 for the current memory configuration.
%

xGetICtype:
subroutine;* RETURN T =(1=>4k, 4=>16K, 16=64K, 64 =>256K)
pushReturn[];

rscr ← not(Config’);

rscr ← ldf[rscr, config.icTypeSZ, config.icTypePos];
PD ← rscr;
skpif[ALU#0], (rscr) # (1c);* test against 1 incase it’s not zero
branch[xGetIcRtn], t ← 1c;* config.icType=0 ==> 4K chips

skpif[ALU#0], (rscr) # (2c);* test against 2 incase it’s not zero
branch[xGetIcRtn], t ← 4c;* config.icType=1 ==> 16K chips

skpif[ALU#0], t ← 100c;* set to 256K chips here
branch[xGetIcRtn], t ← 20c;* reset to 64K chips if config.icType=2

xGetIcRtn:
returnP[];

* January 12, 1979 3:22 PM

xCountModules:
subroutine;* return T=num storage modules. set sNmodules!
pushReturn[];

rscr ← not(Config’);
noop;

rscr ← ldf[rscr, config.modSZ, config.modPOS];* modules rt justified

t ← config.modSZC;* set cnt to (num bits in module field) -1
cnt ← t;

t ← t-t;
xCountML:
skpif[r even], rscr;
t ← t + 1;
rscr ← (rscr) rsh 1;
loopuntil[cnt=0&-1, xCountML];

sNmodules ← t;
returnP[];

* January 25, 1979 5:42 PM
%
Code for returning values in T.
%
getMsubrScr: subroutine;
RBASE ← rbase[mSubrScr];
return, t ← MsubrScr, RBASE ← rbase[defaultRegion];

xGetPipe4: subroutine;* return Pipe4 with all inverted bits
t ← not(pipe4’);* fixed up such that a ’1’ bit implies
t ← t # (pipe4.sexChange0);* the "true" condition
return, t ← t # (pipe4.sexChange1);
xGetPipe2: subroutine;
return, t ← not(pipe2’);
xGetNumFlts: subroutine;
t ← not(pipe2’);
return, t ← ldf[t, pipe2.nFaultsSize, pipe2.nFaultsShift];
* December 18, 1978 10:20 AM
% exerciser for map: to be used when bringing up new boards
%

xBoardLoop: top level;
RBASE ← rbase[defaultRegion];
call[setMbase], t ← r0;
rscr ← t-t;
call[setBR], rscr2 ← t-t;
t ← mcr.disHold;
t ← t OR (mcr.noWake);
call[setMCR];
t ← 1c;
stkp ← t;
xBdL:
call[xUp];
branch[.-1];
xUp: subroutine;
pushReturn[];
RBASE ← rbase[Mwait];
call[longWait], t ← Mwait;
t ← MwriteVal;
Map ← Maddr1, MapBuf ← t;
call[longWait], t ← Mwait;
t ← not(MwriteVal);
Map ← Maddr2, MapBuf ← t;
noop;
xup2:
call[longWait], t ← Mwait;
RMap ← Maddr1;
call[longWait], t ← Mwait;
Mread1 ← not(Pipe3’);
noop;
RMap ← Maddr2;
call[longWait], t ← Mwait;
Mread2 ← not(Pipe3’);
RBASE ← rbase[defaultRegion];
returnP[];

* February 6, 1981 2:06 PM

xRWDmux: pushReturn[];
rscr← 14C;
xDmuxL:
T← T+(MidasStrobe← T);* Shift address bit from B[4]
Noop;
rscr← (rscr)-1;
Branch[xDmuxL, ALU#0];
T← ALUFMem, rscr, Branch[.+2, R>=0]; * T← DMuxData
UseDMD;
returnPandBranch[t];



knowRbase[defaultRegion];

top level;

mapSubrsDone: noop;