// D1Config.bcpl	10 May 1983

//Contains FindConfiguration, called from D1I2 to establish board
//configuration and memory system parameters and the Config action
//that overrules automatically-determined parameters with those supplied
//by the user.  FindConfiguration is also called from MStopped, if the
//machine was running when Midas connected to it.

get "d1.d"
manifest [ get "d1dmux.d" ]
manifest [ get "d1regmem.d" ]

external [
// OS
	SetBlock; Zero

// MINIT0
	@ACTS

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

// MMENU
	@WsMarkA; CreateAction; ItemStream; MarkMenus

// MMPRGN
	UpdateMPDValues

// MCMD
	WnsCSS; WnsCSSD; WnsCS1D; FormCmdMenu; QuitCmdOverlay

// D1I0
	DChecked; @DMuxTab; @SaveMIR; HWStatus

// D1I2
	ConfigUnknown

// D1TABLES
	@MEMLEN; @MEMFORMS

// D1ASM
	LoadMIR; @XctR16; @DoStrobe; LoadDMD; ReadDMux

// D1MEM
	MGetMemData

// Defined here
	FindConfiguration; D1Config
	HaveControl; HaveProcH; HaveProcL; HaveMemC; HaveMemD; HaveMemX
	HaveIFU; HaveDskEth; HaveDisplay
	log2pgsize; log2rows; IMXmask
	AColumnShift; DColumnShift; CacheAMask0; CacheAMask1

//Defined here for D1I2 only
	FixForConfiguration; ShowConnection
	MapICcode; MainICcode; ModuleMask; NoCacheAParity
]

static
[	//Basic parameters
	HaveControl; HaveProcH; HaveProcL; HaveMemC; HaveMemD; HaveMemX
	HaveIFU; HaveDskEth; HaveDisplay
	log2pgsize = 8		//8 for 256-word pages, 10 for 1024-word,
				//12 for 4096-word
	MapICcode = 0		//0 (no map), 1 (illegal bit comb.)
				//2 (16k), 3 (64k), 4 (256k)
	MainICcode = 0		//0 (no storage), 1 (illegal bit comb.),
				//2 (4k), 3 (16k), 4 (64k), 5 (256k)
	ModuleMask = 0		//4-bits:  M0, M1, M2, M3
	log2rows = 6		//6 for 64 rows, 7 for 128, 8 for 256
	NoCacheAParity = 0	//0 if CacheA parity, 1 if 16 address bits
	IMXmask = 7777B		//Length of IMX less 1

	//Derived
	AColumnShift = 5	//5 for 4k cache, 4 for 8k, 3 for 16k
	DColumnShift = 1	//1 for 4k, 0 for 8k, -1 for 16k
	CacheAMask0; CacheAMask1 //Mask for CacheA read-write:
				//17xxxx 17yyyy, where the unspecified
				//bits vary with no. rows and whether the
				//16th bit is an address bit or parity
]

manifest
[	get "d1instrs.d"

//Indices to ACTS
	hControl = 1; hProcL = 4; hProcH = 7
	hIFU = 10; hMemC = 13; hMemD = 16; hMemX = 19
	hDskEth = 22; hDsp = 25
	r64 = 28; r256 = 31
	p256 = 34; p1K = 37; p4K = 40
	m16 = 43; m64 = 46; m256 = 49
	m0 = 52; m1 = 55; m2 = 58; m3 = 61; m4 = 64
	s4 = 67; s16 = 70; s64 = 73; s256 = 76
]

