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] ~ {
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:
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;
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:
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};
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
];
};
};