*----------------------------------------------------------- Title[InitMem.mc...November 23, 1982 12:56 PM...Taft]; *** Pilot-only version *** * Memory system initialization *----------------------------------------------------------- % Entry point: InitMap Cold start: map and main storage initialization (name is an historical artifact). After initialization, InitMap branches to the external label StartEmulator. InitMap code assumes that CacheA, CacheD, and the map automata have already been put into a good state (by bootstrap initialization), but assumes nothing about the contents of the map or main storage. It zeroes all real storage in order to clear out any lurking bad parity. It maps virtual addresses to real storage such that all real storage is compacted in VM (usually at the bottom), and marks all other VM vacant. As a side-effect, it computes VirtualBanks and RealPages, for the benefit of emulators. If no real storage is present, it breaks at NoStorage. This version of the code assumes 256-word pages, but can cope with any map and main storage configuration. % Set[logWordsPerPage, 10]; TopLevel; Set[XTask, IP[EMU]]; * Register usage -- bank shared with Ethernet output registers SetRMRegion[EORegs]; * Reserve[xx]; * Registers defined in RegisterDefs.mc * RVN[VirtualBanks]; * RVN[RealPages]; Reserve[Add[And[IP[RealPages], 17], 1]]; RVN[PgsPerMod]; * Pages per storage module RVN[ModMask]; * Mask of modules present RVN[ITemp0]; * Temporaries RVN[ITemp1]; RVN[ITemp2]; Reserve[1]; * Ensure there is at least one register left RVRel[ITemp17, 17]; *----------------------------------------------------------- * Cold start initialization. * Initially started here by "Initial" (second-stage bootstrap). * Restarted here by Baseboard on 2-button boot. *----------------------------------------------------------- InitMap: At[InitMapLoc], Call[TasksOff]; * Do an I/O Reset RBase← RBase[ITemp0]; B← FaultInfo'; * clear faults T← mcr.noWake; * disable fault task wakeups LoadMCR[T, T]; Call[WaitForMapBuf]; * Set TestSyndrome register to normal state (error correction on) MemBase← IOBR, T← A0; BrHi← T; BrLo← T, Call[FetchGetsT]; * need to be sure store will hit T← MD, Store← T, DBuf← tsyn.ecOn; * DBuf← data LoadTestSyndrome; * TestSyn← DBuf Call[WaitForMapBuf]; TaskingOn; *----------------------------------------------------------- * Map pre-initialization for cold start. * Set the map one-to-one with real storage (without regard to the * real storage configuration), in preparation for flushing the cache. *----------------------------------------------------------- Call[GetMemConfig]; ITemp1← T← A0, Call[BeginEnumerateMap]; Map1to1Loop: ITemp0← A0, Call[IWriteMap]; * Dirty=0, WP=0, RP = VPage mod 2↑16 SCall[NextMapEntry]; ITemp1← (ITemp1)+1, Branch[Map1to1Loop]; *----------------------------------------------------------- * Cache flush and map clear. * Data in the cache is flushed to memory arbitrarily. * This may result in flushing into nonexistent storage, but no matter. *----------------------------------------------------------- CacheFlush: ITemp1← T← A0, Call[BeginEnumerateMap]; CacheFlushLoop: * Flush all munches in this page ITemp0← A0, Cnt← 17S; ITemp0← Flush← ITemp0, Carry20, Branch[., Cnt#0&-1]; * Set the map entry to vacant Nop; ITemp0← T-T-1, Call[IWriteMap]; * Dirty = 1, WP = 1, RP = 0 SCall[NextMapEntry]; Branch[CacheFlushLoop]; *----------------------------------------------------------- * Map and storage initialization. * Map all existing real memory one-to-one into virtual memory, and zero it. *----------------------------------------------------------- ITemp1← T← A0, * Init real page #, virtual bank # Call[BeginEnumerateMap]; * Current module exhausted, find the next one. FindModule: ModMask← (ModMask) LSH 1, Branch[MapModule, R<0]; T← PgsPerMod, Branch[InitMemDone, ALU=0]; ITemp1← (ITemp1)+T, Branch[FindModule]; * Skip nonexistent real pages MapModule: T← (1S)-(PgsPerMod); * Init page count in module ITemp2← T; * Continue mapping virtual pages into the current module. * ITemp1 = real page number * ITemp2 = -(remaining pages in current module)-1 MapModuleCont: ITemp0← A0, Call[IWriteMap]; * Write map entry; WP and Dirty = 0 T← 377C; T← ITemp0← A0, Cnt← T; * Zero out the page ITemp0← (Store← ITemp0)+1, DBuf← T, Branch[., Cnt#0&-1]; ITemp1← (ITemp1)+1, * Increment real page number SCall[NextMapEntry]; * Increment virtual page number ITemp2← (ITemp2)+1, * +1 return; decrement (negative) page count DblBranch[MapModuleCont, FindModule, R<0]; Nop; * +2 return: ran out of virtual memory ?? *----------------------------------------------------------- * Now enable fault reporting and go run the emulator! * For now, do not enable fault reporting of Single Errors. *----------------------------------------------------------- InitMemDone: B← FaultInfo'; * Clear faults T← mcr.noReportSE; * Normal MCR value LoadMCR[T, T]; Call[WaitForMapBuf]; Branch[StartEmulator]; *----------------------------------------------------------- GetMemConfig: * Read the map and storage configuration, and set these registers: * VirtualBanks = size of virtual memory, in units of 64K words * RealPages = size of real memory, in pages * PgsPerMod = number of pages per module * ModMask = bit mask of modules present (B0=1 => module 0 present, etc.) * Breakpoints at NoStorage if no storage modules are present. * Clobbers T, ITemp0, ITemp1, ITemp17 *----------------------------------------------------------- Subroutine; ITemp0← Link; TopLevel; T← 1400C; T← ITemp1← T OR (112C); Call[SetDMuxAddress]; * Read DMux[1512] = MapIs256K ITemp17, Branch[MapIs256K, R<0]; VirtualBanks← 400C; T← (ITemp1)-1, Call[SetDMuxAddress]; * Read DMux[1511] = MapIs64K ITemp17, Branch[GotMapConfig, R<0]; VirtualBanks← 100C, Branch[GotMapConfig]; * Assume MapIs16K MapIs256K: VirtualBanks← 2000C; GotMapConfig: ModMask← NOT (Config'); T← LDF[ModMask, 2, 2]; * Storage chip size = 2↑(12 + 2*T) T← DPF[T, 2, 11]; * ShC count ← 2*T RealPages← A0, ShC← T; ModMask← LSH[ModMask, 10]; * Left-justify the module-present bits ModMask← T← (ModMask) AND (170000C); ITemp1← T, Branch[NoStorage, ALU=0]; PgsPerMod← 400C; * 4K chips give 400B pages/module PgsPerMod← T← ShiftNoMask[PgsPerMod]; * LCY[R, R, 2*n] ITemp1← (ITemp1)+(ITemp1), Branch[.+2, R>=0]; * Count the modules RealPages← (RealPages)+T, FreezeBC; Link← ITemp0, Branch[.-2, ALU#0]; Subroutine; PD← ModMask, Return; *----------------------------------------------------------- * No storage modules are present. *----------------------------------------------------------- NoStorage: Branch[.], Breakpoint; *----------------------------------------------------------- * EnumerateMap: Perform operation on every entry in the map * Calling sequence: * * T← <first virtual bank #, normally 0>, Call[BeginEnumerateMap]; * Loop: <code to be executed for each entry>; * SCall[NextMapEntry]; * Branch[Loop]; * <code reached when map is exhausted>; * * Enter: MemBase = BR to use for enumeration * VirtualBanks set up * Exit: BR addresses word 0 of page corresponding to map entry * T = 0 * Clobbers T, ITemp17 *----------------------------------------------------------- Subroutine; BeginEnumerateMap: ITemp17← A0, Branch[NextMap1]; NextMapEntry: T← LShift[1, logWordsPerPage]C; * Let the memory system do the add! DummyRef← T, T← MD; ITemp17← VALo; T← VAHi; NextMap1: BRLo← ITemp17; PD← (BRHi← T)-(VirtualBanks); T← A0, Return[ALU=0]; *----------------------------------------------------------- IWriteMapFlags: * Write map flags without disturbing real page * Enter: ITemp0 = WP and Dirty bits * Current BR contains VA for map entry to be written * Clobbers ITemp1, Q. *----------------------------------------------------------- Subroutine; ITemp1← A0, Q← Link; TopLevel; RMap← ITemp1, Call[WaitForMapBuf]; * Read current map entry ITemp1← NOT (Map'), Branch[IWriteMap1]; *----------------------------------------------------------- IWriteMap: * Write map entry * Enter: ITemp0 = WP and Dirty bits * ITemp1 = real page number * Current BR contains VA for map entry to be written * Clobbers Q. *----------------------------------------------------------- Subroutine; Q← Link; TopLevel; IWriteMap1: TIOA← ITemp0, Call[WaitForMapBuf]; Map← 0S, MapBuf← ITemp1; Link← Q, Branch[WaitForMapBuf]; *----------------------------------------------------------- WaitForMapBuf: * Wait for map operation to complete * Clobbers nothing *----------------------------------------------------------- Subroutine; PD← T-T-1; PD← PRef, Branch[., ALU<0]; * MapBufBusy is sign bit Return;