//Determine which boards are plugged in and fill in configuration
//parameters.  Note that with power on, mufflers should read 0 for a
//non-existent board.  With no Dorado connected, all mufflers read 1,
//reasonable for debugging Midas.
//*Called from D1I2 and D1GO
let FindConfiguration() be
[
//Do ReadDMux() first, providing enough information to estimate the
//configuration; cannot do ReadAllRegs() until after FixForConfiguration()
//because FixForConfiguration() modifies DCHK, which might be displayed.
	ReadDMux(); HWStatus!0 = DMuxTab!dCLKRUN
	HaveControl = OrMufflers(dCJNK0,dREADY) ne 0
	let T = OrMufflers(dALUB,dPJUNK)
	HaveProcL,HaveProcH = T<<rh ne 0,T<<lh ne 0
	HaveMemC = OrMufflers(dPVAH,dPIPEAD) ne 0
	HaveMemD = OrMufflers(dMEMD0,dDADE) ne 0
	HaveMemX = OrMufflers(dP34INEC,dINMAP) ne 0
	HaveIFU = OrMufflers(dMEMRQ,dFFK) ne 0
	HaveDskEth = OrMufflers(dKSTATE,dERX1) ne 0
	HaveDisplay = OrMufflers(140B,147B) ne 0
	ConfigUnknown = false
//Index is 3 bits: MapIs16K, MapIs64K, MapIs256K
	MapICcode = table [ 0; 4; 3; 1; 2; 1; 1; 1 ] !
		((DMuxTab!dAPESRN rshift 5) & 7B)
//Index is 3 bits: ChipsAre4K, ChipsAre16K, ChipsAre64K
	MainICcode = table [ 0; 4; 3; 1; 2; 1; 1; 1 ] !
		((DMuxTab!dSTOUT rshift 1) & 7B)
//*Note that ReadAllRegs() has not been executed when FindConfiguration
//is called from D1I2, so ALUFM is not setup, but ok for this instruction.
//Wind up with M0, M1, M2, and M3 in right-most 4 bits of ModuleMask
	ModuleMask = (XctR16(RCONFG,lv ModuleMask) rshift 4) & 17B
	LoadMIR(SaveMIR)
//CacheConfig eq 0 and PageConfig eq 0 are undefined values
	let CacheConfig = (DMuxTab!dPIPEAD rshift 10) & 3
	let PageConfig = (DMuxTab!dPIPEAD rshift 8) & 3
	log2rows = table [ 6; 8; 8; 6 ] !CacheConfig
	NoCacheAParity = CacheConfig eq 1 ? 1,0
	log2pgsize = table [ 8; 12; 10; 8 ] !PageConfig
//**Need to compute IMXmask here
	FixForConfiguration()
]


and OrMufflers(first,last) = valof
[	let T = 0
	for I = first to last do
	[ T = T % DMuxTab!I
	]
	resultis T
]


//**NOTE:  when put in command files, this action will only work, in
//**general, if the Have actions are executed in the correct order.
and D1Config(nil,nil) = valof
[	ACTS!0 = CreateAction("Done",lv ConDone,0)
//Haves
	DefTF("Control","Control'",hControl,lv HaveControl)
	DefTF("ProcL","ProcL'",hProcL,lv HaveProcL)
	DefTF("ProcH","ProcH'",hProcH,lv HaveProcH)
	DefTF("IFU","IFU'",hIFU,lv HaveIFU)
	DefTF("MemC","MemC'",hMemC,lv HaveMemC)
	DefTF("MemD","MemD'",hMemD,lv HaveMemD)
	DefTF("MemX","MemX'",hMemX,lv HaveMemX)
	DefTF("DskEth","DskEth'",hDskEth,lv HaveDskEth)
	DefTF("Dsp","Dsp'",hDsp,lv HaveDisplay)
//Cache rows
	DefCon(lv log2rows,"64-rows",r64,6)
	DefCon(lv log2rows,"256-rows",r256,8)
//Page size
	DefCon(lv log2pgsize,"256",p256,8)
	DefCon(lv log2pgsize,"1K",p1K,10)
	DefCon(lv log2pgsize,"4K",p4K,12)
//Map chips
	DefCon(lv MapICcode,"16K-wds",m16,2)
	DefCon(lv MapICcode,"64K-wds",m64,3)
	DefCon(lv MapICcode,"256K-wds",m256,4)
//Modules
	DefCon(lv ModuleMask,"0",m0,0)
	DefCon(lv ModuleMask,"1",m1,10B)
	DefCon(lv ModuleMask,"2",m2,14B)
	DefCon(lv ModuleMask,"3",m3,16B)
	DefCon(lv ModuleMask,"4",m4,17B)
//Storage chips
	DefCon(lv MainICcode,"4K-ics",s4,2)
	DefCon(lv MainICcode,"16K-ics",s16,3)
	DefCon(lv MainICcode,"64K-ics",s64,4)
	DefCon(lv MainICcode,"256K-ics",s256,5)
	resultis D1ConMenu
]


