§ 2.3. Shifts and Rotations¶
BarrelShifter8 provides variable-distance shifts and rotations for ALU8. It operates on eight-bit words and reports the last shifted-out bit separately from the result.
| Component | Description | Structural | Behavioral |
|---|---|---|---|
BarrelShifter8 |
Shifts or rotates an eight-bit word by zero through seven positions and reports the carry/last shifted-out bit | Yes | Yes |
These columns indicate registered simulator implementations; the simplified C++ examples below are not counted.
The combinational and bit-numbering conventions from 2.1. Arithmetic Components apply here. The simplified C++ example describes binary behavior, not the simulator implementation; it omits propagation delays and X/Z handling.
2.3.1. BarrelShifter8¶
BarrelShifter8 selects a shift or rotation of A by zero through seven bit positions. The result is produced by a structural multiplexer network, not by a clocked sequence of shifts.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
A |
Input | 8 | Word to shift or rotate |
B |
Input | 8 | Shift distance in bits 2–0; bits 7–3 are ignored |
OP |
Input | 3 | Local shift/rotation selector |
C_IN |
Input | 1 | Carry value returned for a valid operation with distance zero |
OUT |
Output | 8 | Shifted or rotated word |
CARRY |
Output | 1 | Last shifted-out bit, or C_IN for distance zero |
There are no OVERFLOW, ZERO, NEGATIVE, or INVALID_OP pins on this component.
Behavior¶
The effective distance is
Thus B = 0x08 means distance zero, not a shift by eight; B = 0xFF means distance seven.
Local OP |
Operation | Movement and fill | Complete ALU8.OP |
|---|---|---|---|
0b000 |
SLL |
Shift left; fill low bits with zero | 0x10 |
0b001 |
SRL |
Shift right; fill high bits with zero | 0x11 |
0b010 |
SRA |
Shift right; fill high bits with the original A[7] |
0x12 |
0b011 |
ROL |
Rotate left; wrap shifted-out high bits into low positions | 0x13 |
0b100 |
ROR |
Rotate right; wrap shifted-out low bits into high positions | 0x14 |
0b101–0b111 |
Reserved | OUT = 0, CARRY = 0, regardless of other inputs |
No corresponding shift operation |
The reserved local selections are not a global invalid-opcode table: global codes 0x15–0x17 select comparison operations in the complete ALU. The top-level decoder determines which subunit's output is used.
For every valid operation at n = 0, OUT = A and CARRY = C_IN. For 1 ≤ n ≤ 7, the low eight result bits are
Here \(s(A)\) is the two's-complement interpretation from 2.1. For negative operands, arithmetic right shift rounds toward negative infinity; it is not C++ signed division's truncation toward zero.
Carry and ignored inputs¶
| Operation | CARRY when n > 0 |
|---|---|
SLL, ROL |
Original A[8 - n] |
SRL, SRA, ROR |
Original A[n - 1] |
C_IN does not supply a fill bit and never enters OUT. For nonzero distance it is ignored, including by the rotations. ROL and ROR rotate eight bits, not a nine-bit word containing carry. These carry rules report the last bit shifted out, not whether any discarded bit was 1.
C++ example¶
#include <cstdint>
struct Shift8Result {
std::uint8_t OUT;
bool CARRY;
};
Shift8Result shift8_ref(
std::uint8_t a, std::uint8_t b, std::uint8_t op, bool c_in) {
if (op > 4) return {0, false};
const unsigned n = unsigned(b) & 7u;
if (n == 0) return {a, c_in};
const unsigned x = a;
unsigned result = 0;
switch (op) {
case 0: result = x << n; break; // SLL
case 1: result = x >> n; break; // SRL
case 2: // SRA
result = (x >> n) | ((x & 0x80u) ? (0xFFu << (8 - n)) : 0u);
break;
case 3: result = (x << n) | (x >> (8 - n)); break; // ROL
case 4: result = (x >> n) | (x << (8 - n)); break; // ROR
}
const unsigned carry_bit = (op == 0 || op == 3) ? 8 - n : n - 1;
return {
static_cast<std::uint8_t>(result & 0xFFu),
((x >> carry_bit) & 1u) != 0,
};
}
The explicit zero-distance branch avoids invalid shift indices. All shifts operate on unsigned integers; sign fill is constructed explicitly. op represents the three-bit local selector; out-of-range integer arguments also return zero result and carry.
Unknown inputs and timing¶
For known, valid OP and known B[2:0], the unused upper bits of B do not affect either output, even when they contain X or Z. At nonzero distance, unknown C_IN is also isolated. At distance zero, an X or Z carry input yields CARRY = X through the gate network, while known A remains unchanged on OUT.
Unknown data or relevant control bits follow the underlying multiplexer gates. Bits that are known to be zero-filled can still be determined; a Z passing through logic becomes X, not a high-impedance output. Known reserved local selections mask both outputs to zero.
The three structural shift stages are combinational, not three clock cycles. Changes pass through direction selection, shift stages, and output masking before settling. No single structural component latency is declared; use the recorded checkpoints to inspect settled data and carry together.
Implementation¶
Structural implementation¶
The network first reverses the bit order for leftward operations, uses a shared rightward shift network, and reverses the result back afterward. Reversal changes bit positions; it does not invert their values.
| Internal block | Function |
|---|---|
A_SPLIT, B_SPLIT |
Expose operand bits and distance controls |
LEFT_SELECT, ROTATE_SELECT, ARITHMETIC_SELECT, VALID_SELECT |
Derive controls from local OP using Mux8to1 components |
INPUT_REVERSE_* |
Select the original or reversed input order |
SHIFT_1_* |
Optionally shift by 1, controlled by B[0] |
SHIFT_2_* |
Optionally shift by 2, controlled by B[1] |
SHIFT_4_* |
Optionally shift by 4, controlled by B[2] |
OUTPUT_REVERSE_* |
Restore the bit order for leftward operations |
VALID_BIT_*, CARRY_VALID |
Mask reserved selections to zero |
OUT_JOIN |
Assemble the output word |
Each enabled stage selects either a shifted word or the preceding word. Its carry multiplexer selects the stage's last shifted-out bit when enabled; otherwise it keeps the preceding carry. The chain starts with C_IN, which survives only when no shift stage is enabled. Fill selection supplies zero, the sign bit, or wrapped data according to the operation.
Behavioral implementation¶
Behavioral8<BarrelShifter8> calls shift. It evaluates direction reversal, the optional 1-, 2-, and 4-position stages, carry selection, and reserved-opcode masking as operations on arrays of four-state values. It creates no stage components or internal events; the three stages are evaluated within one call.
The evaluator is defined in ALU8Behavioral.cpp; its value functions are in ALU8ValueModel.hpp. It retains the public pins without functional circuit children. Catalog construction supplies a delay table characterized from the gates; where a delay twin is available and agrees with the computed value, publication can follow the current inputs’ gate-level settling time within that bound, subject to older pending results. The compact evaluator does not reproduce transient gate glitches.
The recorded scenario runs against both implementations in CTest. ALU8FidelityContractTest checks binary/X/Z settled-output equivalence against the structural circuit. The example table uses the default structural run; its checkpoint times need not match the behavioral run.
Examples¶
All 96 recorded rows of BarrelShifter8Test, in checkpoint order. Outputs are test expectations verified against the simulation. Time is the absolute settled checkpoint time in simulator units, not milliseconds or CPU cycles.
Default scenario profile: canonical-default-preview / structural (396ffca50e2dd8dd). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | AInput · 8 bit |
BInput · 8 bit |
C_INInput · 1 bit |
OPInput · 3 bit |
CARRYExpected output · 1 bit |
OUTExpected output · 8 bit |
|---|---|---|---|---|---|---|---|
#0row-0 | 19 | 0x81 |
0x00 |
0 |
0x0 |
0 |
0x81 |
#1row-1 | 27 | 0x81 |
0x00 |
1 |
0x0 |
1 |
0x81 |
#2row-2 | 39 | 0x81 |
0x01 |
0 |
0x0 |
1 |
0x02 |
#3row-3 | 41 | 0x81 |
0x01 |
1 |
0x0 |
1 |
0x02 |
#4row-4 | 51 | 0x81 |
0x03 |
0 |
0x0 |
0 |
0x08 |
#5row-5 | 53 | 0x81 |
0x03 |
1 |
0x0 |
0 |
0x08 |
#6row-6 | 61 | 0x81 |
0x07 |
0 |
0x0 |
0 |
0x80 |
#7row-7 | 63 | 0x81 |
0x07 |
1 |
0x0 |
0 |
0x80 |
#8row-8 | 75 | 0x81 |
0x08 |
0 |
0x0 |
0 |
0x81 |
#9row-9 | 83 | 0x81 |
0x08 |
1 |
0x0 |
1 |
0x81 |
#10row-10 | 95 | 0x81 |
0xFF |
0 |
0x0 |
0 |
0x80 |
#11row-11 | 97 | 0x81 |
0xFF |
1 |
0x0 |
0 |
0x80 |
#12row-12 | 118 | 0x81 |
0x00 |
0 |
0x1 |
0 |
0x81 |
#13row-13 | 126 | 0x81 |
0x00 |
1 |
0x1 |
1 |
0x81 |
#14row-14 | 138 | 0x81 |
0x01 |
0 |
0x1 |
1 |
0x40 |
#15row-15 | 140 | 0x81 |
0x01 |
1 |
0x1 |
1 |
0x40 |
#16row-16 | 150 | 0x81 |
0x03 |
0 |
0x1 |
0 |
0x10 |
#17row-17 | 152 | 0x81 |
0x03 |
1 |
0x1 |
0 |
0x10 |
#18row-18 | 160 | 0x81 |
0x07 |
0 |
0x1 |
0 |
0x01 |
#19row-19 | 162 | 0x81 |
0x07 |
1 |
0x1 |
0 |
0x01 |
#20row-20 | 174 | 0x81 |
0x08 |
0 |
0x1 |
0 |
0x81 |
#21row-21 | 182 | 0x81 |
0x08 |
1 |
0x1 |
1 |
0x81 |
#22row-22 | 194 | 0x81 |
0xFF |
0 |
0x1 |
0 |
0x01 |
#23row-23 | 196 | 0x81 |
0xFF |
1 |
0x1 |
0 |
0x01 |
#24row-24 | 216 | 0x81 |
0x00 |
0 |
0x2 |
0 |
0x81 |
#25row-25 | 224 | 0x81 |
0x00 |
1 |
0x2 |
1 |
0x81 |
#26row-26 | 236 | 0x81 |
0x01 |
0 |
0x2 |
1 |
0xC0 |
#27row-27 | 238 | 0x81 |
0x01 |
1 |
0x2 |
1 |
0xC0 |
#28row-28 | 247 | 0x81 |
0x03 |
0 |
0x2 |
0 |
0xF0 |
#29row-29 | 249 | 0x81 |
0x03 |
1 |
0x2 |
0 |
0xF0 |
#30row-30 | 256 | 0x81 |
0x07 |
0 |
0x2 |
0 |
0xFF |
#31row-31 | 258 | 0x81 |
0x07 |
1 |
0x2 |
0 |
0xFF |
#32row-32 | 270 | 0x81 |
0x08 |
0 |
0x2 |
0 |
0x81 |
#33row-33 | 278 | 0x81 |
0x08 |
1 |
0x2 |
1 |
0x81 |
#34row-34 | 289 | 0x81 |
0xFF |
0 |
0x2 |
0 |
0xFF |
#35row-35 | 291 | 0x81 |
0xFF |
1 |
0x2 |
0 |
0xFF |
#36row-36 | 303 | 0x81 |
0x00 |
0 |
0x3 |
0 |
0x81 |
#37row-37 | 311 | 0x81 |
0x00 |
1 |
0x3 |
1 |
0x81 |
#38row-38 | 323 | 0x81 |
0x01 |
0 |
0x3 |
1 |
0x03 |
#39row-39 | 325 | 0x81 |
0x01 |
1 |
0x3 |
1 |
0x03 |
#40row-40 | 335 | 0x81 |
0x03 |
0 |
0x3 |
0 |
0x0C |
#41row-41 | 337 | 0x81 |
0x03 |
1 |
0x3 |
0 |
0x0C |
#42row-42 | 345 | 0x81 |
0x07 |
0 |
0x3 |
0 |
0xC0 |
#43row-43 | 347 | 0x81 |
0x07 |
1 |
0x3 |
0 |
0xC0 |
#44row-44 | 359 | 0x81 |
0x08 |
0 |
0x3 |
0 |
0x81 |
#45row-45 | 367 | 0x81 |
0x08 |
1 |
0x3 |
1 |
0x81 |
#46row-46 | 381 | 0x81 |
0xFF |
0 |
0x3 |
0 |
0xC0 |
#47row-47 | 383 | 0x81 |
0xFF |
1 |
0x3 |
0 |
0xC0 |
#48row-48 | 400 | 0x81 |
0x00 |
0 |
0x4 |
0 |
0x81 |
#49row-49 | 408 | 0x81 |
0x00 |
1 |
0x4 |
1 |
0x81 |
#50row-50 | 420 | 0x81 |
0x01 |
0 |
0x4 |
1 |
0xC0 |
#51row-51 | 422 | 0x81 |
0x01 |
1 |
0x4 |
1 |
0xC0 |
#52row-52 | 432 | 0x81 |
0x03 |
0 |
0x4 |
0 |
0x30 |
#53row-53 | 434 | 0x81 |
0x03 |
1 |
0x4 |
0 |
0x30 |
#54row-54 | 442 | 0x81 |
0x07 |
0 |
0x4 |
0 |
0x03 |
#55row-55 | 444 | 0x81 |
0x07 |
1 |
0x4 |
0 |
0x03 |
#56row-56 | 456 | 0x81 |
0x08 |
0 |
0x4 |
0 |
0x81 |
#57row-57 | 464 | 0x81 |
0x08 |
1 |
0x4 |
1 |
0x81 |
#58row-58 | 478 | 0x81 |
0xFF |
0 |
0x4 |
0 |
0x03 |
#59row-59 | 480 | 0x81 |
0xFF |
1 |
0x4 |
0 |
0x03 |
#60row-60 | 492 | 0x81 |
0x00 |
0 |
0x5 |
0 |
0x00 |
#61row-61 | 500 | 0x81 |
0x00 |
1 |
0x5 |
0 |
0x00 |
#62row-62 | 512 | 0x81 |
0x01 |
0 |
0x5 |
0 |
0x00 |
#63row-63 | 514 | 0x81 |
0x01 |
1 |
0x5 |
0 |
0x00 |
#64row-64 | 524 | 0x81 |
0x03 |
0 |
0x5 |
0 |
0x00 |
#65row-65 | 526 | 0x81 |
0x03 |
1 |
0x5 |
0 |
0x00 |
#66row-66 | 534 | 0x81 |
0x07 |
0 |
0x5 |
0 |
0x00 |
#67row-67 | 536 | 0x81 |
0x07 |
1 |
0x5 |
0 |
0x00 |
#68row-68 | 548 | 0x81 |
0x08 |
0 |
0x5 |
0 |
0x00 |
#69row-69 | 556 | 0x81 |
0x08 |
1 |
0x5 |
0 |
0x00 |
#70row-70 | 568 | 0x81 |
0xFF |
0 |
0x5 |
0 |
0x00 |
#71row-71 | 570 | 0x81 |
0xFF |
1 |
0x5 |
0 |
0x00 |
#72row-72 | 582 | 0x81 |
0x00 |
0 |
0x6 |
0 |
0x00 |
#73row-73 | 590 | 0x81 |
0x00 |
1 |
0x6 |
0 |
0x00 |
#74row-74 | 602 | 0x81 |
0x01 |
0 |
0x6 |
0 |
0x00 |
#75row-75 | 604 | 0x81 |
0x01 |
1 |
0x6 |
0 |
0x00 |
#76row-76 | 614 | 0x81 |
0x03 |
0 |
0x6 |
0 |
0x00 |
#77row-77 | 616 | 0x81 |
0x03 |
1 |
0x6 |
0 |
0x00 |
#78row-78 | 624 | 0x81 |
0x07 |
0 |
0x6 |
0 |
0x00 |
#79row-79 | 626 | 0x81 |
0x07 |
1 |
0x6 |
0 |
0x00 |
#80row-80 | 638 | 0x81 |
0x08 |
0 |
0x6 |
0 |
0x00 |
#81row-81 | 646 | 0x81 |
0x08 |
1 |
0x6 |
0 |
0x00 |
#82row-82 | 658 | 0x81 |
0xFF |
0 |
0x6 |
0 |
0x00 |
#83row-83 | 660 | 0x81 |
0xFF |
1 |
0x6 |
0 |
0x00 |
#84row-84 | 672 | 0x81 |
0x00 |
0 |
0x7 |
0 |
0x00 |
#85row-85 | 680 | 0x81 |
0x00 |
1 |
0x7 |
0 |
0x00 |
#86row-86 | 692 | 0x81 |
0x01 |
0 |
0x7 |
0 |
0x00 |
#87row-87 | 694 | 0x81 |
0x01 |
1 |
0x7 |
0 |
0x00 |
#88row-88 | 704 | 0x81 |
0x03 |
0 |
0x7 |
0 |
0x00 |
#89row-89 | 706 | 0x81 |
0x03 |
1 |
0x7 |
0 |
0x00 |
#90row-90 | 714 | 0x81 |
0x07 |
0 |
0x7 |
0 |
0x00 |
#91row-91 | 716 | 0x81 |
0x07 |
1 |
0x7 |
0 |
0x00 |
#92row-92 | 728 | 0x81 |
0x08 |
0 |
0x7 |
0 |
0x00 |
#93row-93 | 736 | 0x81 |
0x08 |
1 |
0x7 |
0 |
0x00 |
#94row-94 | 748 | 0x81 |
0xFF |
0 |
0x7 |
0 |
0x00 |
#95row-95 | 750 | 0x81 |
0xFF |
1 |
0x7 |
0 |
0x00 |
Scroll within the table for all rows and pins. Buses use hexadecimal; values containing X/Z use MSB-first binary. Inputs show the declared values in effect at each checkpoint, including retained inputs. Sequential tests also replay preparation changes between checkpoints, such as lowering the clock. Use the matching checkpoint label in the simulation below.
Embedded simulation¶
The barrel-shifter8 scenario runs BarrelShifter8Test: 96 recorded cases using A = 0x81, all eight local selections, six B values (0, 1, 3, 7, 8, 255), and both carry inputs. Checkpoints expose the zero-distance carry rule, masked distance, and reserved selections as well as shifts and rotations.
Open BarrelShifter8 in the simulator
Source and tests¶
| Test | Coverage |
|---|---|
BarrelShifter8Test |
96 recorded binary cases: eight local selections × six B values × both carry inputs, with A = 0x81. Checks OUT and CARRY; this is the embedded scenario. |
ALU8ContractTest: standalone shifter sweep |
20,480 cases: five valid operations × 256 A values × eight effective distances × both carry inputs. Every case drives B[7:3] = 0b11111. |
ALU8ContractTest: integrated checks |
Boundary and seeded random ALU cases, plus targeted X/Z cases for ignored upper distance bits, ignored carry at nonzero distance, and unknown carry at zero distance. |
The 20,480-case sweep is exhaustive over valid operations, data words, effective distances, and binary carry inputs, but not over every eight-bit B value, reserved local selection, or four-state pattern. It disables history recording; the embedded simulation contains only the 96 recorded cases.