<> <> <> <> <<>> DIRECTORY Basics, TamarinBlocks, TamDefs, TamGenDefs; TamSim: CEDAR PROGRAM IMPORTS TamDefs, Basics, TamGenDefs = BEGIN OPEN TamDefs, TamGenDefs; <<-------------------- Service Routines --------------------->> GetClocks: PUBLIC PROC[clocks: ClockRec] RETURNS [clock, clock2, clockstate, writeOk, done, stall: BOOL] = { clock _ clocks.clock; clock2 _ clocks.clock2; clockstate _ clocks.clockstate; writeOk _ clocks.writeOk; done _ clocks.done; stall _ clocks.stall; }; PutClocks: PUBLIC PROC[clock, clock2, clockstate, writeOk, done, stall: BOOL] RETURNS [clocks: ClockRec] = { clocks.clock _ clock; clocks.clock2 _ clock2; clocks.clockstate _ clockstate; clocks.writeOk _ writeOk; clocks.done _ done; clocks.stall _ stall; }; <<>> <<---------------------Register File ------------------>> <<>> banks: NAT = 6; bankSize: NAT = 40; lastRegClock, curRegState: BOOL; curRegAddr: ARRAY BOOL OF NAT; registerArray: ARRAY [0..576) OF TaggedWord; RegisterFile: PUBLIC PROC[r: TaggedWord, uWriteOctal: BOOL, uRD1Addr: rd1addr, uRD2Addr: rd2addr, uDSwap: BOOL, regAddr: NAT, clocks: ClockRec] RETURNS [setd1, setd2: BOOL _ FALSE, d1, d2: TaggedWord]= { clock, clock2, clockstate, writeOk: BOOL; [clock, clock2, clockstate, writeOk] _ GetClocks[clocks]; IF clock2 AND ~lastRegClock THEN { curRegAddr[curRegState] _ regAddr; curRegState _ clockstate; }; d1 _ registerArray[curRegAddr[FALSE]]; d2 _ registerArray[curRegAddr[FALSE]-1]; IF uDSwap THEN {temp: TaggedWord _ d1; d1 _ d2; d2 _ temp;}; setd1 _ uRD1Addr = Raddr; setd1 _ uRD2Addr = PrevRaddr1; IF curRegState AND writeOk THEN registerArray[curRegAddr[TRUE]] _ r; }; <<>> <<>> <<-------------------- Pc Logic --------------------->> curPc, nextPc, fetchPc: Word; validPcBits: PACKED ARRAY[0..7] OF BOOL; lastPcClock: BOOL; <<>> <<>> PcLogic: PUBLIC PROC [r: Word, uRD2Addr: rd2addr, uW2Addr: w2addr, uOpLength, uPcCxt: NAT, uLatchPc: BOOL, cxt: NAT, clocks: ClockRec] RETURNS [d2set: BOOL _ FALSE, d2, pcAddr: Word, wtAddr, rdAddr: NAT, iBufEmpty, iBufFull, opValid: BOOL] = { readclock, writeclock: BOOL; clock, clock2, clockstate, writeOk, done: BOOL; [clock, clock2, clockstate, writeOk, done] _ GetClocks[clocks]; d2 _ OnesWord; readclock _ clock2 AND ~clockstate AND ~lastPcClock; writeclock _ clock2 AND clockstate AND lastPcClock; lastPcClock _ clock2; IF readclock AND (uLatchPc OR done) THEN { curPc _ nextPc; nextPc _ AddDelta[uOpLength, nextPc]; }; IF (uW2Addr = Pc) AND writeclock THEN { nextPc _ r; fetchPc _ r; validPcBits _ [FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE]; }; IF (uRD2Addr = CurrPc) THEN d2 _ curPc; IF (uRD2Addr = NextPc) THEN d2 _ nextPc; pcAddr _ DoubleWordShiftRight[fetchPc, ZerosWord, 2]; wtAddr _ Basics.DoubleAnd[[li[WordToCard[fetchPc]]], [li[7]]].lc; rdAddr _ Basics.DoubleAnd[[li[WordToCard[nextPc]]], [li[7]]]. lc; iBufEmpty _ ~validPcBits[Basics.BITAND[7, rdAddr]]; iBufFull _ validPcBits = [TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE]; opValid _ validPcBits[Basics.BITAND[7, rdAddr]]; }; <<-- Instruction Buffer Latches & State Info>> iBufRegs: ARRAY [0..7] OF Word; lastIBufDataRegsClock, lastIBufDriveClock: BOOL _ FALSE; iBufDataLatch: Word; IBufLogic: PUBLIC PROC[x: Word, uRD1Addr: rd1addr, rdAddr, wtAddr: NAT, wtIBuf: BOOL, opLength: NAT, clocks: ClockRec] RETURNS [setd1: BOOL _ FALSE, d1: Word _ OnesWord, opcode, iBufN: NAT] = { encodeOpLength: ARRAY[0..5] OF NAT = [0FH, 0FH, 0EH, 0CH, 08H, 00H]; ibl, nibl, curIWd, nextIWd, iBSres: Word; clock, clock2, clockstate, writeOk: BOOL; [clock, clock2, clockstate, writeOk] _ GetClocks[clocks]; [ibl, nibl] _ IBufDrive[x, wtIBuf, clocks]; [curIWd, nextIWd] _ IBufReg[ibl, nibl, rdAddr, Basics.BITAND[rdAddr+1, 7], wtAddr]; [iBSres, iBufN, opcode] _ IShifter[curIWd, nextIWd, ShiftAmountEncode[Basics.BITAND[rdAddr, 3]]]; [setd1, d1] _ IBufDataRegs[iBSres, uRD1Addr = IBufData, encodeOpLength[opLength], clocks]; }; ShiftAmountDecode: PROC [shiftlines: NAT] RETURNS [shiftamount: NAT] = { <<-- shiftlines: [8 4 2 1] bit select line for what byte (8 = msb)>> shiftamount _ SELECT shiftlines FROM 8=>0, 4=>8, 2=>16, 1=>24 ENDCASE=> 0; }; ShiftAmountEncode: PROC [shiftamount: NAT] RETURNS [shiftlines: NAT] = { shiftlines _ SELECT shiftamount FROM 0=>8, 8=>4, 16=>2, 24=>1 ENDCASE=> 0; }; DecodeToIndex: PROC [decoder: NAT] RETURNS [index: NAT] = { <<-- decoder: [128, 64, 32, 16, 8 4 2 1] bit select line for index (1 = msb)>> index _ SELECT decoder FROM 128=>0, 64=>1, 32=>2, 16=>3, 8=>4, 4=>5, 2=>6, 1=>7 ENDCASE=> 0; }; IBufDataRegs: PUBLIC PROC [iBSres: Word, selIBufData: BOOL, resetmask: NAT, clocks: ClockRec] RETURNS [setd1: BOOL _ FALSE, D1: Word _ ZerosWord] = { IF clocks.clock AND ~lastIBufDataRegsClock AND clocks.done THEN { shiftdist: NAT _ SELECT resetmask FROM 0=>0, 8=>8, 12=>16, 14=>24, 15=>32, ENDCASE => ERROR; iBufDataLatch _ SingleWordShiftRight[SingleWordShiftLeft[iBSres, shiftdist], shiftdist]; }; lastIBufDataRegsClock _ clocks.clock; IF selIBufData THEN {D1 _ iBufDataLatch; setd1_TRUE}; }; IShifter: PUBLIC PROC [curIWd, nextIWd: Word, sel: NAT] RETURNS [iBSres: Word, ibufN, opCode: NAT] = { shiftDist: NAT _ ShiftAmountDecode[sel]; opCode _ ByteToCard[WordToBytes[DoubleWordShiftRight[curIWd, nextIWd, shiftDist]][3]]; iBSres _ DoubleWordShiftRight[curIWd, nextIWd, shiftDist + 8]; ibufN _ ByteToCard[WordToBytes[iBSres][3]]; }; IBufReg: PUBLIC PROC [ibl, nibl: Word, selCur, selNext, selWrite: NAT] RETURNS [curIWd, nextIWd: Word] = { IF (ibl # OnesWord) OR (nibl # OnesWord) THEN iBufRegs[DecodeToIndex[selWrite]] _ ibl; curIWd _ iBufRegs[DecodeToIndex[selCur]]; nextIWd _ iBufRegs[DecodeToIndex[selNext]]; }; IBufDrive: PUBLIC PROC [xBus: Word, nWtIBuf: BOOL, clocks: ClockRec] RETURNS [ibl, nibl: Word _ OnesWord] = { IF ~clocks.clock AND ~nWtIBuf THEN { ibl _ xBus; nibl _ TamNot[xBus]; }; }; <<---------- Execution Units ----------->> UnitNotImplemented: SIGNAL [euControl: EuControlRec] = CODE; ExecutionUnits: PUBLIC PROC [euControl: EuControlRec, d1, d2: Word, muxBus: SixBitIndex, uEuCC: euccode] RETURNS [setresult: BOOL, result: Word, euCondRes: BOOL] ~ { overFlow, carry, gt: BOOL; <<>> <<-- Do the adder all of the time to set up the condition bits>> [result, overFlow, carry, gt] _ Adder[euControl.adderOp, d1, d2]; setresult _ TRUE; SELECT euControl.euUnit FROM NOP => setresult _ FALSE; Adder => NULL; -- Have already done it LU => result _ LogicalUnit[euControl.luOp, d1, d2]; Shifter => result _ Shifter[d1, d2, muxBus]; Prior => result _ PriorityEncoder[d1]; ENDCASE => SIGNAL UnitNotImplemented[euControl]; euCondRes _ SELECT uEuCC FROM overFlow => overFlow, carry => carry, gt => gt, ENDCASE => TRUE; }; onesInByte: ARRAY [0..256) OF [0..8] = [ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8]; priorityOfByte: ARRAY [0..256) OF INT = [-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7]; Signs: TYPE = MACHINE DEPENDENT { a0b0c0 (0), a0b0c1 (1), a0b1c0 (2), a0b1c1 (3), a1b0c0 (4), a1b0c1 (5), a1b1c0 (6), a1b1c1 (7)}; ALUHelper: PROC [a,b,c: BOOL] RETURNS [Signs] = INLINE { RETURN [LOOPHOLE[ 4*LOOPHOLE[a, CARDINAL] + 2*LOOPHOLE[b, CARDINAL] + LOOPHOLE[c, CARDINAL]]]; }; WordCarryAdd: PROC [wordA, wordB: Word, carryIn: BOOL] RETURNS [wordC: Word, carryOut: BOOL _ FALSE] = { cardA: CARD _ WordToCard[wordA]; cardB: CARD _ WordToCard[wordB]; cardC: CARD _ cardA+cardB; SELECT cardC FROM < cardA, < cardB => carryOut _ TRUE; ENDCASE; IF carryIn THEN {cardC _ cardC+1; IF cardC = 0 THEN carryOut _ TRUE}; wordC _ CardToWord[cardC]; }; Adder: PUBLIC PROC [adderOp: AdderOpType, d1, d2: Word] RETURNS [result: Word, overFlow, carry, gt: BOOL] ~ { <> <<0 => add no carry (d1 + d2)>> <<1 => add with carry (d1 + d2 + 1)>> <<8 => sub no carry (NOT(d1) + d2)>> <<9 => sub with carry (NOT(d1) + d2 + 1)>> carryIn: BOOL _ ((adderOp = tADDC) OR (adderOp = tSUBC)); in1: Word _ d1; IF ((adderOp = tSUB) OR (adderOp = tSUBC)) THEN in1 _ TamXor[d1, OnesWord]; [result, carry] _ WordCarryAdd[in1, d2, carryIn]; SELECT ALUHelper[in1[0], d2[0], result[0]] FROM a0b0c1, a1b1c0 => overFlow _ TRUE; ENDCASE; gt _ IF in1[0] # d2[0] THEN carry ELSE d1[0]; RETURN [result, overFlow, carry, gt] }; <<>> Shifter: PUBLIC PROC [top, bot: Word, shiftAmount: SixBitIndex] RETURNS [shifterResult: Word] ~ { shifterResult _ DoubleWordShiftRight[bot, top, shiftAmount]; RETURN [shifterResult]; }; PriorityEncoder: PUBLIC PROC [inword: Word] RETURNS [result: Word] ~ { inNum: INT _ WordToInt[inword]; bytePriority: INT; i: NAT _ 3; zeroByte: BOOL; bytePriority _ priorityOfByte[Basics.DoubleShiftRight[[li[inNum]], 8*i].li]; zeroByte _ bytePriority = -1; THROUGH [0..2] WHILE zeroByte DO i _ i -1; bytePriority _ priorityOfByte[Basics.DoubleShiftRight[[li[inNum]], 8*i].li]; zeroByte _ bytePriority = -1; ENDLOOP; IF (bytePriority # -1) THEN RETURN [IntToWord[bytePriority + 8*i]] ELSE RETURN [IntToWord[32]]; }; LUOpNotImplemented: SIGNAL [luOp: LuOpType] = CODE; LogicalUnit: PUBLIC PROC [luOp: LuOpType, d1, d2: Word] RETURNS [result: Word] ~ { SELECT luOp FROM tAND => result _ TamAnd[d1, d2]; tXOR => result _ TamXor[d1, d2]; tOR => result _ TamOr[d1, d2]; tNOR => result _ TamNot[TamOr[d1, d2]]; tNAND => result _ TamNot[TamAnd[d1, d2]]; ENDCASE => SIGNAL LUOpNotImplemented[luOp]; RETURN [result]; }; Multiplier: PUBLIC PROC [d1, d2: Word, sgnd: BOOL _ TRUE] RETURNS [resultH, resultL: Word, numCycles0, numCycles1: NAT] ~ { BoothVal: TYPE = {zero, X1, Xminus1, X2, Xminus2}; BoothValArray: TYPE = ARRAY [0..8) OF BoothVal; BoothRec: TYPE = RECORD [ pos: NAT, val: BoothVal]; BoothArray: TYPE = ARRAY [0..16) OF BoothRec; bArray: BoothArray; pos: NAT; val: BoothVal; shiftRL: Word; shiftRH: Word; carry: BOOL; MultShifter: PROC [word: Word, shft: SixBitIndex] RETURNS [resL, resR: Word] ~ { resR _ SingleWordShiftLeft[word, shft]; resL _ DoubleWordShiftLeft[ZerosWord, word, shft]; RETURN [resL, resR]; }; Booth: PROC [word: Word] RETURNS [bArray: BoothArray, numCycles0, numCycles1: NAT] ~ { bva: BoothValArray = [zero, X1, X1, X2, Xminus2, Xminus1, Xminus1, zero]; bv: BoothVal; boothIndex: NAT; wordIndex: NAT _ 32; i: NAT _ 0; numCycles0 _ 0; numCycles1 _ 0; <> boothIndex _ 4*LOOPHOLE[word[wordIndex-2], NAT] + 2*LOOPHOLE[word[wordIndex-1], NAT]; bv _ bva[boothIndex]; IF bv # zero THEN numCycles1 _ 1; bArray[i] _ [wordIndex, bv]; i _ i+1; WHILE wordIndex >= 4 DO wordIndex _ wordIndex -2; boothIndex _ 4*LOOPHOLE[word[wordIndex-2], NAT] + 2*LOOPHOLE[word[wordIndex-1], NAT] + LOOPHOLE[word[wordIndex], NAT]; bv _ bva[boothIndex]; IF bv # zero THEN IF (wordIndex MOD 4 = 0) THEN numCycles1 _ numCycles1 + 1 ELSE numCycles0 _ numCycles0 + 1; bArray[i] _ [wordIndex, bv]; i _ i+1; ENDLOOP; RETURN [bArray, numCycles0, numCycles1]; }; resultH _ resultL _ ZerosWord; IF ~sgnd THEN resultH _ d2; [bArray, numCycles0, numCycles1] _ Booth[d1]; FOR i: INT IN [0..16) DO [pos, val] _ bArray[i]; SELECT val FROM zero => NULL; X1 => { [shiftRH, shiftRL] _ MultShifter[d2, 32-pos]; [resultL, carry] _ WordCarryAdd[resultL, shiftRL, FALSE]; [resultH, carry] _ WordCarryAdd[resultH, shiftRH, carry]; }; Xminus1 => { [shiftRH, shiftRL] _ MultShifter[d2, 32-pos]; shiftRH _ TamNot[shiftRH]; shiftRL _ TamNot[shiftRL]; [resultL, carry] _ WordCarryAdd[resultL, shiftRL, TRUE]; [resultH, carry] _ WordCarryAdd[resultH, shiftRH, carry]; }; X2 => { [shiftRH, shiftRL] _ MultShifter[d2, 32-pos+1]; [resultL, carry] _ WordCarryAdd[resultL, shiftRL, FALSE]; [resultH, carry] _ WordCarryAdd[resultH, shiftRH, carry]; }; Xminus2 => { [shiftRH, shiftRL] _ MultShifter[d2, 32-pos+1]; shiftRH _ TamNot[shiftRH]; shiftRL _ TamNot[shiftRL]; [resultL, carry] _ WordCarryAdd[resultL, shiftRL, TRUE]; [resultH, carry] _ WordCarryAdd[resultH, shiftRH, carry]; }; ENDCASE => ERROR; ENDLOOP; RETURN [resultH, resultL, numCycles0, numCycles1]; }; DpCc: PUBLIC PROC [uDpCC: NAT, d1, d2: TaggedWord] RETURNS [dpCondRes: BOOL] = { dpCondRes _ (TaggedAnd[d1, dpCCodes[uDpCC].d1] = 0) AND (TaggedAnd[d2, dpCCodes[uDpCC].d2] = 0) AND (TaggedAnd[TaggedNot[d1], dpCCodes[uDpCC].nD1] = 0) AND (TaggedAnd[TaggedNot[d2], dpCCodes[uDpCC].nD2] = 0) AND (TaggedAnd[TaggedXor[d1, d2], dpCCodes[uDpCC].d1XorD2] = 0); }; TagUnit: PUBLIC PROC [uTag: tag, d1, d2: TaggedWord] RETURNS [rTag: NAT _ 0] = { rTag_ SELECT uTag FROM Int => 0, D2b87 => 0, D1 => d1.tag, D2 => d2.tag, ENDCASE => ERROR; }; temp1, newTemp1: TaggedWord; lastSpecialRegsClock: BOOL; SpecialRegs: PUBLIC PROC [r: TaggedWord, uRD1Addr: rd1addr, uRD2Addr: rd2addr, uW2Addr: w2addr, clocks: ClockRec] RETURNS [d1set, d2set: BOOL _ FALSE, d1, d2: TaggedWord] = { clock, clock2, clockstate, writeOk: BOOL; [clock, clock2, clockstate, writeOk] _ GetClocks[clocks]; IF clock AND ~lastSpecialRegsClock THEN temp1 _ newTemp1; IF uW2Addr = Temp1 THEN newTemp1 _ r; lastSpecialRegsClock _ clock; IF uRD1Addr = Temp1 THEN {d1set _ TRUE; d1 _ temp1; }; IF uRD2Addr = Temp1 THEN {d2set _ TRUE; d2 _ temp1; }; }; <<------------- Memory Control -------------->> TLB: PUBLIC PROC[d1, r: Word, muxBus: NAT, pcAddr: Word, clockTlb, selPcAddr: BOOL, clocks: ClockRec] RETURNS [pa: CARD, pageFault, tlbMis: BOOL] = { <<-- Select address of d1 or pcAddr based on selPcAddr clockTlb indicates when to store a Tlb entry from the R bus >> pageFault _ FALSE; tlbMis _ FALSE; pa _ WordToCard[IF selPcAddr THEN pcAddr ELSE d1]; }; fakeMemory: ARRAY [0..1000] OF FullWord; MemBuffer: PUBLIC PROC[d2: TaggedWord, muxBus: NAT, xIntoChip: FullWord, pa: CARD, latchMemBuffer, writeMemBufferlo, writeMemBufferhi: BOOL] RETURNS [r: TaggedWord, xOutofChip: FullWord, xBits: XBitRec] = { <<-- NOTE where are the xBITS coming from on a WRITE? -------->> xOutofChip _ [[0, 0], d2]; IF latchMemBuffer THEN { r _ fakeMemory[pa].tagWord; xBits _ fakeMemory[pa].xBits; }; IF writeMemBufferlo THEN fakeMemory[pa].tagWord _ d2; IF writeMemBufferhi THEN fakeMemory[pa].xBits _ [0,0]; }; MemCtl: PUBLIC PROC[dpCc, opValid, iBufFull, iBufEmpty, pageFault: BOOL, uCycle: cycle] RETURNS [memCtlCondRes, wtIBuf, latchMemBuffer, writeMemBufferlo, writeMemBufferhi, selPcAddr, clockTlb: BOOL _ FALSE] = { selPcAddr _ ~opValid OR ((uCycle = None) AND ~iBufFull); clockTlb _ FALSE; memCtlCondRes _ TRUE; latchMemBuffer _ ~selPcAddr AND ((uCycle=R40) OR (uCycle=RWAccess)); writeMemBufferlo _ ~selPcAddr AND ((uCycle=W34) OR (uCycle=W40)); writeMemBufferhi _ ~selPcAddr AND ((uCycle=W6) OR (uCycle=W40)); }; <<----------------- Condition Code Logic -------------->> CCodeMux: PUBLIC PROC[regMuxCondRes, euCondRes, dpCondRes, memCtlCondRes: BOOL] RETURNS [condRes: BOOL] = { condRes _ regMuxCondRes AND euCondRes AND dpCondRes AND memCtlCondRes; }; PreCond: PUBLIC PROC[reset, interrupt: BOOL] RETURNS [selPreCond, forceNewOp: BOOL _ FALSE, preCondAddr: NAT] = { IF interrupt THEN {selPreCond_ TRUE; preCondAddr_100;}; IF reset THEN {selPreCond_ TRUE; preCondAddr_100; forceNewOp_TRUE;}; }; UCodeCtl: PUBLIC PROC[condRes, uInvertSide, uWriteT, uWriteF, forceNewOp: BOOL] RETURNS [writeOk, selA: BOOL] = { writeOk _ ((condRes AND uWriteT) OR (~condRes AND uWriteF)) AND ~forceNewOp; selA _ condRes OR forceNewOp; }; UCodeMux: PUBLIC PROC[selPreCond: BOOL, preCondAddr, opcode, uAAddr: NAT, uADone: BOOL] RETURNS [aAddr: NAT] = { aAddr _ IF uADone THEN IF selPreCond THEN preCondAddr ELSE opcode ELSE uAAddr;}; latchedUCode: UCodeWord; lastUCodeClock: BOOL; UCode: PUBLIC PROC[aAddr, uBaddr: NAT, selA: BOOL, clocks: ClockRec] RETURNS [mi: UCodeWord] = { clock, clock2, clockstate, writeOk: BOOL; [clock, clock2, clockstate, writeOk] _ GetClocks[clocks]; IF clock AND ~lastUCodeClock THEN latchedUCode _ uCode[IF selA THEN aAddr ELSE uBaddr]^; lastUCodeClock _ clock; mi _ latchedUCode; }; <<--------------- RegContext --------------->> topCxt, botCxt, currCxt: NAT; Context: PUBLIC PROC[newuRCxt, uWCxt, uNewTopCxt, uNewBotCxt: BOOL, uAltCxt: altcxt, clocks: ClockRec] RETURNS [regCxt: NAT] = { cxt: ARRAY BOOL OF NAT _ [ currCxt, SELECT uAltCxt FROM Top => topCxt, NextTop => IF topCxt = 5 THEN 0 ELSE topCxt+1, PrevTop => IF topCxt = 0 THEN 5 ELSE topCxt-1, Bot => botCxt, NextBot => IF botCxt = 5 THEN 0 ELSE botCxt+1, PrevBot => IF botCxt = 0 THEN 5 ELSE botCxt-1, K => 0, Global => 6, ENDCASE => 0 ]; regCxt _ cxt[IF clocks.clockstate THEN newuRCxt ELSE uWCxt]; }; <<>> <<>> <<--------------- RegMux --------------->> arg, arg2, tos, nextArg, nextArg2, nextTos: NAT; lastRegMuxClock: BOOL _ FALSE; RegMux: PUBLIC PROC[cxt: NAT, uTos, uArg, uArg2: MuxRec, uOpMask: opmask, uK, uK2: NAT, uWaddr: waddr, uMuxBus: muxbus, newuRaddr: raddr, newuK, iBufN, opcode: NAT, clocks: ClockRec, d2, r: Word] RETURNS [regAddr, regMuxCondRes, muxBus: NAT] = { NewReg: PROC[val: NAT, ufields: MuxRec] RETURNS [newval: NAT] = { newval _ (IF ufields.selReg THEN tos ELSE 0) + ((IF ufields.selOp THEN 1 ELSE -1) * (IF ufields.selMux THEN muxBus ELSE 0)) + (IF ufields.selIncr THEN 1 ELSE 0); }; clock, clock2, clockstate, writeOk: BOOL; [clock, clock2, clockstate, writeOk] _ GetClocks[clocks]; <<-- Mask Opcode >> opcode _ SELECT uOpMask FROM None => opcode, b0111 => Basics.BITAND[opcode, 7], b1111 => Basics.BITAND[opcode, 0FH], ENDCASE => 0; <<-- Latch new Register Values on Clock>> IF clock AND ~clockstate AND ~lastRegMuxClock AND writeOk THEN { arg_ nextArg; arg2 _ nextArg2; tos _ nextTos; }; lastRegMuxClock _ clock; <<-- Set MuxBus Value>> muxBus _ SELECT uMuxBus FROM Tos => tos, Arg => arg, Arg2 => arg2, IBufN => iBufN, K => uK, K2 => uK2, D2 => tos , R => tos, ENDCASE => tos; <<-- Set the New Register Values>> nextTos _ NewReg[tos, uTos]; nextArg _ NewReg[arg, uArg]; nextArg2 _ NewReg[arg2, uArg2]; <<-- Select the Register Address>> cxt _ Basics.BITSHIFT[cxt, 6]; IF clockstate THEN { -- Next address is Read address IF newuRaddr=K THEN cxt _ 0; regAddr _ Basics.BITOR[cxt, SELECT newuRaddr FROM Tos => nextTos, Arg => nextArg, Arg2 => nextArg2, IBufN => iBufN, Opcode => opcode, K => newuK, ENDCASE => newuK ]; } ELSE { IF uWaddr=K THEN cxt _ 0; regAddr _ Basics.BITOR[cxt, SELECT uWaddr FROM NewTos => nextTos, NewArg => nextArg, NewArg2 => nextArg2, IBufN => iBufN, Opcode => opcode, K => newuK, ENDCASE => newuK ]; }; }; END.