and DefTF(Strue,Sfalse,X,lvStat) be
[	ACTS!X = CreateAction(Strue,lv DoConTrue,X)
	ACTS!(X+1) = CreateAction(Sfalse,lv DoConFalse,X)
	ACTS!(X+2) = lvStat
]


and DefCon(lvStat,Str,X,Val) be
[	ACTS!X = CreateAction(Str,lv DoConSel,X)
	ACTS!(X+1) = lvStat
	ACTS!(X+2) = Val
]


and D1ConMenu(S,nil) be
[	FixForConfiguration()
	WsMarkA(ACTS!0)
	Wss(ItemStream," Have: "); MarkMenus(0)
	ShowOnOffAct(hControl)
	if HaveControl then
	[ ShowOnOffAct(hProcL)
	  if HaveProcL do
	  [ ShowOnOffAct(hProcH)
	    if HaveProcH do
	    [ ShowOnOffAct(hIFU); ShowOnOffAct(hMemC)
	      if HaveMemC do
	      [ ShowOnOffAct(hMemD); ShowOnOffAct(hMemX)
	      ]
	      ShowOnOffAct(hDskEth); ShowOnOffAct(hDsp)
	    ]
	  ]
	]
	if HaveMemC do
	[ Wss(ItemStream," Rows: "); MarkMenus(0)
	  WsMarkA(ACTS!r64); WsMarkA(ACTS!r256)
	  if HaveMemX do
	  [ Wss(ItemStream," Pgsize: "); MarkMenus(0)
	    WsMarkA(ACTS!p256); WsMarkA(ACTS!p1K); WsMarkA(ACTS!p4K)
	    Wss(ItemStream," Map size: "); MarkMenus(0)
	    WsMarkA(ACTS!m16); WsMarkA(ACTS!m64); WsMarkA(ACTS!m256)
	    if HaveMemD do
	    [ Wss(ItemStream," Modules: "); MarkMenus(0)
	      WsMarkA(ACTS!m0); WsMarkA(ACTS!m1)
	      WsMarkA(ACTS!m2); WsMarkA(ACTS!m3); WsMarkA(ACTS!m4)
	      Wss(ItemStream," Storage has: "); MarkMenus(0)
	      WsMarkA(ACTS!s4); WsMarkA(ACTS!s16); WsMarkA(ACTS!s64)
	      WsMarkA(ACTS!s256)
	    ]
	  ]
	]
]


and ShowOnOffAct(X) be
[	WsMarkA((rv ACTS!(X+2) ? ACTS!(X+1),ACTS!X))
]


and ConDone(nil,nil,nil) be
[	UpdateMPDValues()
	QuitCmdOverlay()
]


and DoConTrue(X,MBunion,nil) be
[	rv ACTS!(X+2) = true
	FormCmdMenu()
]


and DoConFalse(X,MBunion,nil) be
[	rv ACTS!(X+2) = false
	FormCmdMenu()
]


and DoConSel(X,MBunion,nil) be
[	rv ACTS!(X+1) = ACTS!(X+2)
	FormCmdMenu()
]


