//D1Reset.bcpl -- hardware reset overlay to setup Runxx enables, zero
// memories, and other stuff.
//	Last edited: 30 April 1980

//**Ran into "TOO MANY NAMES IN SAME SCOPE" error in compiling, so had
//**to extract "didReset" from MCommon.d and d1dmux.d symbols.

get "d1.d"
manifest [ get "d1pe.d" ]
manifest [ get "d1regmem.d" ]
manifest [ get "d1instrs.d" ]
//manifest [ get "d1dmux.d" ]
manifest [ dCTD=#11; dCTASK=#7; dREADY=#17; dTOPE=#13; dNEXT=#10
	dCLKRUN=#110; dESTAT=#164 ]
//get "mcommon.d"
manifest [ didReset = #2000 ]

external [
// OS
	Zero; SetBlock

// MINIT0
	@ACTS

// MASM
	Wss; ResetsCSS; @WssCSS; WssCS1; ResetsCS1

// MDATA
	MIRPE; MCTimeOut; CheckStoppedGlitches

// MRGN
	UpdateDisplay

// MMPRGN
	UpdateMPDValues

// MMENU
	@WsMarkA; CreateAction; ItemStream; MarkMenus

// MCMD
	WnsCSS; WnsCSSD; QuitCmdOverlay; FormCmdMenu; SetAbort; CmdAbort
	ErrorExit
	CmdCS1; CmdCommentStream; LoadDone; PassiveOnly; @CmdAbortAct

// MDATA
	@LowAddress; @HighAddress; @BitsChecked; @AddrIncrement

// MGO
	@CantContinue

// MPRINS
	NWss

// MPATTERN
	@PATTERN

// MTEST
	@NDWords

// D1I0
	DMuxSelect; @DMuxTab; HWStatus

// D1I1
	@LDRMEM

// D1ASM
	@SelectTask; @Xct; @XctL16BP; @XctLFF; @DoStrobe
	@XctL16C; @XctL16T; @XctL16Q; @SetALUF; @SetRSTK
	LoadMIR; LoadDMD; ReadDMux

// D1TABLES
	@MEMLEN

// D1RES
	DoNOPs

// D1REG
	PutRegData

// D1MEM
	PutMemData; MGetMemData; MPutMemData
	@SaveMCR; @SaveSRN; @SaveT; @SaveQ; @SaveTPC; @SaveLINK; SaveTIOA

// D1VM
	SetVirtP

// D1CONFIG
	log2pgsize; log2rows; AColumnShift; MapICcode; IMXmask
	HaveControl; HaveMemC; HaveMemD; HaveMemX; HaveIFU

// Defined here
	D1Reset
]

manifest
[	rRunRefresh = 1; rRefreshPeriod = 3; eIMlh = 5; eIMrh = 7
	eIOB = 9; eRAM = 11; eMem = 13; eMD = 15; eMIRdebug = 17
	zRM = 19; zSTK = 21; zIFUM = 23; zIM = 25; zMemCD = 27; zMAP = 29
]


let D1Reset(nil,nil) = valof
[	SetAbort(lv CmdAbort,nil)
	ACTS!0 = CreateAction("Do-it",lv ResDoIt,0)
//Run enables
	DefRes("RunRefresh",rRunRefresh)
	DefRes("RefreshPeriod",rRefreshPeriod)
//PE enables
	DefRes("IMlh",eIMlh);	DefRes("IMrh",eIMrh)
	DefRes("IOB",eIOB);	DefRes("RM/T/STK",eRAM)
	DefRes("Mem",eMem);	DefRes("MD",eMD)
	DefRes("MIRdebug",eMIRdebug); ACTS!(eMIRdebug+1) = false
//Memory zeroing
	DefRes("RM",zRM);	DefRes("STK",zSTK)
	DefRes("IFUM",zIFUM);	DefRes("IM",zIM)
	DefRes("MemCD",zMemCD);	DefRes("MAP",zMAP)
//MAP reset is too slow to do ordinarily
	ACTS!(zMAP+1) = false
	resultis D1ResMenu
]


and DefRes(String,X) be
[	ACTS!X = CreateAction(String,lv DoResAct,X)
	ACTS!(X+1) = true
]


and DoResAct(X,MBUnion,nil) be
[	ACTS!(X+1) = not ACTS!(X+1)
	FormCmdMenu()
]


and ShowRAct(X,lvPostS,S) be
[	if ACTS!(X+1) do
	[ Wss(ItemStream,"not-"); Wss(S,rv lvPostS)
	  Wss(S,rv ACTS!X); rv lvPostS = " "
	]
	WsMarkA(ACTS!X)
]


and D1ResMenu(S,nil) be
[	let PostS = "Run: "
	ResetsCSS(); ResetsCS1()
	WsMarkA(CmdAbortAct); WsMarkA(ACTS!0)
	let PostS = "Init: "
	Wss(ItemStream,"  Init: "); MarkMenus(0)
	for I = zRM to zMAP by 2 do ShowRAct(I,lv PostS,CmdCommentStream)
	MarkMenus(0); Wss(ItemStream,"Run: "); MarkMenus(0)
	let PostS = "  Enable: "
	for I = rRunRefresh to rRefreshPeriod by 2 do
		ShowRAct(I,lv PostS,CmdCommentStream)
	let PostS = "PE enable: "
	MarkMenus(0); Wss(ItemStream,PostS); MarkMenus(0)
	for I = eIMlh to eMIRdebug by 2 do ShowRAct(I,lv PostS,CmdCS1)
]

and ResDoIt(nil,MBUnion,nil) be
[	ResetsCSS(); ResetsCS1()
	WssCSS("...")
//Enclosure to limit number of names
	[ let Time = 1	//1.53 sec measured for null Reset
			//0.15 sec measured for RM/STK reset
	  if HaveIFU & ACTS!(zIFUM+1) then Time = Time+1
	  if HaveControl & ACTS!(zIM+1) then
		Time = Time+(selecton IMXmask into
		[ default: 3	//2.52 sec measured
		  case #17777: 5
		  case #37777: 10
		] )
	  if ACTS!(zMemCD+1) then	//2.14 sec measured for both
		[ if HaveMemC then Time = Time+1
		  if HaveMemD then Time = Time+(selecton log2rows into
		  [ default: 1
		    case 7: 3
		    case 8: 7
		  ] )
		]
	  if HaveMemX & ACTS!(zMAP+1) then
		Time = Time+(selecton MapICcode into
		[ default: 9	//8.75 sec measured
		  case 3: 35
		  case 4: 140 ] )
	  if Time > 5 then
	  [ WnsCSSD(Time); WssCSS(" sec...")
	  ]
	  UpdateDisplay()
	]
//Indicate cannot continue from breakpoint
	CantContinue = CantContinue % didReset
	PassiveOnly = false
	let RunControl =
		RunEnable+ECLup+(ACTS!(rRunRefresh+1) & RunRefresh)+
		((not ACTS!(rRefreshPeriod+1)) & EnRefreshPeriodx)+IOResetx
	HWStatus>>HWStatus.RunControl = RunControl
//IOReset stays on until after ResetControl is called
	LoadDMD(RunControl & not IOResetx)
//Compute ESTAT bits for error-check later
	let HaltEnables =
		(ACTS!(eIMlh+1) & IMlhPEena)+
		(ACTS!(eIMrh+1) & IMrhPEena)+
		(ACTS!(eIOB+1) & IOBPEena)+
		(ACTS!(eRAM+1) & RAMPEena)+
		(ACTS!(eMem+1) & MemoryPEena)+
		(ACTS!(eMD+1) & MdPEena)+
		(ACTS!(eMIRdebug+1) & MIRDebugena)
	DMuxSelect = DMuxTab
//Establish error-halt enables, build HWStatus>>HWStatus.MIRdebugging
//and HWStatus>>HWStatus.HaltConditions, and clear IMAddr0 to 2
	PutRegData(ESTATx,lv HaltEnables)
//Clear direct IM test stuff, clear/set MIRdebug
	LoadDMD(IMDataA); LoadDMD(IMDataB); LoadDMD(IMDataC)
//The theory on Reset is that all registers and memories not loaded by
//a microprogram are always reset, while those loaded by microprograms
//appear in the Reset menu and are conditionally reset.  An exception is
//ALUFM which is not reset; also ReadAllRegs() cannot be called because
//it smashes SaveALUFM16 and SaveALUFM0 which might be relevant if a
//reset is being carried out while a microprogram is loaded.
	DoNOPs(31)		//Let things settle down (?)
//Reset error counters
	Zero(MIRPE,2); CheckStoppedGlitches!0,MCTimeOut!0 = 0,0
	XctL16Q(1B); Xct(SetALUF(LAF0,16B))	//ALUFM[16]←NOT A
	XctL16Q(25B); Xct(LAF0)			//ALUFM[0]←B
//Reset memory
	XctL16T(0); Xct(SRNFT)	//Select processor's private pipe entry
	SaveMCR,SaveSRN = NoWake,0
	PutRegData(TESTSYNx,table [ 200B ] )	//Turn on error-corr.
//Make sure Asrn ge 2 after power up by issuing two IOFetch←'es
	SelectTask(2)
	Xct(IOFET); DoNOPs(10)
	Xct(IOFET); DoNOPs(10)
//Reset T, TIOA, control section (LINK, TPC, NOTIFY, TASKINGON),
//Display controller, and IFU.  MD reset conditional on ACTS!(zMemCD+1)
	ResetControl()
//MAP reset?
	if HaveMemX & ACTS!(zMAP+1) do
	[ SelectTask(0); XctL16T(NoWake); Xct(MCRFT)
//TIOA[0:1] set to Dirty, use whatever BR currently selected
	  XctL16T(0); Xct(BRLOFT); XctL16Q(40000B); Xct(TIOAFQ)
//Load MAP words with Dirty and pointer to corresponding absolute page
	  let mshift = 16-log2pgsize
//Right-shift double-precision Map length 16-log2pgsize
	  let BRHIlast = (MEMLEN!(MAPx+MAPx) lshift log2pgsize)+
		(MEMLEN!(MAPx+MAPx+1) rshift mshift)
	  for I = 0 to BRHIlast-1 do
	  [ XctL16T(I); Xct(BRHIFT); let Z = I lshift log2pgsize
	    for J = 0 to (1 lshift mshift)-1 do
	    [ XctL16T(J lshift log2pgsize); Xct(NOOP)
	      XctL16Q(J+Z); Xct(MAPTQ)
	    ]
	  ]
	]
	if HaveMemC & ACTS!(zMemCD+1) do
	[ let AVec,DVec = vec 1,vec 4
	  AVec!0,DVec!0 = 0,0
//Reset CACHEA to map first 4K/16K of storage
//Since the left-most two bits of CACHEA address are the column,
//the first column winds up being loaded with 0 in VA[4:21], second
//with 1, third with 2, and fourth with 3.
	  for I = 0 to MEMLEN!(CACHEAx+CACHEAx+1)-1 do
	  [ AVec!1 = I; DVec!1 = (I rshift log2rows) lshift (log2rows+4)
	    PutMemData(CACHEAx,DVec,AVec)
	  ]
//Zero BR
	  XctL16T(SaveMCR); Xct(MCRFT); XctL16T(0); Xct(SRNFT)
	  for I = 0 to MEMLEN!(BRx+BRx+1)-1 do
	  [ XctLFF(LMB0,I); Xct(BRLOFT); Xct(BRHIFT)
	  ]
//Zero CACHED
	  if HaveMemD do
	  [ XctL16T(NoWake); Xct(MCRFT); XctL16Q(0); Xct(NOOP)
	    for I = 0 to MEMLEN!(CACHEDx+CACHEDx+1)-1 do
	    [ XctL16T(I); Xct(STORETQ)	//These should all be hits?
	    ]
	  ]
	]
	XctL16T(SaveMCR); Xct(MCRFT)	//Reset MCR
//Reset RM?
	if ACTS!(zRM+1) do
	[ for I = 0 to (MEMLEN!(RMx+RMx+1)-1) rshift 4 do
	  [ XctLFF(LRB0,I); XctL16C(LRM0,-1)
	    for J = 1 to 15 do Xct(SetRSTK(LRM0,J))
	  ]
	  LoadDone = false
	]
//Reset STK?
	if ACTS!(zSTK+1) do
	[ SelectTask(0)
	  for I = 0 to MEMLEN!(STKx+STKx+1)-1 do
	  [ XctL16Q(I); Xct(STKPFQ); XctL16C(WSTACK,-1)
	  ]
	  XctL16Q(0); Xct(STKPFQ)
	]
//Reset IM?
	if HaveControl & ACTS!(zIM+1) do
	[
//Note that neither the VM nor the symbol table is reset; RunProg or
//Dtach has to be used to reset these, although using existing symbols
//or VA's is meaningless after an IM reset.
	  LoadDone = false; SetVirtP(false)
//Initialize IM to LocBranch[.], breakpoint, nop in FF (=77B)
	  for I = 0 to IMXmask do
	  [ XctL16C(LLINK,I); XctL16C(LIMLFB,104B)	//ASEL←4, BSEL←1
//FF←77, JCN←200+(I & 77)
	    XctL16C(LLINK,I); XctL16C(LIMRFB,37600B+(I & 77B))
	  ]
//Set return instruction for CALL to be RETURN, FREEZEBC, BRKP
//(= RSTK[0] ALUF[17] BSEL[0] LC[0] ASEL[4] BLK[0] FF[76] JCN[107] BRKP)
	  PutMemData(IMXx,table [ 000002B; 007621B; 170000B ] ,
		table [ 0; CallRetAddr ])
	]
//Reset IFUM?
	if HaveIFU & ACTS!(zIFUM+1) do
	[ Xct(IFRES); LoadDone = false
	  for I = 0 to 3 do
	  [ XctL16Q(100000B+(I lshift 8)); Xct(ISEVFQ)
//IFaddr and PackedAlpha = 0 in IFUMLH; Sign=0, Length'=2, RBaseB'=0,
//MemB=0, TPause'=1, TJump'=1, and N=17 in IFUMRH.
	    for J = 0 to 377B do
	    [ XctL16Q(J lshift 8); Xct(BRKINSFQ)
	      XctL16Q(0); Xct(IFHFQ); Xct(RQ)
	      XctL16Q(75077B); Xct(IFLFQ); Xct(RQ)
	    ]
	  ]
	]
//Reset registers again twice
	ResetControl(); ResetControl()
	ReadDMux()
	Zero(LowAddress,2)
	SetBlock(HighAddress,-1,2)
	SetBlock(BitsChecked,-1,NDWords)
	AddrIncrement!0,AddrIncrement!1 = 0,1
//Check for Reset errors
	let SomeError,prelim = false,""
	ResetsCSS(); ResetsCS1()
	[ let ActEnables = (DMuxTab+dCLKRUN)>>nib2
	  RunControl = RunControl & #17
	  if ActEnables ne RunControl do
	  [ WssCSS("Run-enables = "); WnsCSS(ActEnables)
	    WssCSS(", should be "); WnsCSS(RunControl)
	    SomeError,prelim = true,", "
	  ]
	]
	if (MIRPE!0 ne 0) % (MIRPE!1 ne 0) do
	[ WssCSS(prelim); WssCSS("MIR P.E.'s occurred")
	  SomeError,prelim = true,", "
	]
	PATTERN = (DMuxTab!dESTAT & Henables) xor	//actual enables
		HaltEnables				//desired enables
	if PATTERN ne 0 do
	[ WssCSS(prelim); WssCSS("PE enable errs:")
	  NWss(" RAM",RAMPEena)
	  NWss(" Mem",MemoryPEena)
	  NWss(" MD",MdPEena)
	  NWss(" IMrh")
	  NWss(" IMlh")
	  NWss(" IOB")
	  NWss(" MIRdebug")
	  SomeError = true
	]
	if HaveControl do
	[ prelim = "Failed to zero "
	  let nprelim = ", "
	  if DMuxTab!dCTD ne 0 do
	  [ WssCS1(prelim); WssCS1("CTD"); prelim,SomeError = nprelim,true
	  ]
	  if DMuxTab!dCTASK ne 0 do
	  [ WssCS1(prelim); WssCS1("CTASK"); prelim,SomeError = nprelim,true
	  ]
	  if (DMuxTab!dREADY & 77777B) ne 0 do
	  [ WssCS1(prelim); WssCS1("Ready"); prelim,SomeError = nprelim,true
	  ]
	  if (DMuxTab!dTOPE & 77777B) ne 0 do
	  [ WssCS1(prelim); WssCS1("TOPE"); prelim,SomeError = nprelim,true
	  ]
	  if DMuxTab!dNEXT ne 0 do
	  [ WssCS1(prelim); WssCS1("Next"); SomeError = true
	  ]
	]
	UpdateMPDValues()
	if SomeError then ErrorExit("")
	QuitCmdOverlay()
]


//This is a total reset, superset of stuff in SetupIMA.
and ResetControl() be
[	let rIFU,rLINK,rMD,rT,rTIOA = -1,-1,-1,-1,-1
	LoadMIR(LDRMEM+TON)		//Do this one with Freeze off
	DoStrobe(Control+SetRun+SetSS)	//TaskingOn
	Xct(NOOP)
	if rIFU do
	[ Xct(IFRES); Xct(NOSKED)
	]
	let RunControl = RunEnable+HWStatus>>HWStatus.RunControl
	LoadDMD(RunControl & not IOResetx)
	XctL16Q(1400B); Xct(TIOAFQ)
	XctL16Q(32B); Xct(OUTPUTFQ)	//Reset interim dsp cont
	XctL16Q(1B); Xct(TESTFQ)	//Reset junk wakeups
	XctL16Q(SaveTIOA); Xct(TIOAFQ)	//Restore TIOA
	Xct(RFINFO)			//Reset fault task
	let AVec,DVec,DVec1 = vec 1,vec 3,vec 3
	Zero(AVec,2); Zero(DVec1,4)
	if rMD do
	[ MGetMemData(CACHEAx,DVec,AVec); MPutMemData(CACHEAx,DVec1,AVec)
	  XctL16T(NoRef+DisHold+DisBR); Xct(MCRFT)
	]
//Reset T, TLINK, TIOA, and MD tag as requested
	for I = 0 to 17B do
	[ SelectTask(I)
	  if rT then SaveT = 0
	  if rMD then
	  [ XctL16T(0); Xct(FETCHM)
	  ]
	  XctL16T(SaveT)
	  if rLINK then SaveLINK = 7777B
	  if rTIOA then [ XctL16Q(0); Xct(TIOAFQ) ]
	]
	XctL16Q(SaveQ)
//Restore CACHEA 0 and MCR
	if rMD then MPutMemData(CACHEAx,DVec,AVec)
//Reset TPC's of all tasks to 7777B
	SelectTask(0)
	SaveTPC = 7777B
//Clear CTASK, etc. by doing instruction with Freeze off;
//"RETURN" with Freeze off resets CIA to 7777.
	XctL16C(LLINK,SaveTPC); LoadMIR(LDRMEM+RETN)
	DoStrobe(Control+SetRun+SetSS)
	for I = 1 to 17B do	//TPC←7777B for tasks 1 to 15
	[ XctL16C(LLINK,SaveTPC); Xct(NOOP)
	  XctL16C(LTPC,I)
	]
	DoStrobe(Clock+UseCPReg+ClrReady)
	DoStrobe(Clock+UseCPReg)
	XctL16C(LLINK,SaveLINK); Xct(NOOP)
	LoadDMD(RunControl)
]