Reading — step 1 of 5
Read
~1 min readArchitecture Basics
Memory Layout
The simulator's memory is a byte array, 4 GiB conceptually but typically a few MiB allocated.
Standard layout for our toy:
0x00000000 - 0x0000FFFF: Reserved / null guard
0x00010000 - 0x000FFFFF: Code (.text)
0x00100000 - 0x001FFFFF: Read-only data (.rodata)
0x00200000 - 0x002FFFFF: Initialized data (.data)
0x00300000 - 0x003FFFFF: Uninit data (.bss)
0x80000000 - 0x80FFFFFF: Stack (grows down from top)
Loads/stores are size-typed:
- LB/LBU: load byte (signed/unsigned).
- LH/LHU: load halfword (16-bit).
- LW: load word (32-bit).
- SB: store byte.
- SH: store halfword.
- SW: store word.
python
Alignment: RISC-V requires loads/stores aligned to their size. Misaligned access raises an exception. Some implementations handle in software.
Address translation: real CPUs use MMU (paging). Toy: skip translation, use physical address directly.
Memory-mapped I/O:
- Special addresses correspond to devices (UART, timer, etc.).
- Write to 0x10000000 → byte appears on serial console.
- Read from 0x10000004 → status flag.
- Our toy: simulate one UART for output.
Bootstrap:
- Load program binary at 0x10000.
- Set pc = 0x10000.
- Set sp = 0x80FFFFF0 (top of stack, aligned).
- Set x10 (a0) = argc, x11 (a1) = argv pointer.
- Run until ECALL with system_exit.
ECALL convention (Linux-like):
- a7 = syscall number.
- a0-a6 = args.
- 64 = sys_write, 93 = sys_exit.
- After ECALL, simulator dispatches to host action.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…