Field Descriptor and behavior
The opcode is described by a 13-bit quantity called the field descriptor, which can come from two registers: field, aliased with RAM[euField], and KBusAB, loaded on every PhA from kBus.
Field descriptor: insert(BOOL), mask([0..32]) and shift([0..32]).
The double word (opLBus, opRBus) is left-shifted by shift to produce shiftout. So if shift=0, we have shiftout=opLBus, and if shift=32, shiftout=opRBus.
Two mask are produced: mask1 has mask one's on the right, and mask2 has shift one's on the right.
If insert is FALSE, mask2 is discarded, and the result is AND[shiftout, mask1], which keeps only the shift bits on the right.
If insert is TRUE (ah!ah!), both masks are XORed to form maskHole. Now, the result is formed bitwise as follows: if maskHole=1, then the result is shiftout, and if maskHole=0 the result is opRBus.
The result is finally written onto the sBus if the opcode is FOP or FOPK.
This translates into:
maskHole ← MaskGen[mask] XOR (MaskGen[shift] AND insert)
shiftout ← ShiftLeft[opLBus, opRBus, shift]
result ← (maskHole AND shiftout) OR (~maskHole AND opRBus AND insert)
Shifter
In a first, I used a barrel shifter by even amounts (0, 2, 4, . . . , 30) followed by a shift by one, which saves control lines; however, the saving is pretty small, and the increase in regularity substancial, so I kissed it goodbye and I now use a plain barrel shifter. The inputs are connected directly to opLBus (on top) and opRBus (on the bottom).
Special case for shift = 32, so 33 select lines.
sh0 ← PhB AND (shift=0)
sh1 ← PhB AND (shift=1), and so on
sh31 ← PhB AND (shift=31)
sh32 ← PhB AND (shift =32) -- so don't use shift>32
Mask generators
Both are identical, though their control differ. A mask generator receives a 6-bit input (let's say k), and produces a 32-bit word with k ones on the right (of course the rest is filled with zeros).
***Theory of mask generation . . .***
A touch of theory: let k and i be two n+1-bit numbers, and F[n, k, i]=k>i. By recurring on the high-order bit, we find that
F[n, k, i]=k[n].~i[n] + (k[n]=i[n]). F[n-1, k, i]
F[0, k, i]=k[0].~i[0]
In every slice, i is a constant and k an input. Let's decompose the former equations according to the value of i[n]:
i[n]=0:
F[n, k, i]=k[n] + F[n-1, k, i]=Nand [~k[n], ~F[n-1, k, i]]
F[0, k, i]=k[0]
i[n]=1:
F[n, k, i]=k[n] . F[n-1, k, i]=Nor [~k[n], ~F[n-1, k, i]]
F[0, k, i]=0
Let's define Op[i, n] =if i[n] then Nor else Nand (risky notation, I know!). Then we find that
F[n, k, i]=Op[i, n][~k[n], ~F[n-1, k, i]]=Op[i, n][~k[n], ~Op[i, n-1][~k[n], ~F[n-2, k, i]]].
Now back to the
EU. k is represented on 6 bits, k[5]..k[0]. With some care, we find that the mask can be implemented with an array of
NOR and
NAND as follows:
(1) if i[n]=0 use a Nand, otherwise use a Nor;
(2) if n is odd (5, 3, 1) then inverse the rule (1);
(3) the select lines carrying k are inverted for n=5, 3, 1, and 0;
(4) the first gate collapses into ~k[0] if i is even, and 1 otherwise, which explains (3);
Every slice contains 5 gates, and receives 6 select lines. The output is the mask, not its complement.
Control lines:
mask1Sel[i] ← PhB AND shift[i], for i=2, 4
mask1Sel[i] ← PhB AND ~shift[i], for i=0, 1, 3, 5
mask2Sel[i] ← PhB AND mask[i], for i=2, 4
mask2Sel[i] ← PhB AND ~mask[i], for i=0, 1, 3, 5
Merge box
It merges both masks, using a xor gate, implemented in cascode style. No control line is needed.
Then it produces the result. The only control needed is insert, no timing or holding really necessary.
The equation is:
~insert: mask ← mask1; sBus ← mask AND shiftout
insert: mask ← mask1 XOR mask2; sBus ← (mask AND shiftout) OR (~mask AND opRBus)
This can be summarized as:
mask ← mask1 XOR (mask2 AND insert)
sBus ← (mask AND shiftout) OR (~mask AND opRBus AND insert)
Finally the merge box writes on the sBus.
sBusWrEnable ← PhB AND ~ACERTAINHOLD AND (EUAluOp2AB=FOP OR EUAluOp2AB=FOPK)