25-Comp-A3 Computer Architecture · December 2017
Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)
3-hour, open-book exam. Questions 1 and 2 are mandatory; the first five questions answered constitute a complete paper (Q6 is answered here as well, for completeness). Reference texts: Patterson & Hennessy, Computer Organization and Design, 6th ed.
Question text not reproduced: the examination questions are © Engineers and Geoscientists BC. Open the official past paper (linked at the top of this page) to read the question, then follow the worked solution below.
Given. (a) an 8-instruction sequence with two independent lw/lw/add/sw groups on a 5-stage (IF-ID-EX-MEM-WB) pipeline where a load's result is available at the end of stage 4 (MEM) but a dependent instruction needs its operand at the start of stage 3 (EX). (b) a 4-instruction, 8-bit encoding table for a 4-register CPU.
Find. (a) a reordering of the 8 instructions with no load-use stalls. (b) the structural problems in the encoding table and a corrected field layout.
Approach. (a) since two back-to-back instructions place the load's MEM stage in the very same cycle as the dependent instruction's EX stage (one cycle too early), insert at least one independent instruction between every load and any instruction that consumes its result; interleave the two independent chains to supply those fillers for free. (b) decode each row's opcode bit positions and check whether they overlap with another row's operand-field bit positions for some operand value.
i and i+1, instruction i's MEM stage (cycle where a load's value becomes available) falls in the exact same cycle as instruction i+1's EX stage (where an ADD needs its operand, at the start of that cycle) — the value simply isn't ready yet, forcing a stall. Separating the load and its consumer by at least one independent instruction pushes the consumer's EX stage one cycle later, which now lines up with (or follows) the load's MEM/WB forwarding point, removing the stall. The original code has exactly two such hazards: lw $6→add $6,$5,$6 (adjacent) and lw $9→add $9,$8,$9 (adjacent). Because the two lw/lw/add/sw groups are entirely independent of each other (different registers, only sharing the read-only base $4), each group's extra load can be pulled forward to fill the other group's hazard slot:
| Slot | Instruction | Note |
|---|---|---|
| 1 | lw $5, 0($4) | |
| 2 | lw $6, 4($4) | |
| 3 | lw $8, 8($4) | independent filler (was slot 5) |
| 4 | add $6, $5, $6 | 1 instr after lw $6: hazard-free |
| 5 | lw $9, 12($4) | independent filler (was slot 6) |
| 6 | sw $6, 0($7) | |
| 7 | add $9, $8, $9 | 1 instr after lw $9: hazard-free |
| 8 | sw $9, 0($10) |
lw $8, 8($4) and lw $9, 12($4) above sw $6, 0($7), so it preserves the program's meaning only if the store's target MEM[$7+0] does not alias either loaded address MEM[$4+8] or MEM[$4+12]. Nothing in the question relates $7 to $4, and a compiler performing this schedule would either prove independence or keep the store ahead of the two loads; the register dependences alone are unaffected either way.0000 and 0010) with the register fields R1/R2 occupying the HIGH nibble (bits 7–4); BZ also fixes its low nibble (0101) with Imm4 in the high nibble; but Add does the opposite — it fixes its HIGH nibble (1000) and puts its register fields R1/R2 in the LOW nibble. Because there is no single, position-consistent opcode field shared by every instruction, an instruction cannot be identified by looking at one fixed set of bits — and because R1/R2/Imm4 are unconstrained operand values, some combinations of a "data-like" field in one instruction exactly reproduce the fixed bit pattern of a different instruction:
Load R1=2, R2=0 encodes as 10 00 0000 = 0x80. Add $0,$0 encodes as 1000 00 00 = 0x80. Identical byte, two different instructions — the decoder cannot tell "load register 2 from the address in register 0" from "add register 0 to register 0."Store R2=2, R1=0 encodes as 10 00 0010 = 0x82. Add R1=0, R2=2 encodes as 1000 00 10 = 0x82. Same collision.Add R1=1, R2=1 encodes as 1000 0101 = 0x85. BZ Imm4=1000(=8) encodes as 1000 0101 = 0x85. Same collision, this time between Add and a branch.| Part | Result |
|---|---|
| (a) | $\boxed{lw\$5,\ lw\$6,\ lw\$8,\ add\$6,\ lw\$9,\ sw\$6,\ add\$9,\ sw\$9}$ — 0 stall cycles (was 2) |
| (b) | Add's opcode nibble collides with Load/Store/BZ operand fields (e.g. Load $2,($0) = Add $0,$0 = 0x80); fix: one fixed 2-bit opcode field at the same position in every instruction |