//D1SimIfu.bcpl 10 May 1983

//SimIfu is called by DSimulate to check consistency of signals muffled
//on the IFU board.

get "d1simmi.d"
manifest [ get "d1dmux.d" ]

structure [ lh byte; rh byte ]

external [
// D1I0
	@DMuxTab; @OldDMuxTab

// D1SimDec
	oldoldFFfunc

// Defined here
	SimIfu
]


//Flipflops in the IFU pipeline are clocked when Testing is false or when
//an unsimulatable test condition occurs.  The simulator only simulates
//these when Testing is false.

//Flops dependent upon IfuMemAck not predicted because TestMemAck isn't
//muffled, but at Tn eq 2 could compute T2IfuAck =
//T2Hit & (not T2WantCHdly) & (not oldWantIfuRef).

//Prediction for many signals depends upon K-level inputs.  These inputs are
//unchanged between T0 and T2 only when IFUM has a stable address and is not
//being written.  J changes at even clocks, so only the InstrAddr address
//signals, which change at T3, can cause an unstable address between T0 and
//T2.  However, the write enable for the 415A RAMs is low between T1 and T3
//of an instruction which writes the RAM; during this period the RAM outputs
//are forced low.  So DecLo← or DecHi← in OldDMuxTab will cause affected
//K-level terms to be 0 at T2 when they are loaded into M-level, or DecLo← or
//DecHi← in OldOldDMuxTab will cause the K-level signals to be 0 at T0, when
//they are looked at for prediction.

let SimIfu(Tn,Correct,Tneven,FFfunc,asel,T2IfuNextMacro,T2NextData,T2Hold,
	oldFFfunc,T1DTab,T1FFfunc,T2DTab,lvHoldReq,NextMacro) = valof