//Establish consequences for the selected configuration:  set DCHK
//appropriately; compute AColumnShift and DColumnShift from log2rows for
//ConvertAV; fill in lengths for configuration-dependent memories;
//copy the basic configuration parameters into HWStatus to preserve them
//for future Run-Prog.
and FixForConfiguration() be
[	HWStatus>>HWStatus.HaveControl = HaveControl
	HWStatus>>HWStatus.HaveProcL = HaveProcL
	HWStatus>>HWStatus.HaveProcH = HaveProcH
	HWStatus>>HWStatus.HaveMemC = HaveMemC
	HWStatus>>HWStatus.HaveMemD = HaveMemD
	HWStatus>>HWStatus.HaveMemX = HaveMemX
	HWStatus>>HWStatus.HaveIFU = HaveIFU
	HWStatus>>HWStatus.HaveDskEth = HaveDskEth
	HWStatus>>HWStatus.HaveDisplay = HaveDisplay
	HWStatus>>HWStatus.ConfigUnknown = ConfigUnknown
	HWStatus>>HWStatus.MapICcode = MapICcode
	HWStatus>>HWStatus.MainICcode = MainICcode
	HWStatus>>HWStatus.ModuleMask = ModuleMask
	HWStatus>>HWStatus.log2rows = log2rows
	HWStatus>>HWStatus.NoCacheAParity = NoCacheAParity
	HWStatus>>HWStatus.log2pgsize = log2pgsize
	HWStatus>>HWStatus.IMXmask = IMXmask

	LoadDMD(IMControl)
	DoStrobe(Clock)

	let ProcMask = HaveProcH ? -1,377B
	let MapLen,VMLen,MainLen = vec 1,0,0
	Zero(MapLen,2)
	SetBlock(DChecked+dCLKRUN,-1,10B)	//Baseboard
	SetBlock(DChecked,HaveControl,20B)	//Control section
	SetBlock(DChecked+dSaveMIR,HaveControl,10B)	//MIR & IMOUT
	DChecked!dESTAT = HaveControl
	test HaveControl & HaveProcL
	ifso
	[ SetBlock(DChecked+20B,ProcMask,20B)
//Testing above the processor requires both processor boards alive
	  SetBlock(DChecked+40B,HaveProcH,dBMUX-40B)
	  DChecked!dBMUX = ProcMask
	  unless HaveProcH do
	  [ DChecked!dCIA = 177776B	//No B.C.'s
	    DChecked!dSTKRB = 137B	//Not RBaseBypass', RBaseWriteEn'
	    DChecked!dRTSB = 177B	//Not StkPSaveEn'
	    DChecked!dALUCON = 277B	//Not Pdata.08
	  ]
//Use of MemD and MemX requires MemC
	  test HaveProcH & HaveMemC
	  ifso
	  [
//VMLen is set to the limit imposed by CacheA; limit imposed by Map
//is ignored (???)
	    VMLen = 1 lshift (3+log2rows+NoCacheAParity)
	    test HaveMemX
	    ifso
	    [ MBlock(MapLen,
		table [ 0; 0;		//nothing
			0; 40000B;	//illegal--use 16K
			0; 40000B;	//16K
			1; 0;		//64K
			4; 0		//256K
			] + MapICcode+MapICcode,2)
//Use the largest module number to determine the the size of storage
//in case there are holes in the address space.
	      let LargestModule =
		table [ 0; 4; 3; 4; 2; 4; 3; 4;
			1; 4; 3; 4; 2; 4; 3; 4 ] ! ModuleMask
//Set multiplier for 64k ic's when ic size readings are inconsistent.
	      let ICSizeMul =
		table [ 0; 20B; 1B; 4B; 20B; 100B ] ! MainICcode
	      MainLen = LargestModule*ICSizeMul
	    ]
	    ifnot
	    [ Zero(DChecked+dMAPBUF,20B)
	      DChecked!dHIT = 177377B	//Not XWantsPipeDly
//Not WantCHdly', MDhold', Dbusy, AtookST, AwantsMapFS'
	      DChecked!dHOLD = 165656B
//Not IoStoreInA, Map←InPair', FlushInA, IoRefInA',VicInPair'
//bEcHasA, ←PrVArow
	      DChecked!dPAIR = 106725B
	      DChecked!dPIPEAD = 7777B	//Not PipeAd
	      DChecked!dFD = 176677B	//Not MakeMDM←D', DadH←'
	      DChecked!dEC = 171777B	//Not StartEcGen, StartEcChk
	      DChecked!dDADE = 7777B	//Not DCE'c
	      DChecked!dMCR = 163770B	//Not MemX MCR bits, Victim
	    ]
//Since RunRefresh is false during SimGo, can't enable MemoryPE stops,
//but MD should always have good parity, so ok to enable.
	    unless HaveMemD do
	    [ Zero(DChecked+dMEMD0,10B)
	      DChecked!dHIT = DChecked!dHIT & 177477B	//Not ColVic
	      MainLen = 0
	    ]
	  ]
	  ifnot	//MemC, MemD, MemX unusable
	  [ HaveMemD,HaveMemX = 0,0
	    Zero(DChecked+dPVAH,40B)
	    Zero(DChecked+dAAD,2)	//AAD, MEMB
	  ]
	  unless HaveIFU do
	  [ Zero(DChecked+dMEMRQ,20B)
//Not IfuRefInA, KillIfuRef, ←PrVArow, PairFull
	    DChecked!dPAIR = DChecked!dPAIR & 175770B
	    DChecked!dSTA = DChecked!dSTA & 177776B	//Not UseAsrn
	    DChecked!dPIPEAD = DChecked!dPIPEAD & 7777B	//Not PipeAd
	    DChecked!dHIT = DChecked!dHIT & 177377B	//Not MiscPCHP'
	  ]
	  test HaveDskEth
//Don't check mufflers changing with ethernet data; these are PDNew, PDOld,
//PDCnt[0:1] and 2133b in ERX0 and RxState[1:2], PDCarrier, RxSRFull', and
//RxCRCReset in ERX1.  Although not simulated, the DChecked table affects
//reporting of these signals by the ReadAllDMux test in the HWChk action.
	  ifso
	  [ DChecked!dERX0 = DChecked!dERX0 & 7757B
	    DChecked!dERX1 = DChecked!dERX1 & 113357B
	  ]
	  ifnot Zero(DChecked+dKSTATE,10B)
	  unless HaveDisplay do Zero(DChecked+140B,10B)
	]
	ifnot		//No simulation above control
	[ Zero(DChecked+20B,160B)
	  DChecked!dCIA = DChecked!dCIA & 177776B	//No B.C.'s
	  HaveProcL,HaveProcH = 0,0
	  HaveMemC,HaveIFU = 0,0
	  HaveMemD,HaveMemX = 0,0
	  HaveDskEth,HaveDisplay = 0,0
	]

//Turn off signals affected by simulator bugs not fixed yet.
	let T = table [
		dPCJ;		   377B	//PCJ/I
//		dMX;		177477B	//DSel[0:1] (maybe fixed)
//		dINMAP;		127777B	//RefUsesD10InMap'/X (maybe fixed)
//					//WriteInMap'/X (maybe fixed)
//		dSTA;		177775B	//MapFree/X
//		dMAPCTRL;	177747B	//MapFnc'[0:1] (maybe fixed)
//		dPIPEAD;	 77777B	//PipeAd.0/C
//		dP34INEC;	170377B	//Pipe34Ad[0:3]/X (maybe fixed)
//		dAPESRN;	173777B	//ProcSrn.0/X
//		dPEEC;		 77777B	//PEsrn.0/X
	]
	for I = 0 to 0 by 2 do DChecked!(T!I) = DChecked!(T!I) & (T!(I+1))
	MBlock(MEMLEN+MAPx+MAPx,MapLen,2)
	MEMLEN!(IMXx+IMXx+1) = IMXmask+1
	MEMLEN!(IMx+IMx+1) = IMXmask+1
	MEMLEN!(VMx+VMx) = VMLen
	MEMLEN!(ROWx+ROWx+1) = 1 lshift log2rows
	MEMLEN!(CACHEAx+CACHEAx+1) = 4B lshift log2rows
	MEMLEN!(CACHEDx+CACHEDx+1) = 100B lshift log2rows
	AColumnShift = 11-log2rows
	DColumnShift = 7-log2rows
//Flags put in DVec!0[0:3], VA[4:15] in DVec!0[4:15]; value has a
//total of 15 address bits, or 16 if parity bit is converted to address
//bit
	CacheAMask0 = 170000B+(-1 rshift (13-log2rows-NoCacheAParity))
//VA[16:31] munch and row address bits not part of value
	CacheAMask1 = -1 lshift (log2rows+4)
	let FormCACHEA = MEMFORMS!CACHEAx
	FormCACHEA!3 = #15-log2rows-NoCacheAParity
	FormCACHEA!4 = #17+NoCacheAParity

//Show board configuration
	ShowConnection()
	test HaveControl
	ifso
	[ WssCSS(", ContA")
	  WnsCS1D(MEMLEN!(IMXx+IMXx+1)); WssCS1("-word IMX")
//Require ContA/B and ProcL/H to indicate any others
	  test HaveProcL
	  ifso test HaveProcH
	    ifso
	    [ unless HaveIFU do WssCSS("-ProcH")
	      test HaveMemC
	      ifso
	      [	test HaveIFU
		ifso unless HaveMemX do WssCSS("-MemC")
		ifnot WssCSS(", MemC")
		WssCS1(", "); WnsCS1D(1 lshift log2rows)
		WssCS1(" rows")
		test HaveMemX
		ifso test HaveMemD
		  ifso
		  [ WssCSS("-MemD")
		    WssCS1(", ")
		    test MapICcode ne 1
		    ifso
		    [ WnsCS1D(table [ 0; 0; 16; 64; 256 ] ! MapICcode)
		      WssCS1("K ")
		      WnsCS1D(1 lshift log2pgsize)
		      WssCS1("-word pages")
		    ]
		    ifnot WssCS1("??Map ic size??")
		    test (ModuleMask eq 0) % (MainICcode eq 0)
		    ifso WssCS1(", no storage")
		    ifnot
		    [ test MainICcode ge 2
		      ifso
		      [	WssCS1(", ")
			WnsCS1D(MainLen lshift 6)
			WssCS1("K storage")
			let ModOK =
				table [ -1; 0; 0; 0; 0; 0; 0; 0
					-1; 0; 0; 0; -1; 0; -1; -1 ] !
					ModuleMask
			unless ModOK do WssCS1(" with holes")
		      ]
		      ifnot WssCS1(", ??storage IC size??")
		    ]
		  ]
		  ifnot WssCSS("-MemX")
		ifnot if HaveMemD then WssCSS(", MemD")
	      ]
	      ifnot if HaveIFU then WssCSS("-IFU")
	      if HaveDskEth then WssCSS(", DskEth")
	      if HaveDisplay then WssCSS(", Dsp")
	    ]
	    ifnot WssCSS("-ProcL")
	  ifnot WssCSS("-ContB")
	]
	ifnot WssCSS(", no control section")
	WssCSS(", Clk = ");
	let T = 20000/((DMuxTab+dCLKRUN)>>lh)
	WnsCSSD(T/10); PutsCSS($.); WnsCSSD(T rem 10); WssCSS(" ns")
]


and ShowConnection() be
[	ResetsCSS(); ResetsCS1()
	let ConnectedMachine = HWStatus>>HWStatus.ConnectedMachine
	test ConnectedMachine eq -1
	ifso WssCSS("Disconnected")
	ifnot
	[ WssCSS("Serial #"); WnsCSS(ConnectedMachine)
	  let Version = vec 1
	  MGetMemData(ABSOLx,Version,table [ 0; 0 ] )
	  WssCSS(", ZVer="); WnsCSS(Version>>lh)
	]
]