Level 55: Sum of an Array
Task
Goal: assemble and run the first full program: it reads an 8-word array from data memory and sums it. New instruction — lui (U-format): imm20 in bits [31:12], value = imm20 << 12; the array base 0x1000 is built as lui x10, 0x1. The array 3 1 4 1 5 9 2 6 is preloaded into DMEM by the platform (visible in the Execution block). Predict the cycle count and compare bitwise with the golden.
The first complete golden run: the program reads an array of eight 32-bit words from data memory and sums it. Everything needed is already built: lw from level 52, beq from level 53, the loop from level 54. The new instruction is just one — lui (the U-format): the 12-bit immediate of addi covers only −2048…2047, while the array base lives at 0x1000.
lui rd, imm20 puts 20 bits into the upper half of the register: lui x10, 0x1 gives x10 = 0x1 << 12 = 0x00001000 — exactly the DMEM base. The array 3 1 4 1 5 9 2 6 is preloaded into memory by the platform before the start (addresses 0x1000–0x101C, visible in the Execution block); there is no need to write it into the program.
The canonical array_sum program:
lui x10, 0x1 # 0: x10 = 0x1000, the array base
addi x11, x0, 0 # 4: the sum
addi x12, x0, 8 # 8: the counter (top down, 8 elements)
loop: beq x12, x0, done # 12
addi x12, x12, -1 # 16
slli x14, x12, 2 # 20: the byte offset (i-1)*4
add x14, x10, x14 # 24
lw x15, 0(x14) # 28
add x11, x11, x15 # 32
beq x0, x0, loop # 36: → 12
done: .end # 40
Level tasks:
- Pack the
luiword in "Word from fields" (it appeared in the mnemonic list on level 55) and take apart the U-format: imm20 in bits [31:12], the low 12 bits are zeros. - Assemble the program in the Assembler tab. The word address: the counter x12 decreases by 1 per iteration, the shift
slli x14, x12, 2multiplies it by 4 (the byte offset), andaddadds the base. - Run it cycle by cycle: the Execution block shows the memory window with the array (the highlight marks changed words; the program only reads, so the values stay in place).
- Predict the cycle count before running — the first "Check" will ask for it and compare it with the trace.
The level's negative scenario: replace the address step with 1 (lw x15, 1(x10)). The lw lands at 0x1001, which is not a multiple of 4. The reference core stops there with the error ERR_DATA_ADDRESS_MISALIGNED and freezes the state: the failing instruction does not execute, and no partial sum appears. This is not "a sum of word pieces" but an error with a freeze — compare the behavior with the trace, not with intuition.
Solution for self-check
First count the cycles on paper. The solution below is a set of checkpoints.
What you should get: array_sum yields x11 = 31 (3 + 1 + 4 + 1 + 5 + 9 + 2 + 6) in 60 cycles (3 setup + 8 iterations × 7 + 1); DMEM is unchanged, and lw at 0x1001 halts the machine with ERR_DATA_ADDRESS_MISALIGNED and a frozen state.
Step 1 — the U-format. lui has neither rs1 nor funct3: the word consists of imm20 [31:12], rd [11:7], and opcode 0110111. The register value = imm20 << 12, the low 12 bits are zeros. lui x10, 0x1 = 0x00001537, x10 = 0x00001000.
Step 2 — sign compensation in li. From level 55 on, the li rd, imm32 pseudo-instruction with a large constant expands to lui + addi. The addi immediate is signed: if bit 11 of the low part is 1, adding it "carries" a one into the upper half, so the assembler increases imm20 in advance: hi = (v + 0x800) >> 12. Check: li x10, 0x1000 — upper 0x1, lower 0, no compensation; li x10, 0x1FFF — upper 0x2, lower −1.
Step 3 — count cycles. The preparation is 3 instructions (lui + two addi). Each iteration: the beq guard, the addi step, slli, add, lw, add, and the jump-back beq — 7 instructions, 8 iterations. On the last iteration the counter is already 0, the beq guard is taken and leads to done. Total: 3 + 8 × 7 + 1 = 60 cycles. The .end halt (jal x0, 0) adds no cycle, and the PC freezes at 40.
Step 4 — compare the result. The sum 3+1+4+1+5+9+2+6 = 31 lands in x11. The DMEM is unchanged at the end (the program only reads). If you experiment with the step of 1, the trace will show an ERR_DATA_ADDRESS_MISALIGNED record at PC 28, and x11 will stay zero — the state is frozen, the sum is not "corrupted", it simply does not exist.
Check yourself
Why cannot the array base be written with a single addi?
The 12-bit signed immediate only covers −2048…2047. The base 0x1000 is built by lui — it puts imm20 into the top 20 register bits, and an addi fixes the low part if needed (the li pseudo-instruction does this on its own).