[	let MDvx = DMuxTab>>IFU0.MDvx
	let GDv = DMuxTab>>IFU0.GDv
	let NewGo = DMuxTab>>IFU0.NewGo
	let MLdDlyx = DMuxTab>>IFU1.MLdDlyx
	let NewPcg = DMuxTab>>IFU1.NewPcg
	let IfuReset = DMuxTab>>IFU1.IfuReset
	let Testing = DMuxTab>>IFU1.Testing
	let ReschedPending = DMuxTab>>IFU0.ReschedPending
	let PcF815 = DMuxTab>>IFU0.PcF815
	let RealPcFG15 = DMuxTab>>IFU0.RealPcFG15
	let BrkInsg = DMuxTab>>IFU1.BrkInsg
	let ZapFGH = DMuxTab>>IFU0.ZapFGH
	let RamErrDly = DMuxTab>>IFU1.RamErrDly
	let FGErrDly = DMuxTab>>IFU1.FGErrDly
	let FDvDly = DMuxTab>>IFU1.FDvDly
	let GDvDly = DMuxTab>>IFU1.GDvDly
	let HDvDly = DMuxTab>>IFU1.HDvDly
	let GFaultDlyx = DMuxTab>>IFU1.GFaultDlyx
	let KReadyDly = DMuxTab>>IFU1.KReadyDly
	let ExceptionDly = DMuxTab>>IFU1.ExceptionDly
	let GLdDlyx = DMuxTab>>IFU1.GLdDlyx
	let IncPcFGDlyx = DMuxTab>>IFU1.IncPcFGDlyx
	let FGFault = DMuxTab>>IFU0.FGFault
	let JFault = DMuxTab>>IFU0.JFault
	let NewGoorNoM = NewGo % MDvx
	let FGDvDly = FDvDly % GDvDly

	let cIfuMARvalx = DMuxTab!dMAR	//actual value if not predicted

	let RamWrite = (oldoldFFfunc & 376B) eq 134B

	if Tn ge 1 do
	[ let cGenOutgx,cTestg,cBrkInsg,cT1IFUMg = -1,0,0,0
	  switchon T1FFfunc into
	  [
case 101B:	cTestg = -1; endcase
case 131B:	cGenOutgx = 0; endcase
case 134B to 135B:	RamWrite = true; endcase
case 137B:	cBrkInsg = -1; endcase
	  ]
	  Correct>>IFU1.Testg = cTestg
	  Correct>>IFU1.GenOutgx = cGenOutgx
	  Correct>>IFU1.RamErrDly = T1DTab>>IFU0.SawRamParityErr

	  if Tn ge 2 do
	  [ let WantIfuHoldDly =
		(RamErrDly & not OldDMuxTab>>IFU1.RamErrDly) %
		(FGErrDly & not OldDMuxTab>>IFU1.FGErrDly)
	    Correct>>IFU0.InstrAddrLd = NewGoorNoM % ReschedPending %
		(WantIfuHoldDly & not MLdDlyx) //% AlphaXLd
	    if Tn eq 2 do
	    [ Correct>>IFU1.FGErrDly = OldDMuxTab>>IFU0.SawFGParityErr
	    ]

	    let oldBMUX = OldDMuxTab!dBMUX
	    let oldReschedPending = OldDMuxTab>>IFU0.ReschedPending
	    let oldWantResched = OldDMuxTab>>IFU0.WantResched
	    let oldTesting = OldDMuxTab>>IFU1.Testing
	    let oldTestg = OldDMuxTab>>IFU1.Testg

	    let T2XLd = T2IfuNextMacro & not T2Hold
	    let cNewPcg,cIfuReset = 0,0
	    let cWantResched = oldWantResched
//Only simulate ReschedPending when ExceptionDispatch is insignificant.
//Last term ideally (oldWantResched & T2XLd & not oldExceptionDispatch)
	    let cReschedPending = oldReschedPending %
		(oldWantResched & T2XLd & ReschedPending)
	    switchon oldFFfunc into
	    [
case 100B:	cNewPcg = 1; endcase
case 103B:	cReschedPending = 1; endcase
case 132B:	cWantResched = 1; endcase
case 133B:	cReschedPending,cWantResched = 0,0; endcase
case 136B:	cIfuReset = 1; endcase
	    ]
	    Correct>>IFU1.IfuReset = cIfuReset

//The stuff below sometimes requires that T1Testing be false and sometimes
//that T2Testing be false, in order to predict whether or not the clocks
//occur.  Require both of these false for simplicity.
	    if (Testing eq 0) & (oldTesting eq 0) do
	    [ Correct>>IFU0.ReschedPending = cReschedPending
	      Correct>>IFU0.WantResched = cWantResched
	      Correct>>IFU1.NewPcg = cNewPcg
//Can't predict BrkIns← except for Tn ge 2 because an IfuReset or IFUTest←
//at T-2 could reset Testing at T1, so can't tell whether BrkIns← ff is
//clocked.
	      Correct>>IFU1.BrkInsg = cBrkInsg
//Note that Mar←PcF' and Testing can both be loaded true, in which case
//future instructions will pollute Mar.  Hence, SimTest rejects
//instructions that do IFUTEST←, and assumes the program executed by
//SimGo doesn't do this because it is illegal.
	      let oldFDv = OldDMuxTab>>IFU0.FDv
	      let oldGDv = OldDMuxTab>>IFU0.GDv
	      let oldHDv = OldDMuxTab>>IFU0.HDv
	      let oldJDv = OldDMuxTab>>IFU0.JDv
	      let oldMDvx = OldDMuxTab>>IFU0.MDvx
	      let oldGLdx = OldDMuxTab>>IFU0.GLdx
	      let oldZapFGH = OldDMuxTab>>IFU0.ZapFGH
	      let oldRealPcFG15 = OldDMuxTab>>IFU0.RealPcFG15
	      let oldPcJ815 = OldDMuxTab>>IFU1.PcJ815
	      let oldDoJump = OldDMuxTab>>IFU0.DoJump
	      let oldNewGo = OldDMuxTab>>IFU0.NewGo
	      let oldDSel = OldDMuxTab>>IFU0.DSel
	      let oldLengthM = OldDMuxTab>>IFU0.LengthM
	      let oldLengthX = OldDMuxTab>>IFU0.LengthX
	      let oldBetaInM = OldDMuxTab>>IFU1.BetaInM
	      let oldNMeq17 = OldDMuxTab>>IFU0.NMeq17
	      let oldNewJ = OldDMuxTab>>IFU0.NewJ
	      let oldZapJ = OldDMuxTab>>IFU0.ZapJ
	      let oldOBJinJ = OldDMuxTab>>IFU1.OBJinJ
	      let oldOBJinJd = OldDMuxTab>>IFU1.OBJinJd
	      let oldValidRam = OldDMuxTab>>IFU0.ValidRam
	      let oldBrkPending = OldDMuxTab>>IFU1.BrkPending
	      let oldSawRamParityErr = OldDMuxTab>>IFU0.SawRamParityErr
	      let oldRefOutstanding = OldDMuxTab>>IFU0.RefOutstanding
	      let oldKillResponse = OldDMuxTab>>IFU0.KillResponse
	      let oldFGFault = OldDMuxTab>>IFU0.FGFault
	      let oldPcF815 = OldDMuxTab>>IFU0.PcF815
	      let oldH = OldDMuxTab>>IFU0.H
	      let oldTwoAlphaM = OldDMuxTab>>IFU0.TwoAlphaM
	      let oldTwoAlphaX = OldDMuxTab>>IFU0.TwoAlphaX
	      let oldJFault = OldDMuxTab>>IFU0.JFault
	      let oldNewGoorNoM = oldNewGo % oldMDvx
	      let oldBetaInH = (not oldMDvx) & (oldLengthM eq 3)
	      let oldIfuReset = OldDMuxTab>>IFU1.IfuReset
//Terms with K-level components must not be used for predictions outside
//the (InstrSet eq oldInstrSet) & not RamWrite conditional
	      let oldLengthK = OldDMuxTab>>IFU1.LengthK
	      let oldTypeJumpKx = OldDMuxTab>>IFU1.TypeJumpKx
	      let oldSignK = OldDMuxTab>>IFU1.SignK
	      let KSimOK = DMuxTab>>IFU1.InstrSet eq OldDMuxTab>>IFU1.InstrSet ? not RamWrite,0

	      let T2NextBeta = (oldLengthX eq 3) & (oldDSel eq 0) &
		T2NextData & oldBetaInM
	      let T2AlphaXLd = (T2NextBeta % T2IfuNextMacro) & not T2Hold
	      let T2MLd = T2AlphaXLd % oldNewGoorNoM
	      let T2XShift = (T2NextData % T2IfuNextMacro) & not T2Hold
	      let oldMakeFDv = OldDMuxTab>>IFU0.NewF & not oldKillResponse

//T2FGFault = T2GDv ? T2GFault,T2FFault, where Dly flipflops give all signals
//except T2FFault.  If G was invalid at T2-, then G was loaded at T2, so
//GFault and FFault are identical, and their common value is observable at
//FGFault regardless of whether G is valid or not unless IfuReset is true;
//if IfuReset is true, then GFault is correct but FFault has been forced to
//0, so T2FFault cannot be observed unless G is valid.  Hence, predictions
//based upon T2FGFault must be conditioned by
//Tneven' % IfuReset' % GDvDly % GDv
	      let T2FGFault = Tneven ? (GDvDly ne 0 ? not GFaultDlyx,FGFault),
		oldFGFault

//BrkPending is loaded true at T2 and at T3 of BrkIns←, false at T2 of
//an IfuReset, and turned off at Teven after FDv when BrkPending.
//The BrkIns register is bogusly loaded at T2 of BrkIns←, then with good
//data at T3 of BrkIns←, finally cleared at Teven after FDv, concurrent
//with J←BrkIns, all assuming IfuReset prior to BrkIns←.
	      let T2BrkPending = Tneven ? (oldBrkPending &
		not OldDMuxTab>>IFU0.BrkLd) % OldDMuxTab>>IFU1.BrkInsg,
		  oldBrkPending

//Terms with K-level components must not be used for predictions outside
//the (InstrSet eq oldInstrSet) & not RamWrite conditional
	      let T2JgH = oldLengthK & HDvDly & oldValidRam
	      let oldMightBeJump = oldNewJ & not oldTypeJumpKx
	      let T2JLd = 1 & (oldZapJ % (not oldJDv) %
		(T2MLd & (oldBetaInH % (KReadyDly & not oldMightBeJump))))
	      let T2JgH = HDvDly & oldLengthK

	      Correct>>IFU1.MLdDlyx = not T2MLd
	      Correct>>IFU1.BetaInM = T2AlphaXLd ? T2XLd,oldBetaInM

	      if Tn eq 2 do
	      [	//cIfuMARvalx predicts MAR when processor doesn't drive MAR
		test T1DTab>>IFU0.WantIfuRefx eq 0
		ifso cIfuMARvalx<<rh = not PcF815
		ifnot cIfuMARvalx = 0

		Correct>>IFU0.HFaultx = oldHDv ne 0 ?
		  OldDMuxTab>>IFU0.HFaultx,not (oldFGFault &
			not OldDMuxTab>>IFU0.EnableFGx)
//GDvDly is loaded at T2, so it contains GDv's value from T1 to T2.
//GDv is set true when loaded from F at T0 or T1; otherwise, it is set false
//when moved into H at T1 or J at T0.  Note that GDv' implies GLd.
//T1GDv' = T0GLd & (T0ZapFGH % T0FDv' % (T0HDv' & T0GDv' & T0PcFG.15))
//T1GDv = T0GLd' % (T0ZapFGH' & T0FDv & (T0HDv % T0GDv % T0PcFG.15'))
		Correct>>IFU1.GDvDly = oldGLdx % ((not oldZapFGH) &
		  oldFDv & (oldHDv % oldGDv % (not oldRealPcFG15)))

		Correct>>IFU1.BrkPending = BrkInsg %
		  (T2BrkPending & (not IfuReset) & not FGDvDly)
		if KSimOK do
		[
//FDv is set true at T1 when loaded from memory, false at T0 when moved
//into G or J, or false at T1 when moved into H.
		  Correct>>IFU0.FDv = (not ZapFGH) & GLdDlyx &
		    (oldMakeFDv % (oldFDv & oldGLdx))

//BMuxEnable = NewPc1 % BrkIns← % Test←.
//TurnOffALU = BMuxEnable % BrkPending % IfuReset1.
//PcF load is enabled by ZapFGH (= IfuReset % NewPc← % DoJump).
//Simulator has to handle collision of BrkIns← with DoJump, in which case
//PcF is loaded with 0 (illegal for microprogram).
//Also, one vs two-byte jump multiplexor select is actually
//the LengtK.1 signal not enabled by ValidRam, but the one enabled by
//ValidRam is muffled.
		  let PcF816 = (PcF815 lshift 1)+RealPcFG15
		  let OBJumpInput =
		    (OldDMuxTab!dIDLY & #37)-(oldSignK lshift 5)+oldPcJ815
		  let TBJumpInput =
		    oldH-(((oldSignK lshift 7) & oldH) lshift 1)+oldPcJ815
		  let IfuALU =
		    selecton oldLengthK into
		    [ case 1: OBJumpInput
		      case 2: TBJumpInput
		      case 0:
		      case 3: PcF816
		    ]
		  let oldIfuBMux = OldDMuxTab>>IFU0.BMuxEnable ne 0 ?
		    oldBMUX,(OldDMuxTab>>IFU0.TurnOffAlu eq 0) & IfuALU
//This should be T1ZapFGH and T1IncPcF but only do this simulation at
//Tn eq 2 because not sure how to treat BrkPending component of TurnOffALU
//at Tn eq 3.
		  Correct>>IFU0.PcF815 = oldZapFGH ne 0 ?
		    oldIfuBMux rshift 1,
		    (OldDMuxTab>>IFU0.IncPcF ne 0 ? oldPcF815+1,oldPcF815)
//GDv is set true when loaded from F at T0 or T1; otherwise, it is set false
//when moved into H at T1 or J at T0.  GDv at T2 = (GDvDly & GLdDly') %
//(FDvDly & not (T2PcFG.15 & JLd & J←H'), where GDvDly & GLdDly' = GLdDly'.
//PcFG is loaded at T1 on ZapFGH; it is counted when F or G is valid and
//being moved down into J or H.
		  let T2RealPcFG15 = (oldZapFGH ne 0 ? oldIfuBMux,
		    not (oldRealPcFG15 xor OldDMuxTab>>IFU0.IncPcFGx)) & 1
		  Correct>>IFU0.RealPcFG15 =
		    T2RealPcFG15 xor (not IncPcFGDlyx)
		  let T2JgOBinF =
		    (not IncPcFGDlyx) & T2RealPcFG15 & not GDvDly
		  Correct>>IFU0.GDv = GLdDlyx % (FDvDly & not T2JgOBinF)

//JK flipflop simulation = (Old % Set) & not (Old & Reset).
//It is possible for both the J and K inputs to the HDv flipflop to be
//true in SH when HDv is true, so that it complements to false, but the above
//simulation allows for this.
//T0 to T1:	Set = DoJump % (FGDv & not ZapFGH),
//		Reset = OneByteJumpInJ' & OneByteJumpInJd
//T1 to T2:	Set = DoJump
//		Reset = JLd & OneByteJumpInJ'
		  Correct>>IFU0.HDv =
		    (HDvDly % oldDoJump) & not (HDvDly & T2JLd & not oldOBJinJ)
//GLdx = ZapFGH' & GDv & (RealPcFG15 & (Tneven ? HDv',JLd & not JgH))'
		  Correct>>IFU1.GLdDlyx = (not oldZapFGH) & GDvDly & not
			(T2RealPcFG15 & T2JLd & not T2JgH)

//FDvDly is loaded at T2, so it holds the value of FDv from T1 to T2.
		  Correct>>IFU1.FDvDly = (not oldZapFGH) &
		    (oldMakeFDv % (oldFDv & oldGLdx))

//Cleverly infer the value in PcFG from RealPcFG.15, PcF, and other signals.
//Know that on the last ZapFGH both PcFG and PcF are loaded from IfuBmux
//at T1; then PcF+1 for every fetch to F acknowledged at T1 and PcFG+1 for
//every byte moved from FG to J at T0 or H at T1.  We are interested in the
//value of PcFG at T2-, just before it is loaded into PcJ.  The simulation
//can't be carried out if IfuReset occurs.  RefOutstanding becomes true at T0
//after a reference and PcF counts at the following T1; the memory eventually
//delivers one or two bytes of data causing NewF true and RefOutstanding
//false at a T0 and FDv true at the following T1; during the instruction in
//which both PcF and PcFG are loaded, ZapFGH is true, indicating that
//RefOutstanding should be ignored.  Hence, after any T1:
//	let X	= (RefOutstanding&ZapFGH')+FDv
//	PcF =	origPcF+X+((GDv+JDv+HDv+N+origPcFG15)/2)
//	PcFG =	2*origPcF+origPcFG15+N+JDv+HDv
//where N = no. bytes moved past the J/H levels.  Then:
//	PcFG	= 2*(PcF-X-(GDv+JDv+HDv+N+origPcFG15)/2)+JDv+HDv+N+origPcFG15
//		= 2*(PcF-X)+(JDv xor HDv xor (N&1) xor origPcFG15)
//			-2 if GDv is true and the xor term is odd

		  let T2PcFG815 = T2RealPcFG15 ne 0 ? 1-(GDvDly lshift 1),0
		  T2PcFG815 =
		    ((T2DTab>>IFU0.PcF815-(oldRefOutstanding & not oldZapFGH)-
			FDvDly) lshift 1)+T2PcFG815
		  if (IfuReset+oldIfuReset) eq 0 then
			Correct>>IFU1.PcJ815 = T2JLd eq 0 ? oldPcJ815,
				(T2JgH ne 0 ? oldPcJ815+1,T2PcFG815)
		]
//**I think it is impossible to have both the J' and K' inputs to the HDv
//flipflop low during FH, but should check.
		Correct>>IFU1.HDvDly =
		  oldDoJump % ((oldFDv % oldGDv) & not oldNewGo) %
		  (oldHDv & not (oldOBJinJd & not oldOBJinJ))

//Need TestMemAck to do this; TLastMakeFgD is computed by D1SimMem
//		Correct>>IFU0.RefOutstanding = (not IfuReset) &
//		  (T2IfuMemAck % (oldRefOutstanding & not T2IfuMakeFgD))
	      ]

//At T2, KillResponse is loaded with 1 if oldZapFGH & oldRefOutstanding,
//else no change; at T1 it is loaded with 0 if NewF, else no change.
	      let sKillResp = oldZapFGH & oldRefOutstanding
	      let T1NewFx = T1DTab>>IFU0.NewF eq 0
	      Correct>>IFU0.KillResponse = (not IfuReset) &
		(not oldIfuReset) & (Tneven ?
		  sKillResp % (T1NewFx & oldKillResponse),
		  T1NewFx & (sKillResp % oldKillResponse))

//The T2FGFault term is unknown under the conditions given earlier, but
//if IfuReset is true, ZapJ is also true, so this prediction works anyway.
	      Correct>>IFU1.ExceptionDly = not (
		(not oldReschedPending) & KReadyDly & (not oldZapJ) &
		(not T2DTab>>IFU1.FGErrDly) & (not oldSawRamParityErr) &
		(T2DTab>>IFU0.HFaultx % (oldLengthK < 2)) &
		(not (T2FGFault & (oldLengthK eq 3)))
		)

	      Correct>>IFU0.LengthX = T2XLd ne 0 ? oldLengthM,oldLengthX
	      Correct>>IFU0.TwoAlphaX = T2XLd ne 0 ?
		oldTwoAlphaM,(oldTwoAlphaX & not T2AlphaXLd)
	      Correct>>IFU0.NX = T2XLd eq 0 ? OldDMuxTab>>IFU0.NX,
		(oldNMeq17 ne 0 ? #17,DMuxTab>>IFU0.NX)

	      Correct>>IFU1.OBJinJd = oldOBJinJ

//The K level signals just before T2 equal the K level signals just after
//T0, except when IFUM is being loaded or InstrSet changes at T1.
	      if KSimOK do
	      [	Correct>>IFU0.LengthM = MLdDlyx eq 0 ? oldLengthK,oldLengthM
		Correct>>IFU0.TwoAlphaM = MLdDlyx eq 0 ?
		  OldDMuxTab>>IFU1.TwoAlphaK,oldTwoAlphaM
		Correct>>IFU0.NMeq17 = MLdDlyx eq 0 ?
		  (OldDMuxTab>>IFU1.NK eq #17),oldNMeq17
		Correct>>IFU0.TypeJumpMx = MLdDlyx eq 0 ?
		  oldTypeJumpKx,OldDMuxTab>>IFU0.TypeJumpMx
		let J = DMuxTab>>IFU0.J
		let oldRealJFault = oldJDv & oldJFault
		let T2SayNotReady = oldZapJ % ((not oldRealJFault) &
			(not KReadyDly) & (not oldBetaInH))
//Both the Set and Reset inputs of the Pause flipflop are used, and these
//signals will survive beyond the T2 clock that loads the flipflop.
		Correct>>IFU0.Pause = IfuReset %
		  ((not NewPcg) &
		    (((oldRealJFault % OldDMuxTab>>IFU0.Pause %
		      (KReadyDly & not OldDMuxTab>>IFU1.TypePauseKx)
		    ) & not OldDMuxTab>>IFU1.NewPcg) % oldIfuReset)
		  )
		Correct>>IFU1.KReadyDly =
		  oldValidRam & ((oldLengthK < 2) % HDvDly) &
		  ((oldLengthK ne 3) % FGDvDly)
		Correct>>IFU1.IncPcFGDlyx =
		  not (FGDvDly & T2JLd & not T2JgH)

	        Correct>>IFU0.NewJ = T2JLd % (oldNewJ & not KReadyDly)
		Correct>>IFU0.DoJump = KReadyDly & oldMightBeJump
		Correct>>IFU0.MDvx = MLdDlyx eq 0 ? T2SayNotReady,oldMDvx
		Correct>>IFU0.JDv = T2JLd eq 0 ? oldJDv,
		  (not oldZapFGH) & (FGDvDly % T2JgH) & (not oldOBJinJ)
//J simulation limited by possible OR'ing of test or BrkIns data with
//data from H.
		Correct>>IFU0.J = T2JLd eq 0 ? OldDMuxTab>>IFU0.J,
		  (T2JgH ne 0 ? J % T2DTab>>IFU0.H,J)
//T2FGFault valid only when Tneven' % IfuReset' % GDvDly % GDv, simplified
//to IfuReset' here.
		if IfuReset eq 0 do
		[ Correct>>IFU0.JFault = T2JLd eq 0 ? oldJFault,
		  (T2JgH ne 0 ? not T2DTab>>IFU0.HFaultx,
			T2FGFault & not T2BrkPending)
		]
		Correct>>IFU1.OBJinJ = ((oldDoJump & T2JgH) % oldOBJinJ) &
		  not (T2JLd & oldOBJinJ)
	      ]

//DSel eq 0 Alpha[4:7] or Alpha[0:7] according to TwoAlphaX,
//1 Alpha[0:3], 2 NX, 3 Length
//DSel ROM contains the following:
//		N ne #17	N eq #17
//TwoAlpha'	0/ 3,3,3,3	20/ 3,3,3,3	Jump
//		1/ 3,3,3,3	21/ 3,3,3,3
//		2/ 3,3,3,3	22/ 3,3,3,3
//		3/ 3,3,3,3	23/ 3,3,3,3
//		4/ 3,3,3,3	24/ 3,3,3,3	Reg. or Pause
//		5/ 2,3,3,3	25/ 3,3,3,3
//		6/ 2,0,3,3	26/ 0,3,3,3
//		7/ 2,0,0,3	27/ 0,0,3,3
//
//TwoAlpha	10/ 3,3,3,3	30/ 3,3,3,3	Jump
//		11/ 3,3,3,3	31/ 3,3,3,3
//		12/ 3,3,3,3	32/ 3,3,3,3
//		13/ 3,3,3,3	33/ 3,3,3,3
//		14/ 3,3,3,3	34/ 3,3,3,3	Reg. or pause
//		15/ 3,3,3,3	35/ 3,3,3,3
//		16/ 2,1,0,3	36/ 1,0,3,3
//		17/ 2,1,0,0	37/ 1,0,0,3
//Note in the above table that 3 is always followed by 3, 1 always by 0,
//2 by 1 if TwoAlphaX else 0 or 3, and 0 by 0 or 3.
	      let DSelifShifted = selecton oldDSel into
	      [ case 0: DMuxTab>>IFU0.DSel
	        case 1: 0
	        case 2: oldTwoAlphaX ? 1,DMuxTab>>IFU0.DSel
	        case 3: 3
	      ]
	      Correct>>IFU0.DSel = T2XLd ne 0 ?
		table [ 3; 3; 3; 3; 3; 2; 2; 2
			 3; 3; 3; 3; 3; 3; 2; 2
			 3; 3; 3; 3; 3; 3; 0; 0
			 3; 3; 3; 3; 3; 3; 1; 1
		 ] ! ((OldDMuxTab!dMX rshift 8) & #37),
		  (T2XShift ne 0 ? DSelifShifted,oldDSel)
	    ]
	    let T1IfuReset1 = T1DTab>>IFU1.IfuReset
	    Correct>>IFU1.Testing = (not T1IfuReset1) &
		(oldTestg ? oldBMUX rshift 1,oldTesting)
	    Correct>>IFU1.TestMakeFgD = (not T1IfuReset1) &
		(oldTestg ? oldBMUX rshift 4,OldDMuxTab>>IFU1.TestMakeFgD)
	  ]
	]

//ProcEnable is false when mufflers are read, forcing these two false
	Correct>>IFU0.XLd = false
	Correct>>IFU0.AlphaXLd = false
	Correct>>IFU0.MLd = NewGoorNoM //% cAlphaXLd

	let DoJump = DMuxTab>>IFU0.DoJump
	let JLd = DMuxTab>>IFU0.JLda
	let LengthK = DMuxTab>>IFU1.LengthK
	let HDv = DMuxTab>>IFU0.HDv
	let FDv = DMuxTab>>IFU0.FDv
	let JDv = DMuxTab>>IFU0.JDv
	let BrkPending = DMuxTab>>IFU1.BrkPending
	let BMuxEnable = DMuxTab>>IFU0.BMuxEnable
	let Testg = DMuxTab>>IFU1.Testg
	let ThreeOutOfFivex = not DMuxTab>>IFU0.ThreeOutOfFive
	let RefOutstandingx = not DMuxTab>>IFU0.RefOutstanding
	let NewF = DMuxTab>>IFU0.NewF
	let LengthM = DMuxTab>>IFU0.LengthM
	let BetaInHx = (LengthM ne 3) % MDvx
	let KReady = DMuxTab>>IFU0.KReady
	let ZapJ = DMuxTab>>IFU0.ZapJ
	let MLd = DMuxTab>>IFU0.MLd
	let SawRamParityErr = DMuxTab>>IFU0.SawRamParityErr
	let SawFGParityErr = DMuxTab>>IFU0.SawFGParityErr

	let MightBeJump = DMuxTab>>IFU0.NewJ & not DMuxTab>>IFU1.TypeJumpKx
	let WantIfuHold = (SawRamParityErr & not RamErrDly) %
		(SawFGParityErr & not FGErrDly)
	let FGDv = FDv % GDv
	let JgH = HDv & LengthK

	Correct>>IFU0.ZapJ = NewGo % (DoJump & not MLdDlyx)
	if NewGo ne 0 then Correct>>IFU0.SawRamParityErr = 0
	if (IfuReset % Testing) ne 0 then Correct>>IFU0.SawFGParityErr = 0

	Correct>>IFU0.IncPcFGx =
		(Tneven ? HDv,not (JLd & not JgH)) % not FGDv

	Correct>>IFU0.EnableFGx = BrkPending % Testing % JgH

	Correct>>IFU0.WantIfuRefx = DMuxTab>>IFU0.Pause % Testing %
		(asel < 4) % (ThreeOutOfFivex & (not NewPcg)) %
		((FFfunc & #330) eq #120)

	let OtherHole =
		(not HDv) & ((not JDv) % MDvx % (GDv & RealPcFG15))
	let GDvandNewForFDv = (GDv & NewF) % FDv
	let notFDvandNewF = not (FDv & NewF)
	Correct>>IFU0.ThreeOutOfFive = DoJump %
		(RefOutstandingx & not GDvandNewForFDv) %
		(OtherHole & not GDvandNewForFDv) %
		(OtherHole & RefOutstandingx & notFDvandNewF) %
		((not FGDv) & (not NewF))

	Correct>>IFU0.KReady = DMuxTab>>IFU0.ValidRam &
		(FGDv % (LengthK ne 3)) & ((LengthK < 2) % HDv)

	Correct>>IFU0.SayNotReady =
		ZapJ % (BetaInHx & (not KReady) & not (JFault & JDv))

	Correct>>IFU0.NewGo = NewPcg % IfuReset
	if Tneven do	//Tneven because T1-clocked IfuReset and Test← used
	[ Correct>>IFU0.TurnOffAlu = IfuReset % BrkPending % BMuxEnable
	  Correct>>IFU0.BMuxEnable = Testg % BrkInsg % NewPcg
//**IfuReset1 = T2IfuReset, should be Tn ne 1
	  Correct>>IFU0.BrkLd = BrkInsg % IfuReset % (FGDv & BrkPending)
	]

	Correct>>IFU0.ValidRam = JDv & (not JFault) & BetaInHx & not NewGo

	Correct>>IFU0.ZapFGH = NewGo % DoJump

	Correct>>IFU0.JLda = ZapJ % (not JDv) % (MLd &
		((KReady & not MightBeJump) % (not BetaInHx)))
	Correct>>IFU0.GLdx = (not ZapFGH) & GDv &
		not (RealPcFG15 & (Tneven ? not HDv,JLd & not JgH))

	Correct>>IFU0.JgOddF =
		(not Tneven) & (not JgH) & (not GDv) & RealPcFG15

	Correct>>IFU0.Exception = ReschedPending % (not KReady) %
		ZapJ % SawFGParityErr % SawRamParityErr %
		((not DMuxTab>>IFU0.HFaultx) & (LengthK ge 2)) %
		(FGFault & (LengthK eq 3))

//Gates for HoldReq are on ContA
	if (NextMacro & WantIfuHold) ne 0 then rv lvHoldReq = 1

	resultis cIfuMARvalx

//Consider adding following:
//	Determine InstrAddr on exceptions and propagate to TNIA;
//	Simulate ←Id data sometimes
]