Master the fundamental concepts of cpu design through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksA register file holds the CPU's working set: eight general-purpose registers in this emulator. Real cores expose two read ports and one write port per cycle so a single instruction can fetch two operands and store a result simultaneously.
cLoading…
Register R0 is often hardwired to zero in RISC ISAs; your toy CPU may treat all eight as general purpose.
Accessing a register takes one cycle and no address calculation. Reading the same data from RAM might cost 50 to 200 cycles if it misses cache. Compilers fight to keep hot variables in registers for this reason.
For this exercise, you will add eight addressable registers and hook them into fetch-decode-execute. You will need two independent read ports for three-operand-style instructions before implementing stack and call instructions.
Keep the relevant datasheet, ISA manual, or architecture textbook chapter open while you implement. When your output disagrees with the reference trace on the same program, the bug is usually a mis-decoded opcode, a stale register read, or a flag bit left unchanged after arithmetic.
For this exercise, you will use those habits while implementing the requirement in the starter code. Microarchitectural product names change across CPU generations, but the control ideas (fetch, bypass, cache lines, vector lanes) stay stable enough to debug from first principles.
Model a CPU register file: eight 16-bit registers with two read ports and one write port, all usable in the same clock cycle. That is what lets ADD R1, R2, R3 read both sources while an earlier instruction writes its result. Like MIPS and RISC-V, R0 is hardwired to zero. You also model what happens when a cycle reads the register that the same cycle is writing.
The first line is mode read-first or mode write-first:
read-first: reads in a cycle see the values from before that cycle's write.write-first: the write happens in the first half of the cycle and reads in the second half, so a read of the register being written sees the new value (this is how classic 5-stage pipelines avoid one hazard).Then one command per line:
cLoading…
Registers are R0..R7; VALUE is decimal 0..65535. All registers start at 0. Writes to R0 are discarded; R0 always reads 0.
cLoading…
Print only the parts that are present, joined by ; (cycle N: idle if neither). A write to R0 prints write R0 ignored. dump prints R0=.. R1=.. ... R7=... A line that doesn't parse prints error: bad cycle and does not advance the cycle counter.
Input:
cLoading…
Output:
cLoading…
read(rf, a, b, &x, &y) and write(rf, d, v) operations; the cycle function orders them according to the mode.R0 rule is enforced inside the register file, not by the caller.Hidden tests cover write-first mode with a same-cycle read of the written register, both ports reading the same register, idle cycles, and malformed lines (bad register names, out-of-range values, parts in the wrong order).