TamSim.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Krivacic April 10, 1987 12:55:33 pm PST
Last Edited by: Krivacic April 23, 1987 5:36:44 pm PST
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: BOOLFALSE, 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: BOOLFALSE, 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: BOOLFALSE, 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: BOOLFALSE, D1: Word ← ZerosWord] = {
IF clocks.clock AND ~lastIBufDataRegsClock AND clocks.done THEN {
shiftdist: NATSELECT 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: BOOLFALSE] = {
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] ~ {
Performs the add function based on euOp. The various operations are defined below:
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: BOOLTRUE]
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;
The least significant 2 bits are special
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: BOOLFALSE, 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: BOOLFALSE, preCondAddr: NAT] = {
IF interrupt THEN {selPreCond← TRUE; preCondAddr�};
IF reset THEN {selPreCond← TRUE; preCondAddr� 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.