// DCPProms.bcpl -- Dicentra Central Processor Proms // Last modified November 28, 1982 5:35 AM by Boggs external [ Ws; OpenFile; Puts; Closes; TruncateDiskStream; CallSwat; Multibus ] static [ memory; mbFile ] structure String [ length byte; char↑1,1 byte ] manifest [ high = 1; low = 0 ] //----------------------------------------------------------------------------------------- let DCPProms() be //----------------------------------------------------------------------------------------- [ mbFile = OpenFile("DCPProms.mb") DoMemory("Stack", 512, 8, Stack) DoMemory("IB", 512, 8, IB) DoMemory("ALUHigh", 512, 8, ALUHigh) DoMemory("FX", 512, 8, FX) DoMemory("FYZ", 512, 8, FYZ) DoMemory("FY1", 512, 8, FY1) DoMemory("FY2", 512, 8, FY2) DoMemory("FZ1", 512, 8, FZ1) DoMemory("FZ2", 512, 8, FZ2) DoMemory("Trap", 512, 8, Trap) DoMemory("Multibus", 512, 24, Multibus) Puts(mbFile, 0) //0 = end of file TruncateDiskStream(mbFile) Closes(mbFile) ] //----------------------------------------------------------------------------------------- and DoMemory(name, nAddr, nData, Proc) be //----------------------------------------------------------------------------------------- // nAddr is number of addresses; nData is number of output bits [ Ws("*N"); Ws(name) Puts(mbFile, 4) //4 = define memory memory = memory +1 Puts(mbFile, memory) Puts(mbFile, nData) // Write Asciz string to word stream. What a pain! if name>>String.length gr 1 then for i = 1 to name>>String.length-1 by 2 do Puts(mbFile, name>>String.char↑i lshift 8 + name>>String.char↑(i+1)) Puts(mbFile, (name>>String.length & 1) eq 0? 0, name>>String.char↑(name>>String.length) lshift 8) Puts(mbFile, 2) //2 = set current memory Puts(mbFile, memory) Puts(mbFile, 0) //location counter let data = vec 1; if nData gr 32 then CallSwat("increase data vector size") for addr = 0 to nAddr-1 do [ Puts(mbFile, 1) //1 = memory contents Puts(mbFile, 0) //0 = source line number (not used) Proc(addr, data) for i = 0 to (nData+15)/16 -1 do Puts(mbFile, data!i) ] ] //----------------------------------------------------------------------------------------- and Stack(addr, data) be //----------------------------------------------------------------------------------------- [ structure Addr: [ blank bit 7 StackP bit 4 PopX bit PopZ bit PushX bit PushY bit PushZ bit ] structure Data: [ StackTrap bit blank bit 3 StackP bit 4 blank bit 8 ] let PopX = addr<<Addr.PopX eq high let PopZ = addr<<Addr.PopZ eq high let PushX = addr<<Addr.PushX eq high let PushY = addr<<Addr.PushY eq high let PushZ = addr<<Addr.PushZ eq high let StackP = addr<<Addr.StackP let Pop = PopX % PopZ let Push = PushX % PushY % PushZ let StackTrap = Pop & StackP eq 0 % Push & StackP eq 15 % PopX & Push & StackP eq 0 % Push & PopZ & StackP eq 15 % PopX & PopZ & (StackP eq 0 % StackP eq 1) % PopX & PopZ & Push & (StackP eq 0 % StackP eq 1) if Pop then StackP = StackP -1 if Push then StackP = StackP +1 data>>Data.StackP = StackP data>>Data.StackTrap = StackTrap? high, low ] //----------------------------------------------------------------------------------------- and IB(addr, data) be //----------------------------------------------------------------------------------------- [ manifest [ // instruction buffer states ibEmpty = 0 ibByte = 1 ibFull = 2 ibWord = 3 ] structure Addr: [ blank bit 7 IBDisp bit ReadIB bit WriteIB bit IBPtrGetsWord bit IBPtrGetsByte bit EnC2Funs bit Interrupt bit InIBPtr bit 2 unused bit ] structure Data: [ GoodIBDisp bit IBEmpty bit //low true IBRefillTrap bit ReadIB0 bit //low true ReadIB1 bit //low true WriteIBFront bit OutIBPtr bit 2 blank bit 8 ] let IBDisp = addr<<Addr.IBDisp eq high let ReadIB = addr<<Addr.ReadIB eq high let WriteIB = addr<<Addr.WriteIB eq high let IBPtrGetsWord = addr<<Addr.IBPtrGetsWord eq high let IBPtrGetsByte = addr<<Addr.IBPtrGetsByte eq high let EnC2Funs = addr<<Addr.EnC2Funs eq high let Interrupt = addr<<Addr.Interrupt eq high let InIBPtr = addr<<Addr.InIBPtr let IBEmpty = false let IBRefillTrap = false let GoodIBDisp = false let ReadIB0 = false let ReadIB1 = false let WriteIBFront = false let OutIBPtr = InIBPtr let advance = false // IBRefillTrap causes a trap to one of four locations executed in Cycle 1: // 3400b or 3000b Interrupt // 2400b IB refill; IB not empty // 2000b IB refill; IB is empty if IBDisp & EnC2Funs & not ReadIB & not WriteIB & not IBPtrGetsWord then test (Interrupt % InIBPtr ne ibFull) & not IBPtrGetsByte ifso IBRefillTrap = true ifnot [ GoodIBDisp = true; advance = true ] // ReadIB puts IBFront onto the X bus and advances IBPtr. // Since there are always at least 2 bytes in the buffer when we begin // executing a Mesa instruction, ReadIB can't trap. // Note that "ReadIB, IBDisp" is not legal (its a Noop). if ReadIB & not IBDisp & not WriteIB & not IBPtrGetsWord & not IBPtrGetsByte then advance = true if advance then [ WriteIBFront = true ReadIB0 = (InIBPtr & 1) eq 0 //ReadIB0 is the inverse of IBPtr.1 ReadIB1 = not ReadIB0 OutIBPtr = selecton InIBPtr into [ case ibFull: ibWord case ibWord: ibByte case ibByte: ibEmpty case ibEmpty: ibEmpty ] ] // Unless we are refilling due to a jump instruction, IBPtr will be ibByte or ibEmpty. // If it's ibEmpty then we need to write IBFront from IB0. // If it's ibByte then we shouldn't write IBFront. // If we are refilling due to a jump instruction, IBPtr value is unknown. // It will be specified by a IBPtr← in this cycle or the next. // Note that "WriteIB, ReadIB" is not legal (it's a Noop). if WriteIB & not IBDisp & not ReadIB test InIBPtr eq ibEmpty ifso [ WriteIBFront = true test IBPtrGetsByte ifso [ ReadIB1 = true; OutIBPtr = ibByte ] ifnot [ ReadIB0 = true; OutIBPtr = ibWord ] ] ifnot OutIBPtr = ibFull // IBPtr←byte or IBPtr←word always come in cycle 1 immediately after a WriteIB. // They load IBFront with the even or odd dest byte and set up IBPtr. if IBPtrGetsWord & not IBDisp & not ReadIB & not WriteIB & not IBPtrGetsByte then [ WriteIBFront = true ReadIB0 = true OutIBPtr = ibWord ] if IBPtrGetsByte & not IBDisp & not ReadIB & not WriteIB & not IBPtrGetsWord then [ WriteIBFront = true ReadIB1 = true OutIBPtr = ibByte ] data>>Data.IBEmpty = OutIBPtr eq ibEmpty? low, high data>>Data.IBRefillTrap = IBRefillTrap? high, low data>>Data.GoodIBDisp = GoodIBDisp? high, low data>>Data.ReadIB0 = ReadIB0? low, high data>>Data.ReadIB1 = ReadIB1? low, high data>>Data.WriteIBFront = WriteIBFront? high, low data>>Data.OutIBPtr = OutIBPtr ] //----------------------------------------------------------------------------------------- and ALUHigh(addr, data) be //----------------------------------------------------------------------------------------- [ structure Addr: [ blank bit 7 paS0 bit paS1 bit paS2 bit paF1 bit paF2 bit pMem bit Cycle3 bit Cycle2 bit blank bit ] structure Data: [ aSh0 bit aSh1 bit aSh2 bit aFh1 bit aFh2 bit ReadMD bit //low true blank bit 2 blank bit 8 ] let paS0 = addr<<Addr.paS0 eq high let paS1 = addr<<Addr.paS1 eq high let paS2 = addr<<Addr.paS2 eq high let paF1 = addr<<Addr.paF1 eq high let paF2 = addr<<Addr.paF2 eq high let pMem = addr<<Addr.pMem eq high let Cycle3 = addr<<Addr.Cycle3 eq high let Cycle2 = addr<<Addr.Cycle2 eq high data>>Data.aSh0 = (pMem & Cycle3? false, paS0)? high, low data>>Data.aSh1 = (pMem & Cycle3? true, paS1)? high, low data>>Data.aSh2 = (pMem & Cycle3? true, paS2)? high, low data>>Data.aFh1 =(pMem & Cycle3? true, paF1)? high, low data>>Data.aFh2 =(pMem & Cycle3? true, paF2)? high, low data>>Data.ReadMD = pMem & Cycle2? low, high ] //----------------------------------------------------------------------------------------- and FX(addr, data) be //----------------------------------------------------------------------------------------- [ structure Addr: [ blank bit 7 pfX bit 4 blank bit 5 ] structure Data: [ blank bit WriteRH bit Shift bit //low true CycleX bit //low true CInGetsPC16X bit //low true MapRefX bit //low true PopX bit PushX bit blank bit 8 ] let FX = addr<<Addr.pfX data>>Data.WriteRH = FX eq 9? high, low data>>Data.Shift = FX eq 10? low, high data>>Data.CycleX = FX eq 11? low, high data>>Data.CInGetsPC16X = FX eq 12? low, high data>>Data.MapRefX = FX eq 13? low, high data>>Data.PopX = FX eq 14? high, low data>>Data.PushX = FX eq 15? high, low ] //----------------------------------------------------------------------------------------- and FYZ(addr, data) be //----------------------------------------------------------------------------------------- [ structure Addr: [ blank bit 7 pfS01 bit 2 pfS23 bit 2 pfZ01 bit 2 = [ pfZ0 bit pfZ1 bit ] pfY0 bit pfY1 bit blank bit ] structure Data: [ Zero bit //low true IB bit //low true Rot bit //low true Byte bit //low true Const bit //low true FourBitBr bit //low true TwoBitBr bit //low true OneBitBr bit //low true blank bit 8 ] let pfS01 = addr<<Addr.pfS01 let pfS23 = addr<<Addr.pfS23 let pfZ01 = addr<<Addr.pfZ01 let pfZ0 = addr<<Addr.pfZ0 eq high let pfY0 = addr<<Addr.pfY0 eq high let pfY1 = addr<<Addr.pfY1 eq high data>>Data.Zero = (pfS23 eq 1 % (pfS23 eq 3 & pfZ0))? low, high data>>Data.IB = (pfS23 eq 3 & pfZ01 eq 3)? low, high data>>Data.Rot = (pfS23 eq 0 & pfZ01 eq 3)? low, high data>>Data.Byte = pfS01 eq 3? low, high data>>Data.Const = pfS23 eq 1? low, high data>>Data.FourBitBr = (pfS01 eq 0 & pfY0 & not pfY1)? low, high data>>Data.TwoBitBr = (pfS01 eq 0 & pfY0)? low, high data>>Data.OneBitBr = (pfS01 eq 0 & not pfY0)? low, high ] //----------------------------------------------------------------------------------------- and FY1(addr, data) be //----------------------------------------------------------------------------------------- [ structure Addr: [ blank bit 7 pfY bit 4 pfS01 bit 2 blank bit 3 ] structure Data: [ WriteDebA bit //low true WriteExtCtrl bit ClrIntTrap bit //low true IBDisp bit SetInterrupt bit WriteStkP bit WriteIB bit CycleY bit //low true blank bit 8 ] let pfY = addr<<Addr.pfY let pfS01 = addr<<Addr.pfS01 data>>Data.WriteDebA = (pfS01 eq 2 & pfY eq 0)? low, high data>>Data.WriteExtCtrl = (pfS01 eq 2 & pfY eq 1)? high, low data>>Data.ClrIntTrap = (pfS01 eq 1 & pfY eq 2)? low, high data>>Data.IBDisp = (pfS01 eq 1 & pfY eq 3)? high, low data>>Data.SetInterrupt = (pfS01 eq 1 & pfY eq 4)? high, low data>>Data.WriteStkP = (pfS01 eq 1 & pfY eq 5)? high, low data>>Data.WriteIB = (pfS01 eq 1 & pfY eq 6)? high, low data>>Data.CycleY = (pfS01 eq 1 & pfY eq 7)? low, high ] //----------------------------------------------------------------------------------------- and FY2(addr, data) be //----------------------------------------------------------------------------------------- [ structure Addr: [ blank bit 7 pfY bit 4 pfS01 bit 2 blank bit 3 ] structure Data: [ blank bit MapRefY bit //low true blank bit PushY bit IORefY bit //low true WriteBank bit BHEN bit RawRef bit blank bit 8 ] let pfY = addr<<Addr.pfY let pfS01 = addr<<Addr.pfS01 data>>Data.MapRefY = (pfS01 eq 1 & pfY eq 9)? low, high data>>Data.PushY = (pfS01 eq 1 & pfY eq 11)? high, low data>>Data.IORefY = ((pfS01 eq 1 % pfS01 eq 2) & pfY eq 12)? low, high data>>Data.WriteBank = (pfS01 eq 1 & pfY eq 13)? high, low data>>Data.BHEN = (pfS01 eq 2 & (pfY eq 12 % pfY eq 14 % pfY eq 15))? low, high data>>Data.RawRef = ((pfS01 eq 1 % pfS01 eq 2) & pfY eq 14)? high, low ] //----------------------------------------------------------------------------------------- and FZ1(addr, data) be //----------------------------------------------------------------------------------------- [ structure Addr: [ blank bit 7 pfZ bit 4 pfS23 bit 2 blank bit 3 ] structure Data: [ ADR0 bit IBPtrGetsByte bit IBPtrGetsWord bit CInGetsPC16Z bit //low true IORefZ bit //low true PopZ bit PushZ bit AltUAddr bit blank bit 8 ] let pfZ = addr<<Addr.pfZ let pfS23 = addr<<Addr.pfS23 data>>Data.ADR0 = (pfS23 eq 3 & pfZ eq 0)? high, low data>>Data.IBPtrGetsByte = (pfS23 eq 0 & pfZ eq 1)? high, low data>>Data.IBPtrGetsWord = (pfS23 eq 0 & pfZ eq 2)? high, low data>>Data.CInGetsPC16Z = (pfS23 eq 0 & pfZ eq 3)? low, high data>>Data.IORefZ = (pfS23 eq 3 & pfZ eq 7)? low, high data>>Data.PopZ = (pfS23 eq 0 & pfZ eq 5)? high, low data>>Data.PushZ = (pfS23 eq 0 & pfZ eq 6)? high, low data>>Data.AltUAddr = (pfS23 eq 0 & pfZ eq 7)? high, low ] //----------------------------------------------------------------------------------------- and FZ2(addr, data) be //----------------------------------------------------------------------------------------- [ structure Addr: [ blank bit 7 pfZ bit 4 pfS23 bit 2 blank bit 3 ] structure Data: [ ReadDebB bit //low true ReadExtStat bit //low true ReadMisc bit //low true ReadRH bit //low true blank bit ReadIB bit blank bit IBHigh bit //low true blank bit 8 ] let pfZ = addr<<Addr.pfZ let pfS23 = addr<<Addr.pfS23 data>>Data.ReadDebB = (pfS23 eq 3 & pfZ eq 8)? low, high data>>Data.ReadExtStat = (pfS23 eq 3 & pfZ eq 6)? low, high data>>Data.ReadMisc = (pfS23 eq 3 & pfZ eq 10)? low, high data>>Data.ReadRH = (pfS23 eq 3 & pfZ eq 11)? low, high data>>Data.ReadIB = (pfS23 eq 3 & pfZ eq 13)? high, low data>>Data.IBHigh = (pfS23 eq 3 & pfZ eq 15)? low, high ] //----------------------------------------------------------------------------------------- and Trap(addr, data) be //----------------------------------------------------------------------------------------- [ manifest [ // These bits appear inverted on X[8-9] when fZ = XLow←Misc. // If X[8-9] = zero then a control store parity error occured. stateIBEmpty = 0 stateStack = 1 stateInit = 2 stateNoTrap = 3 stateParity = 3 ] structure Addr: [ blank bit 7 CurrentState bit 2 TrapIn bit IBEmptyTrap bit //low true StackTrap bit InitTrap bit //low true ParityTrap bit ClrIntTrap bit //low true Cycle1 bit ] structure Data: [ NextState bit 2 Trap bit ParityLED bit //low true ForceBank0 bit blank bit 3 blank bit 8 ] let CurrentState = addr<<Addr.CurrentState let IBEmptyTrap = addr<<Addr.IBEmptyTrap eq low let StackTrap = addr<<Addr.StackTrap eq high let InitTrap = addr<<Addr.InitTrap eq low let ParityTrap = addr<<Addr.ParityTrap eq high let ClrIntTrap = addr<<Addr.ClrIntTrap eq low let Cycle1 = addr<<Addr.Cycle1 eq high let TrapIn = addr<<Addr.TrapIn eq high let NextState = CurrentState let Trap = false // The Trap machine only remembers one trap. If multiple traps occur, // only one of them is reported. The priority of reporting is: // InitTrap - highest priority // ParityTrap // StackTrap // IBEmptyTrap - lowest priority // If a trap occurs in an instruction which clears traps, the new trap still takes. // The instruction at location 0 must read the trap type (XBus←Misc) and // clear the trap (ClrIntTrap), or else another trap will occur. // InitTrap causes a continuous Trap regardless of the cycle. // The CP repeatedly executes the instruction at location 0. // The Multibus FSM loops in Cycle 1. // The control store bank is forced to 0. // When InitTrap goes away, the processor takes off from location 0 in cycle 1. // The instruction at location 0, which the CP repeatedly executes while // Init is asserted, contains fY = ClrIntTrap. Unless inhibited, this will // cause the trap machine to forget its mission 3 cycles before the processor // is finally released from its chains. TrapIn detects this peculiar // combination and remembers it long enough to inhibit ClrIntTrap until the last // time that that magic instruction at location 0 is executed. if ClrIntTrap & CurrentState eq stateInit & (TrapIn % not Cycle1) then ClrIntTrap = false if ClrIntTrap then NextState = stateNoTrap if IBEmptyTrap & CurrentState eq stateNoTrap then NextState = stateIBEmpty if StackTrap & (CurrentState eq stateNoTrap % CurrentState eq stateIBEmpty) then NextState = stateStack if ParityTrap & CurrentState ne stateInit then NextState = stateParity if InitTrap then NextState = stateInit // Trap must be asserted during Cycle 2, so we must decide to assert it during Cycle 1. // A Trap causes the address loaded into NIA at the end of cycle 2 to be zero. // The instruction at location 0 is fetched in cycle 3 and executed in cycle 1. if Cycle1 & (NextState ne stateNoTrap % ParityTrap) then Trap = true // ParityTrap is a level (JK-FF) rather than a 1-cycle pulse like the rest of the traps. // This is fortunate since the trap mechanism has only 2 state bits but has 5 states: // NoTrap, IBEmpty, Stack, Parity, Init. // InitTraps and ParityTraps go to location 0 in bank 0. // All other traps go to location 0 in the current bank. // This trap handler might just pass control to the trap handler in bank 0. data>>Data.NextState = NextState data>>Data.ParityLED = ParityTrap? low, high data>>Data.ForceBank0 = (Trap & ParityTrap) % InitTrap? high, low data>>Data.Trap = Trap? high, low ]