EUAlu.rose
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by: Monier, October 10, 1984 3:27:55 pm PDT
Directory Rope, DragOpsCross;
Imports EUOps, Dragon, RoseTypes, CacheOps, BitOps, DragOpsCrossUtils;
Open EUOps;
Cedar
ALUOpcode: TYPE = {Add, Sub, Or, And, Xor, PassLeft};
preShiftOpcode: TYPE = {ShNop, Sh1R};
postShiftOpcode: TYPE = {ShNop, Sh2R, Sh1R, Sh1L, PassLeft};
mqOpcode: TYPE = {NoOp, Read, Write, Sh2R, Sh1L};
carrySelChoice: TYPE = {Zero, PrevC, PrevCbar, Update, UpdateBar};
Returns a+b+carryIn and carryOut, where a and b are considered to be signed numbers
DoubleADD: PROC[al, bl: Dragon.HexWord, carryIn: BOOL]
RETURNS [sl: Dragon.HexWord, carryOut: BOOL] = {
Xor: PROC[x, y: BOOL] RETURNS [z: BOOL] =
{RETURN[(x AND NOT y) OR (y AND NOT x)]};
ai, bi: BOOL;
s: BOOLFALSE;
c: BOOL ← carryIn;
sum: BitOps.BitDWord ← [0,0];
FOR i: INTEGER IN [1..32] DO
ai ← EBFL[al, 32-i];
bi ← EBFL[bl, 32-i];
s ← Xor[ai, Xor[bi, c]];
c ← Dragon.MoreThanOneOf[ai, bi, c]; -- c ← (ai AND bi) OR (bi AND c) OR (ai AND c);
sum ← BitOps.IBID[s, sum, 32, 32-i];
ENDLOOP;
RETURN[LFD[sum], c]};
Returns a-b-carryIn and carryOut, where a and b are considered to be signed numbers
Implemented as a+(~b)+1+(~carryIn)
DoubleSUB: PROC[a, b: Dragon.HexWord, carryIn: BOOL]
RETURNS [dif: Dragon.HexWord, carryOut: BOOL] ={
[dif, carryOut] ← DoubleADD[a, WordOp[not,b], NOT carryIn]};
Shift1RDtoD: PROC[i0: BOOL, w: Dragon.HexWord] RETURNS [sh: Dragon.HexWord, s31: BOOL] =
BEGIN
s31 ← BitOps.EBFD[LTD[w], 32, 31];
sh ← LFD[BitOps.MDTD[LTD[w], 32, 0 , 31, LTD[sh], 32, 0, 31]];
sh ← BitOps.IBID[i0, LTD[sh], 32, 0];
END;
Shift2RDtoD: PROC[i0, i1: BOOL, w: Dragon.HexWord] RETURNS [sh: Dragon.HexWord, s30, s31: BOOL] =
BEGIN
sh ← LFD[BitOps.MDTD[LTD[w], 32, 0 , 30, LTD[sh], 32, 0, 30]];
sh ← BitOps.IBID[i0, LTD[sh], 32, 0];
sh ← BitOps.IBID[i1, LTD[sh], 32, 1];
s30 ← BitOps.EBFD[LTD[w], 32, 30];
s31 ← BitOps.EBFD[LTD[w], 32, 31];
END;
;
ALUOpcodeCtrl: CELL [
Bits In and Out
EUAluOpAB< EnumType["Dragon.ALUOps"], -- sent on 2A, used during 2B. Not latched by EU.
mqAB30, mqAB31 < BOOL,
carryAB < BOOL,
LeftOpSign < BOOL,
preShiftOp > EnumType["preShiftOpcode"],
postShiftOp > EnumType["postShiftOpcode"],
ALURealOp > EnumType["ALUOpcode"],
mqOp > EnumType["mqOpcode"],
CarryIn > BOOL,
carryBASelect > EnumType["carrySelChoice"],
saveLeftOp > BOOL,
Timing and housekeeping interface
rejectBA < BOOL,
PhA, PhB<BOOL,
ResetAB<BOOL,
Vdd, Gnd, PadVdd, PadGnd<BOOL
]
State
prevSubBA: BOOL, -- Set iff EUAluOpAB=MulStep and ALURealOp=Sub
EvalSimple
IF PhA AND NOT rejectBA THEN {
prevSubBA ← mqAB30; -- for next cycle
};
IF PhB THEN { -- control signals fired during PhB
The default values
preShiftOp    ← ShNop;
postShiftOp    ← ShNop;
ALURealOp    ← PassLeft; -- safe, but in fact not such a common opcode
mqOp      ← NoOp;
CarryIn     ← FALSE; -- Depends on how OR, AND, ..., are implemented
carryBASelect   ← PrevC; -- just recycle
SELECT EUAluOpAB FROM
SAdd => {
ALURealOp   ← Add;
CarryIn     ← carryAB;
carryBASelect  ← Zero;
};
SSub => {
ALURealOp   ← Sub;
CarryIn    ← carryAB;
carryBASelect  ← Zero;
};
UAdd => {
ALURealOp   ← Add;
CarryIn    ← carryAB;
carryBASelect  ← Update;
};
USub => {
ALURealOp   ← Sub;
CarryIn    ← carryAB;
carryBASelect  ← UpdateBar;
};
VAdd => {
ALURealOp   ← Add;
};
VSub => {
ALURealOp   ← Sub;
};
LAdd => {
ALURealOp   ← Add;
carryBASelect  ← Zero;
};
LSub => {
ALURealOp   ← Sub;
carryBASelect  ← Zero;
};
FOP, FOPK => { -- nothing to do, action in the Field Unit
};
And => {
ALURealOp   ← And;
};
Or => {
ALURealOp   ← Or;
};
Xor => {
ALURealOp   ← Xor;
};
BndChk => { -- BC ← NOT ( aluLeft IN [0..aluRight) ), AluOut ← aluLeftBus
postShiftOp   ← PassLeft;
ALURealOp   ← Sub; -- we throw away the result and pass the left op
};
LoadDouble => {
postShiftOp   ← PassLeft; -- load Result2B with LeftOperand (=0 please)
mqOp     ← Write;  -- load mq with RightOperand
};
MulStep => {
zero: BOOL-- 000 or 111
mqAB30 AND mqAB31 AND prevSubBA OR
~mqAB30 AND ~mqAB31 AND ~prevSubBA;
two: BOOL-- 011 or 100
mqAB30 AND ~mqAB31 AND ~prevSubBA OR
~mqAB30 AND mqAB31 AND prevSubBA;
one: BOOL ← ~zero AND ~two; -- the other cases
SELECT TRUE FROM
zero => { -- pass left, shift 2R [aluOut, mqAB] with sign extension
postShiftOp   ← Sh2R; -- with sign extension
mqOp     ← Sh2R; -- left bits from aluOut
};
one => { -- either add or sub, then shift 2R with sign extension
carryBASelect  ← Update;
ALURealOp   ← IF mqAB30 THEN Sub ELSE Add;
postShiftOp   ← Sh2R; -- with sign extension
mqOp     ← Sh2R; -- left bits from aluOut
};
two => { -- shift 1R aluLeft, then add or sub, then shift 1R aluOut
preShiftOp   ← Sh1R;
carryBASelect  ← Update;
ALURealOp   ← IF mqAB30 THEN Sub ELSE Add;
postShiftOp   ← Sh1R; -- sign extension
mqOp     ← Sh2R; -- left bit: aluOut31, LeftOp31
ENDCASE => ERROR};
RdMQ => {
mqOp     ← Read; -- we read mq, i.e. we put its value in Result2B
};
DivStep => {
postShiftOp   ← Sh1L;
ALURealOp   ← Sub;
carryBASelect  ← Update;
mqOp     ← Sh1L; -- left bit from AluOut
saveLeftOp   ← ; -- depends on N, so see timing
};
LastDivStep => { -- same, but shift only mq
};
ENDCASE => ERROR Stop["Invalid ALU Operation"];
};
ENDCELL;
ALUpreShift: CELL [
In and out
LeftOpBus < INT[32],
preShiftOp < EnumType["preShiftOpcode"],
AluLeftBus > INT[32],
LeftOp31 > BOOL,
LeftOpSign > BOOL,
Timing and housekeeping interface
rejectBA < BOOL,
PhA, PhB<BOOL,
ResetAB<BOOL,
Vdd, Gnd, PadVdd, PadGnd<BOOL
]
State
EvalSimple
IF PhA AND NOT rejectBA THEN {
};
IF PhB THEN { -- control signals fired during PhB
LeftOpSign ← BitOps.EBFD[LeftOpBus, 32, 0];
LeftOp31 ← FALSE;
SELECT preShiftOp FROM
ShNop => {AluLeftBus ← LeftOpBus}; -- just pass, for anything but MulStep by 1 or 2
Sh1R => {[AluLeftBus, OpLeft31] ← Shift1RDtoD[FALSE, OpLeftBus]}; -- MulStep by 1 or 2, but probably duplicate the sign bit
ENDCASE => ERROR;
};
ENDCELL;
ALUpostShift: CELL [
In and out
AluOut < INT[32],
AluLeftBus < INT[32],
postShiftOp < EnumType["postShiftOpcode"],
sBus > INT[32],
ALUOut30, ALUOut31 > BOOL,
Timing and housekeeping interface
rejectBA < BOOL,
PhA, PhB<BOOL,
ResetAB<BOOL,
Vdd, Gnd, PadVdd, PadGnd<BOOL
]
State
EvalSimple
IF PhA AND NOT rejectBA THEN {
};
IF PhB THEN { -- control signals fired during PhB
SELECT postShiftOp FROM
ShNop => {sBus ← AluOut}; -- output of the ALU
Sh2R => { -- for MulStep by 0 or 1
[sBus, ALUOut30, ALUOut31] ← Shift2RDtoD[CarryOut, CarryOut, AluOut]; -- sign propagation with the carry
};
Sh1R => { -- for MulStep by 2
[sBus, ALUOut31] ← Shift1RDtoD[CarryOut, AluOut];
};
Sh1L => { -- for DivStep
[] ← Shift1LDtoD[];
};
PassLeft => {sBus ← AluLeftBus}; -- for BndChk and LoadDouble
ENDCASE => ERROR;
-- drive the sBus only if opcode # FOP, FOPK
};
ENDCELL;
ALUmqStuff: CELL [
Data path
RightOpBus < INT[32],
ALUOut30, ALUOut31 < BOOL,
LeftOp31 < BOOL,
mqOp < EnumType["mqOpcode"],
sBus > INT[32],
mqAB30, mqAB31 > BOOL,
Timing and housekeeping interface
rejectBA < BOOL,
PhA, PhB<BOOL,
ResetAB<BOOL,
Vdd, Gnd, PadVdd, PadGnd<BOOL
]
State
mqBA, mqAB: Dragon.HexWord  -- which one is which?
EvalSimple
IF PhA AND NOT rejectBA THEN {
};
IF PhB THEN { -- control signals fired during PhB
SELECT mqOp FROM
NoOp  => {mqBA ← mqAB};
Read  => {sBus ← mqBA};
Write  => {mqBA ← RightOpBus};
Sh2R  =>
Sh1L  =>
ENDCASE => ERROR;
};
ENDCELL;
EUJustALU: CELL [
Data path
AluLeftBus, RightOpBus < INT[32],
CarryIn < BOOL,
ALURealOp < EnumType["ALUOpcode"],
AluOut > INT[32],
CarryOut, Zero, Overflow, AluOut0 > BOOL, -- probably more stuff too
Timing and housekeeping interface
rejectBA < BOOL,
PhA, PhB<BOOL,
ResetAB<BOOL,
Vdd, Gnd, PadVdd, PadGnd<BOOL
]
State
EvalSimple
IF PhA AND NOT rejectBA THEN { -- nothing happens, just precharge
};
IF PhB THEN { -- control signals fired during PhB
CarryOut ← FALSE;    -- is this really the default???
SELECT ALURealOp FROM
Add => {
[AluOut, CarryOut] ← DoubleADD[AluLeftBus, OpRightBus, CarryIn];};
Sub => {
[AluOut, CarryOut] ← DoubleSUB[AluLeftBus, OpRightBus, CarryIn];};
Or => {
AluOut ← WordOp[or, AluLeftBus, OpRightBus];};
And => {
AluOut ← WordOp[and, AluLeftBus, OpRightBus];};
Xor => {
AluOut ← WordOp[xor, AluLeftBus, OpRightBus];};
PassLeft => {
AluOut ← AluLeftBus;};
ENDCASE => ERROR;
AluOut0 ← EBFL[AluOut, 0];
Zero ← AluOut=0;
Overflow ← ;   -- get it from DoubleADD
};
ENDCELL;
EUCarryCtrl: CELL [
Bits in and out
CarryOut < BOOL,
carryBASelect < EnumType["carrySelChoice"],
EUConditionA < BOOL,
carryAB > BOOL,
Timing and housekeeping interface
rejectBA < BOOL,
PhA, PhB<BOOL,
ResetAB<BOOL,
Vdd, Gnd, PadVdd, PadGnd<BOOL
]
State
prevReject: BOOL, -- there was a reject on the previous cycle
carryBA: BOOL -- carryBA is the output of the adder modified by the opcode of the previous operation and latched if no trap; carryAB is a copy of carryBA if there is no reject or fault, but treated as an output, not a state.
EvalSimple
IF PhA AND NOT rejectBA   -- no reject during this PhA
AND NOT prevReject   -- nor on the previous phase
AND NOT EUConditionA  -- no trap expected due to CC
THEN {carryAB ← carryBA};
IF PhB THEN { -- control signals fired during PhB
carryBA ← SELECT carryBASelect FROM
Zero   => 0,
PrevC   => carryAB,
PrevCbar  => NOT carryAB,
Update  => CarryOut, 
UpdateBar => NOT CarryOut,
ENDCASE => ERROR;
prevReject ← rejectBA; -- for the next cycle
};
ENDCELL;
EUConditionCtrl: CELL [
Bits in and out
CarryOut, Zero, Overflow, AluOut0, LeftOpSign < BOOL,
EUCondSelAB < EnumType["Dragon.CondSelects"],
EUConditionA > BOOL, -- The selected condition sent back to IFU during 3A
Timing and housekeeping interface
rejectBA < BOOL,
PhA, PhB<BOOL,
ResetAB<BOOL,
Vdd, Gnd, PadVdd, PadGnd<BOOL
]
State
conditionB: BOOL
EvalSimple
IF PhA AND NOT rejectBA THEN {
EUConditionA ← conditionB;
};
IF PhB THEN { -- control signals fired during PhB
conditionB ← SELECT EUCondSelAB FROM -- see on what phase
False =>  FALSE,
EZ =>   Zero,        -- AluOut=0; (only after a sub!!!)
LZ =>   AluOut0,       -- AluOut<0 (high-order bit)
LE =>   Zero OR AluOut0,     -- AluOut<=0
True =>  TRUE,
NE =>   NOT Zero,      -- AluOut#0
GE =>   NOT AluOut0,     -- AluOut>=0
GZ =>   NOT (Zero OR AluOut0),   -- AluOut>0
OvFl =>  overflow,
BC =>   LeftOpSign OR NOT AluOut0, -- LeftOp NOT IN [0..RightOp)
IL =>    ,         -- wait for Lisp people
DivOvFl => ,
NotOvFl => NOT overflow,
NotBC =>  NOT (LeftOpSign OR NOT AluOut0),
NotIL =>  ,
ENDCASE =>  ERROR Stop["Invalid EUConditionBA Code"];
};
ENDCELL;
EUAlu: CELL [
Large Buses
LeftOpBus < INT[32],
RightOpBus < INT[32],
sBus > INT[32],
saveLeftOp > BOOL,
Mux selectors
EUAluOpAB< EnumType["Dragon.ALUOps"],
EUCondSelAB< EnumType["Dragon.CondSelects"],
EUConditionA> BOOL,
Timing and housekeeping interface
PhA, PhB<BOOL,
ResetAB, rejectBA<BOOL,
Vdd, Gnd, PadVdd, PadGnd<BOOL
]
State
Expand
Internal glue
AluLeftBus: INT[32];
LeftOp31, LeftOpSign: BOOL;
AluOut: INT[32];
preShiftOp: EnumType["preShiftOpcode"];
postShiftOp: EnumType["postShiftOpcode"];
carryBASelect: EnumType["carrySelChoice"];
ALURealOp: ALUOpcode;
AluOut0, ALUOut30, ALUOut31: BOOL;
mqAB30, mqAB31: BOOL;
CarryOut, Zero, Overflow: BOOL;
CarryIn: BOOL;
Blocks
preShift: ALUpreShift[];
postShift: ALUpostShift[];
mqStuff: ALUmqStuff[];
OpcodeCtrl: ALUOpcodeCtrl[];
justALU: EUJustALU[];
CarryCtrl: EUCarryCtrl[];
ConditionCtrl: EUConditionCtrl[];
ENDCELL