NivaarExam PrepOfficial exam papers ↗

25-Comp-A3 Computer Architecture · December 2015

Question 6 of 6: Unified Memory, Addressing Modes, and Micro-Operation Sequences

Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)

Notes on this paper

98-Comp-A3, Computer Architecture — National Exams, December 2015. Closed-book, 3 hours; six questions of equal value (20 marks each); FIVE constitute a complete exam (all six answered below as a complete study resource).

Reference texts: Patterson & Hennessy, Computer Organization and Design, 6th ed. — memory hierarchy & cache performance (Q1a, Q2a, Q3a, Q5a), instruction encoding & RISC design (Q2c, Q3b, Q4c), IEEE-754 floating point (Q4b), and memory technology (Q4a); Mano & Ciletti, Digital Design, 6th ed. — control-unit design, register-transfer micro-operations, stack/RPN notation, and binary-multiplication hardware (Q1b, Q3c, Q5b–d, Q6a–c).

Question 6: Unified Memory, Addressing Modes, and Micro-Operation Sequences (20 marks)

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) The stored-program (von Neumann) model of a single shared memory for code and data. (b) Four common addressing modes. (c) The named registers IR, MAR, MBR, PC and the notation $C(X)$ for "content of $X$."

Find. (a) Pros/cons of a unified program+data memory. (b) How each addressing mode computes its operand, with pros/cons. (c) A register-transfer micro-operation sequence for the fetch cycle, for ADD R1,X, and for ISZ X.

Approach. (a) contrast the von Neumann model against a split (Harvard) memory. (b) trace, for each mode, exactly what the operand field is interpreted as and how many memory accesses it costs. (c) write each instruction's execution as an ordered list of register-transfer-level micro-operations, one per clock cycle (or per concurrently-issuable group).

  1. Part (a) — programs and data sharing one memory. Advantages: a single, uniform address space and memory system is simpler and cheaper to build (one set of address/data buses, one memory controller); memory capacity is allocated flexibly between code and data as a program needs (no fixed partition wasted); and it enables powerful techniques such as self-modifying code, dynamically-loaded/generated code (JIT compilation), and loading a program itself as ordinary "data" (what a loader, linker, or OS does). Disadvantages: it creates the classic von Neumann bottleneck — instruction fetches and data accesses contend for the SAME memory port/bus, limiting how much fetch and data traffic can be overlapped (a major reason many caches are split into separate instruction and data caches even though the memory behind them is unified); and it opens a security exposure, because data written into memory (e.g. an unchecked buffer) can potentially be executed as instructions (the basis of many buffer-overflow / code-injection exploits), which is why modern systems add a hardware "no-execute" (NX/XD) bit to mark data pages non-executable.
  2. Part (b) — addressing modes.
    • (1) Immediate: the operand VALUE itself is embedded directly in the instruction word (no memory reference at all). Adv: fastest possible operand access (already in hand once the instruction is fetched), no extra memory cycle. Dis: the operand's size is capped by the instruction's spare bit-field width, so it can't represent arbitrarily large or computed values.
    • (2) Direct: the instruction's address field IS the memory address of the operand; one memory access retrieves it. Adv: simple, single extra memory access. Dis: the address field must be wide enough to span all of memory (costly in instruction bits), and the target address is fixed at compile/assembly time — no runtime flexibility (can't easily index through an array or follow a pointer).
    • (3) Register: the instruction's address field names a CPU register holding the operand directly (no memory access at all for the operand itself). Adv: fastest memory-free access, and the field is very short (only $\lceil\log_2(\#\text{registers})\rceil$ bits, not a full address). Dis: limited by how many registers exist — cannot address the vastly larger memory space this way.
    • (4) Register indirect: the named register holds not the operand but the ADDRESS of the operand in memory; one memory access (after reading the register) retrieves the actual value. Adv: short instruction field (just a register number) yet can reach anywhere in the full memory address space, and the address can be computed/updated at run time (pointers, array traversal, indexing). Dis: costs one memory access to fetch the operand (slower than register-direct), plus the register must first be loaded with a valid address by other code.
  3. Part (c1) — fetch-cycle micro-operations. Executed once at the start of every instruction cycle (steps executed in order; steps that touch independent registers, like $t_1$'s two transfers, can often be issued in the same clock):
    1. $t_1:\ \text{MAR}\leftarrow C(\text{PC})$ — copy the program counter into the memory address register.
    2. $t_2:\ \text{MBR}\leftarrow C(\text{Memory}),\ \text{PC}\leftarrow C(\text{PC})+1$ — read the addressed word into the memory buffer register while simultaneously advancing PC to the next instruction (these two are independent and can overlap).
    3. $t_3:\ \text{IR}\leftarrow C(\text{MBR})$ — move the fetched word into the instruction register for decoding.
  4. Part (c2) — ADD R1,X micro-operations. (Assumes $X$'s address is available from the decoded instruction, e.g. already placed in MAR or an address field of IR — the fetch cycle above has already completed.)
    1. $t_1:\ \text{MAR}\leftarrow \text{address field of }C(\text{IR})$ — load the operand's memory address.
    2. $t_2:\ \text{MBR}\leftarrow C(\text{Memory})$ — read $C(X)$ from memory into the buffer register.
    3. $t_3:\ \text{R1}\leftarrow C(\text{R1})+C(\text{MBR})$ — add the fetched value to R1's current content and store the sum back into R1.
  5. Part (c3) — ISZ X micro-operations. ("Increment and skip if zero": $X$'s content is incremented; if the result is 0, the next instruction is skipped by advancing PC an extra time.)
    1. $t_1:\ \text{MAR}\leftarrow \text{address field of }C(\text{IR})$ — load $X$'s address.
    2. $t_2:\ \text{MBR}\leftarrow C(\text{Memory})$ — read $C(X)$ into the buffer register.
    3. $t_3:\ \text{MBR}\leftarrow C(\text{MBR})+1$ — increment the fetched value inside MBR.
    4. $t_4:\ \text{Memory}\leftarrow C(\text{MBR})$ (write-back to address held in MAR) — store the incremented value back to $X$.
    5. $t_5:\ \textbf{If }C(\text{MBR})=0\textbf{ then }\text{PC}\leftarrow C(\text{PC})+1$ — conditional micro-operation: only when the incremented result is exactly zero does PC advance an extra time, which skips the next instruction in the program.
Final results — Question 6
PartResult
(a) unified memoryAdv: simpler/cheaper, flexible allocation, self-modifying/JIT code. Dis: von Neumann bottleneck; code-injection security exposure
(b) addressing modesImmediate (fastest, size-capped) → Register (fast, register-count-capped) → Register indirect (1 mem access, full range, runtime-flexible) → Direct (1 mem access, fixed at assembly time, wide address field)
(c1) fetch cycleMAR←PC; MBR←Mem, PC←PC+1; IR←MBR
(c2) ADD R1,XMAR←addr(X); MBR←C(X); R1←R1+MBR
(c3) ISZ XMAR←addr(X); MBR←C(X); MBR←MBR+1; Mem←MBR; if MBR=0 then PC←PC+1
Back to the paper →