IPS: 0 Hz
Console / Binary Output

                        
Name Value (Hex) Dec

Instruction Memory

Bkpt Address Code Basic Source

Data Segment

Address Value (+0) Value (+4) Value (+8) Value (+c) Value (+10) Value (+14) Value (+18) Value (+1c)
help_outline
Hover over any block to learn about its architecture and specifications.
Compute / Master Blocks
Memory & Caches
TileLink Interconnect
MMIO Peripherals
TileLink-UH Coherent Bus (High-Speed)
TileLink-UL Bus (Low-Speed/MMIO)
Translation Lookaside Buffer (TLB)
VPN PPN Attributes
L1 Instruction Cache
Set Way Valid Dirty Tag Last Ref Bytes (0-15)
L1 Data Cache
Set Way Valid Dirty Tag Last Ref Bytes (first 8)
L2 Shared Cache
Set Way Valid Dirty Tag Last Ref Bytes (first 8)
grid_on LED Matrix (32x32)
terminal UART Console
keyboard Keyboard
Buffer Status: Empty

RISC-V SoC Simulator

SoC Simulator là một công cụ mô phỏng hoạt động của một Hệ thống trên Chip (SoC) được thiết kế và phát triển bởi nhóm tác giả Nguyễn Xuân Lộc & Dương Hiển Gia Khang. Mục đích của Project là hỗ trợ những người mới bắt đầu tìm hiểu về thiết kế SoC.

RV32I RV32M RV32F MMIO Cache
Mục tiêu sử dụng: viết assembly trong Editor, bấm Assemble để sinh mã máy, Run/Step để thực thi, rồi quan sát Registers, Memory, Cache, I/O và Systems Log Console.
Khu vực Dùng để làm gì Mẹo thao tác
Editor Soạn RISC-V assembly, đặt breakpoint ở gutter, xem binary output. Ưu tiên khai báo .text, .globl _start, nhãn _start:.
SoC Xem sơ đồ CPU, MMU, cache, TileLink, DMA và các ngoại vi. Hover từng block để xem mô tả, dùng log để đối chiếu giao dịch đang chạy.
MMU Quan sát nội dung TLB: VPN, PPN và thuộc tính trang (V/R/W/X/C). Dùng syscall MMU để kiểm thử map/unmap.
Cache Xem L1I, L1D, L2 cache: set, way, dirty, tag, hit/miss. Dùng Cache view và Systems Log Console để quan sát hành vi bộ nhớ.
Memory Xem instruction memory và data segment. Ô địa chỉ hỗ trợ dạng thập phân hoặc hex, ví dụ 0x10010000.
I/O Tương tác LED Matrix, UART Console, Keyboard, Mouse và DMA. I/O dùng memory-mapped registers; syscall chỉ dành cho console/MMU helper.
Systems Log Theo dõi log CPU, MMU, cache, TileLink, DMA, memory và I/O. Có thể search, lọc level/module, clear hoặc export log để debug.

Quick Start (5 phút)

Dành cho người mới: năm bước dưới đây giúp bạn chạy chương trình RISC-V đầu tiên và biết quan sát kết quả ở đâu. Sau đó hãy đọc các mục chi tiết bên dưới để hiểu sâu hơn.
  1. Viết code: mở tab Editor và gõ vài lệnh, ví dụ li a0, 5 rồi addi a0, a0, 1. Gõ rồi nhấn Ctrl-Space để bật gợi ý tên lệnh, thanh ghi và nhãn.
  2. Assemble: bấm Assemble để kiểm tra cú pháp, expand pseudo-instruction và nạp chương trình vào CPU/memory. Nếu có lỗi, đọc dòng lỗi trong Binary Output rồi sửa lại.
  3. Chạy: bấm Run để thực thi liên tục, hoặc Step để chạy từng instruction và xem PC dịch chuyển theo từng chu kỳ.
  4. Xem kết quả: thanh ghi cập nhật ngay trong tab Editor; ô nhớ xem ở tab Memory; ngoại vi như UART/LED/Keyboard/Mouse ở tab I/O; nhật ký bus, CPU, cache, DMA ở Systems Log.
  5. Đặt breakpoint: click vào gutter bên trái dòng lệnh trong Editor để đặt breakpoint, sau đó bấm Run để chương trình tự dừng khi PC tới dòng đó.

Phạm vi hỗ trợ & giới hạn

Simulator tập trung vào mô phỏng hành vi phục vụ học tập. Vì vậy Help dùng cụm RV32IMF subset: nhiều lệnh I/M/F đã chạy được, nhưng chưa phải mô hình ISA/privileged/IEEE-754 conformance đầy đủ.
Hạng mục Đã có Lưu ý khi viết code
Assembler Two-pass assembler, label, .eqv, %hi/%lo, directives dữ liệu, pseudo-instruction và encoding RV32I/M/F. Lỗi cú pháp xuất hiện trong Console / Binary Output; pseudo có thể expand thành 1 hoặc 2 instruction nên breakpoint nên đặt sau khi Assemble.
CPU Integer registers, floating-point registers, RV32I/M/F subset, ECALL/EBREAK, load/store bất đồng bộ qua MMU/cache/bus. Chưa hỗ trợ CSR/privileged mode/interrupt thật. fence được assembler mã hóa nhưng không nên dùng trong chương trình chạy trên CPU hiện tại.
Floating point RV32F single precision cơ bản: arithmetic, FMA, sign injection, compare, convert, classify, move bit pattern. Không mô phỏng đầy đủ FCSR/fflags/frm; rounding mode chỉ có ý nghĩa trong một số lệnh convert.
Atomic amoadd.w để minh họa read-modify-write qua bus. Đây là mở rộng RV32A minh họa, nằm ngoài tên RV32IMF của project.
SoC fabric MMU/TLB, L1I/L1D/L2 cache, TileLink-UH/UL, bridge, DMA, UART, LED, Keyboard, Mouse. Mô phỏng ở mức chức năng/chu kỳ trong trình duyệt, không đại diện timing, điện năng hoặc TileLink-C coherence đầy đủ.

Quy trình chạy chương trình

  1. Viết code: đặt dữ liệu trong .data, đặt lệnh trong .text. Nếu có nhãn _start, simulator sẽ ưu tiên chạy từ nhãn này.
  2. Assemble: bấm Assemble để kiểm tra cú pháp, expand pseudo-instruction và nạp chương trình vào CPU/memory.
  3. Sửa lỗi: nếu có lỗi, đọc dòng lỗi trong Console / Binary Output. Lỗi phổ biến là sai số toán hạng, label chưa khai báo, immediate vượt range.
  4. Step: chạy từng instruction để xem PC, register, memory, cache thay đổi theo từng chu kỳ.
  5. Run: chạy liên tục. Nếu đã đặt breakpoint, Run sẽ dừng khi PC tới instruction tương ứng.
  6. Quan sát: Registers tô vàng khi giá trị đổi; Memory cho biết mã máy/data; I/O hiển thị UART/LED/keyboard; Systems Log Console ghi log bus, CPU, DMA, cache.
  7. Lọc log: mở rộng Systems Log Console để tìm theo text, chọn level warn/error hoặc lọc module như CPU/MMU/TileLink/DMA/I/O.
Nút Chức năng
Assemble Biên dịch assembly, reset CPU/memory cần thiết và load chương trình.
Reset Reset trạng thái CPU/simulator nhưng giữ code trong editor.
Run Thực thi liên tục tới khi program exit, gặp lỗi, vượt max cycle hoặc hit breakpoint.
Pause Tạm dừng Run nhưng giữ nguyên PC/register/memory để tiếp tục Step hoặc Run.
Stop Dừng vòng chạy hiện tại và đồng bộ lại các khung quan sát.
Step Thực thi đúng một bước simulator, hữu ích khi kiểm tra PC/register.
Speed Điều chỉnh số chu kỳ mỗi frame khi Run.
IPS Ước lượng số instruction/chu kỳ đang chạy mỗi giây.
Breakpoint Click gutter bên trái dòng lệnh trong CodeMirror; breakpoint chỉ có hiệu lực với dòng sinh ra instruction thật.
Systems Log Expand/collapse bằng nút mũi tên; dùng Search, Level, module chips, Export và Clear khi debug bus/peripheral.

Cú pháp assembly & operand key

Quy ước dòng lệnh

  • Comment bắt đầu bằng #.
  • Label kết thúc bằng dấu hai chấm: loop:, done:.
  • Immediate hỗ trợ decimal và hex: 10, -4, 0x10010000.
  • Load/store dùng dạng offset(base), ví dụ lw t0, 8(sp).
  • Branch/jump tới label dùng PC-relative offset do assembler tự tính.
  • Hằng số có thể định nghĩa bằng .eqv UART, 0x10000000 và dùng lại trong immediate/address.
  • Relocation helper %hi(label)/%lo(label) dùng với lui/auipc/addi khi cần tự tách địa chỉ.
  • Không đặt instruction trong .data; chuyển về .text trước khi viết lệnh.
  • Nếu file bắt đầu bằng .data, nên chuyển sang .text 0x00400000 trước nhãn _start.

Operand key

rd Destination register, nơi ghi kết quả.
rs1, rs2 Source registers.
imm12 Immediate 12-bit có dấu, thường trong I/S-type.
label Nhãn trong chương trình, dùng cho branch/jump/la/call.
offset(base) Địa chỉ hiệu dụng = base + offset.
frd, frs1 Floating-point registers f0..f31 hoặc ABI như fa0.
rm Rounding mode tùy chọn: rne, rtz, rdn, rup, rmm, dyn.
.data
msg: .asciiz "Hello\n"

.text 0x00400000
.globl _start
_start:
    la   a0, msg
    li   a7, 4
    ecall

    li   a0, 0
    li   a7, 93
    ecall

Thanh ghi quan trọng

Register ABI Ý nghĩa thường dùng
x0 zero Luôn bằng 0; ghi vào x0 không làm thay đổi giá trị.
x1 ra Return address khi gọi hàm bằng jal/call.
x2 sp Stack pointer.
x3, x4 gp, tp Global/thread pointer theo ABI; simulator cho phép dùng như register thường.
x5-x7, x28-x31 t0-t6 Temporary registers, tiện cho biến tạm trong bài lab.
x8-x9, x18-x27 s0-s11 Saved registers, thường giữ giá trị qua lời gọi hàm.
x10-x17 a0-a7 Arguments/return values; a7 dùng làm syscall ID.
pc PC Program Counter, địa chỉ instruction hiện tại/tiếp theo.
f0-f31 ft/fa/fs Floating-point registers cho RV32F single precision; xem tab Floating Point để quan sát giá trị float và bit hex.

Instruction set được hỗ trợ

Bảng dưới đây mô tả các lệnh mà assembler và CPU simulator đang dùng trong phạm vi project. Các lệnh CSR/privileged, interrupt và privileged memory management chuẩn chưa nằm trong đường chạy hiện tại.

RV32I base integer

Nhóm Lệnh Cú pháp Ý nghĩa
R-type add sub rd, rs1, rs2 Cộng/trừ hai thanh ghi.
R-type sll srl sra rd, rs1, rs2 Dịch trái logic, dịch phải logic, dịch phải số học; shift amount lấy 5 bit thấp của rs2.
R-type slt sltu rd, rs1, rs2 So sánh signed/unsigned, ghi 1 nếu rs1 nhỏ hơn rs2.
R-type xor or and rd, rs1, rs2 Toán tử bitwise.
I-type addi slti sltiu xori ori andi rd, rs1, imm12 Phép toán với immediate 12-bit có dấu.
I-shift slli srli srai rd, rs1, shamt Dịch bit với shift amount 0..31.
Load lb lh lw lbu lhu rd, offset(rs1) Đọc byte/half/word từ memory; lbu/lhu zero-extend.
Store sb sh sw rs2, offset(rs1) Ghi byte/half/word từ rs2 xuống memory hoặc MMIO.
Branch beq bne blt bge bltu bgeu rs1, rs2, label Nhảy có điều kiện; signed hoặc unsigned tùy lệnh.
Jump jal rd, label Ghi pc+4 vào rd rồi nhảy tới label.
Jump jalr rd, rs1, imm hoặc rd, imm(rs1) Nhảy tới (rs1+imm)&~1, thường dùng cho return/function pointer.
Upper lui auipc rd, imm20 Nạp immediate cao hoặc cộng offset cao với PC.
System ecall ebreak ecall, ebreak Gọi syscall hoặc dừng bằng breakpoint exception.
Assembler-only fence fence pred, succ Assembler có thể mã hóa operand iorw, nhưng CPU simulator chưa mô phỏng hiệu ứng runtime của lệnh này.

RV32M multiply/divide

mul rd, rs1, rs2 32 bit thấp của phép nhân signed x signed.
mulh rd, rs1, rs2 32 bit cao của signed x signed.
mulhsu rd, rs1, rs2 32 bit cao của signed x unsigned.
mulhu rd, rs1, rs2 32 bit cao của unsigned x unsigned.
div divu rem remu rd, rs1, rs2 Chia và lấy dư signed/unsigned theo quy ước RV32M.

RV32F single precision

Với lệnh có rounding mode, operand rm là tùy chọn; nếu bỏ trống assembler dùng dyn. CPU hiện xử lý rounding rõ nhất ở nhóm fcvt, còn FCSR/fflags chưa được mô phỏng đầy đủ.

flw fsw frd, offset(rs1) / frs2, offset(rs1) Load/store float 32-bit.
fadd.s fsub.s fmul.s fdiv.s frd, frs1, frs2 Cộng, trừ, nhân, chia float.
fmadd.s fmsub.s fnmsub.s fnmadd.s frd, frs1, frs2, frs3 Fused multiply-add/subtract variants.
fsqrt.s frd, frs1 Căn bậc hai float.
fmin.s fmax.s frd, frs1, frs2 Minimum/maximum, có xử lý NaN cơ bản.
fsgnj.s fsgnjn.s fsgnjx.s frd, frs1, frs2 Copy/negate/xor sign bit.
fcvt.w.s fcvt.wu.s fcvt.s.w fcvt.s.wu rd/frd, frs1/rs1[, rm] Chuyển đổi int/unsigned int và float.
feq.s flt.s fle.s rd, frs1, frs2 So sánh float, kết quả ghi vào integer register.
fclass.s rd, frs1 Phân loại số float: zero, subnormal, normal, infinity, NaN.
fmv.x.w fmv.w.x rd, frs1 / frd, rs1 Di chuyển bit pattern giữa register integer và float.

Atomic đang có

amoadd.w là mở rộng RV32A minh họa cho atomic read-modify-write; nó hữu ích khi demo bus/atomic nhưng không phải thành phần chuẩn của RV32IMF subset.

amoadd.w rd, rs2, offset(rs1) Đọc word cũ ở memory, cộng rs2 vào memory, trả word cũ về rd.

Pseudo instructions

Pseudo Expand gần đúng Ghi chú
nop addi x0, x0, 0 Không làm gì.
li rd, imm addi hoặc lui + addi Assembler tự chọn 1 hoặc 2 instruction theo độ lớn immediate.
la rd, label auipc + addi Nạp địa chỉ label đúng theo PC-relative relocation đơn giản.
mv rd, rs addi rd, rs, 0 Copy register.
j label jal x0, label Nhảy không lưu return address.
jr rs jalr x0, rs, 0 Nhảy tới địa chỉ trong register.
ret jalr x0, ra, 0 Return từ function.
call label auipc ra + jalr ra Gọi subroutine xa hơn range của jal.
beqz rs, label beq rs, x0, label Branch nếu register bằng 0.
bnez rs, label bne rs, x0, label Branch nếu register khác 0.
fmv.s, fabs.s, fneg.s fsgnj.s variants Copy, absolute, negate float bằng sign injection.

Assembler directives

Các directive dữ liệu tự ghi theo little-endian. .word và .float tự căn 4 byte, .half tự căn 2 byte; chuỗi hỗ trợ escape cơ bản như \n, \t, \", \\.
Directive Cú pháp Ý nghĩa
.text .text [address] Chuyển sang vùng lệnh. Khi quay lại sau .data, nên viết rõ .text 0x00400000 để instruction bắt đầu ở text base.
.data .data [address] Chuyển sang vùng dữ liệu, mặc định 0x10010000.
.section .section .text, .section .rodata Hỗ trợ một số section phổ biến: text, data, rodata, bss, startup/hot/cold; section lạ sẽ được cảnh báo và bỏ qua.
.word .half .byte .word 1, 2, 0xFF Ghi dữ liệu 32-bit, 16-bit, 8-bit vào data memory.
.float .single .float 1.25, -3.5 Ghi float single-precision little-endian.
.ascii .ascii "abc" Ghi chuỗi không tự thêm byte null.
.asciiz .string .asciiz "abc\n" Ghi chuỗi và thêm byte 0 kết thúc.
.space .space 64 Dành sẵn số byte, khởi tạo 0.
.align .align 2 Căn địa chỉ theo 2^n byte; .align 2 là 4 byte.
.globl .global .globl _start Đánh dấu label global; simulator ưu tiên _start nếu có.
.extern .extern symbol Đánh dấu symbol ngoài; chủ yếu để tương thích input assembly.
.eqv .eqv UART, 0x10000000 Định nghĩa hằng số thay thế trong assembler; cũng chấp nhận dạng .eqv UART 0x10000000.
.org .org 0x10010100 Đặt địa chỉ hiện tại trong section.

ECALL / Syscall

Đặt syscall ID trong a7, đặt arguments trong a0, a1, a2, sau đó gọi ecall. Trong trình duyệt, các syscall in/exit hiển thị trong Console / Binary Output; UART MMIO vẫn dùng cho I/O thiết bị.
a7 Tên Input Output / tác dụng
1 PrintInt a0 = integer In số nguyên.
4 PrintString a0 = địa chỉ chuỗi null-terminated In chuỗi tới khi gặp byte 0.
64 Write stdout a0=1, a1=buffer, a2=count Ghi count byte; trả số byte đã ghi trong a0.
93 Exit a0 = exit code Dừng chương trình.
100 MMU Map Page a0=VA, a1=PA, a2=flags Map một page. Flags: bit0 R, bit1 W, bit2 X, bit3 cacheable.
101 MMU Unmap Page a0=VA Gỡ mapping của virtual page tương ứng.
102 MMU Clear Mappings Không cần Xóa page table/TLB mappings do simulator quản lý.
0 Halt/no-op Không cần Dừng CPU theo behavior hiện tại.

Memory map

Range / base Tên Ghi chú lập trình
0x00400000 Text segment Mặc định cho instruction sau .text; _start được ưu tiên làm PC ban đầu nếu có.
0x10010000 Data segment Mặc định cho dữ liệu sau .data.
0x10000000-0x10000013 UART TX/RX/status/control/baud divisor; MMIO không cache.
0xFF000000-0xFF000FFF LED Matrix 32x32 pixels, row-major, mỗi pixel 1 word 0x00RRGGBB; MMIO không cache.
0xFF100000-0xFF100013 Mouse X, Y, button bitmap, status, control.
0xFFFF0000-0xFFFF0007 Keyboard Control bit0 = ready; Data = ASCII char.
0xFFED0000-0xFFED0007 DMA registers CTRL và DESC FIFO, kết nối qua TileLink-UH.
Các địa chỉ khác Main Memory / RAM Đi qua MMU, cache L1I/L1D/L2 và TileLink-UH nếu không thuộc vùng MMIO.

I/O peripherals

UART 0x10000000

+0x00 TX write-only: ghi ASCII byte để gửi ra UART Console.
+0x04 RX read-only: đọc byte người dùng nhập.
+0x08 Status: bit0 TX ready, bit1 RX available, bit2/3 interrupt enable, bit4 TX busy/queue not empty.
+0x0C Control: bit0 TX interrupt enable, bit1 RX interrupt enable.
+0x10 Baud divisor; baud = 48MHz / (16 x divisor).

LED Matrix 0xFF000000

Mỗi pixel là một word. Offset pixel = ((row * 32) + col) * 4. Màu dùng dạng 0x00RRGGBB. Đọc vùng LED trả 0; ghi word sẽ cập nhật canvas.

Keyboard 0xFFFF0000

Đọc control +0x00, nếu bit0 = 1 thì đọc data +0x04 để lấy ASCII và pop khỏi buffer. Nhập ký tự trong ô Keyboard của I/O view để bơm dữ liệu vào buffer.

Mouse 0xFF100000

Đọc X/Y/button/status/control ở +0x00/+0x04/+0x08/+0x0C/+0x10. Button bitmap: bit0 left, bit1 right, bit2 middle. Ghi mask vào status để clear bit tương ứng, ví dụ 0x3 clear move/click.

DMA quick reference

CTRL +0x00 Read bits: bit0 EN, bit1 START latched, bit2 DONE, bits8..15 data FIFO count, bits16..19 descriptor FIFO depth log2, bit24 data FIFO empty, bit25 data FIFO full, bit27 descriptor FIFO empty, bit28 descriptor FIFO full, bit29 error, bit30 DONE mirror, bit31 busy. Write bit0 enable, bit1 start, bit27 acknowledge/clear done+error.
DESC +0x04 Write-only FIFO: ghi 3 word liên tiếp theo thứ tự source, destination, config; đọc trả 0.
config bits0..23 = elements, bit27 byte swap, bits28..29 source mode, bits30..31 destination mode. Mode 0 = byte fixed, 1 = word fixed, 2 = byte increment, 3 = word increment.

Đọc sơ đồ SoC

  • Mở sơ đồ bằng tab SoC; sơ đồ vẽ toàn bộ khối và các đường TileLink nối chúng.
  • Khối được tô màu theo nhóm trong Legend: Compute/Master (CPU, DMA), Memory & Caches (MMU, L1I/L1D/L2, Main Memory), TileLink Interconnect (UH/UL) và MMIO Peripherals (UART, LED, Keyboard, Mouse).
  • Có hai bus TileLink: TileLink-UH là bus coherent tốc độ cao nối CPU (qua L2) và DMA tới Main Memory; TileLink-UL là bus tiện ích tốc độ thấp nối các ngoại vi MMIO. Một cầu nối (bridge) bắc giữa UH và UL khi request đi sang vùng còn lại.
  • Đường CPU chính là RISC-V Core → MMU → L1 Cache → L2 → TileLink-UH → Main Memory; truy cập MMIO rẽ qua bridge UH/UL xuống TileLink-UL.
  • Khi chạy chương trình, các đường dây liên quan sẽ sáng lên để thể hiện luồng giao dịch đang đi qua (ví dụ fetch lệnh làm sáng nhánh L1I, load/store làm sáng nhánh L1D, MMIO làm sáng nhánh UL); dây tắt dần sau khi giao dịch kết thúc.
  • Hover vào từng khối để xem mô tả kiến trúc; nếu vừa có giao dịch, tooltip còn hiện thêm dòng Last Transaction mô tả giao dịch gần nhất qua khối.
  • Nhấp vào một khối để xem chi tiết ở tab tương ứng: CPU → Editor, MMU → MMU, các cache → Cache, Main Memory → Memory, ngoại vi (UART/LED/Keyboard/Mouse) → I/O. Nhấp vào DMA hoặc bus TileLink-UH/UL sẽ mở Systems Log đã lọc theo module đó.
Khối Vai trò
RISC-V Core Lõi CPU thực thi lệnh RV32IMF; fetch lệnh và load/store dữ liệu thông qua MMU.
MMU Dịch địa chỉ ảo (VA) sang địa chỉ vật lý (PA); trang 4 KB, TLB 16 mục liên kết đầy đủ (fully-associative), thay thế LRU.
L1I Cache Cache lệnh L1 giữ các lệnh vừa fetch; bỏ qua với địa chỉ non-cacheable/MMIO.
L1D Cache Cache dữ liệu L1 cho load/store của CPU; ghi theo write-through, thay thế LRU.
L2 Cache Cache chung hợp nhất, phục vụ miss của L1I/L1D trước khi xuống Main Memory.
DMA Controller Chuyển khối dữ liệu trực tiếp giữa bộ nhớ và ngoại vi, giảm tải cho CPU; thanh ghi tại 0xFFED0000.
TileLink-UH Bus coherent tốc độ cao nối CPU (qua L2) và DMA tới Main Memory và thanh ghi.
TileLink-UL Bus tiện ích tốc độ thấp nối các ngoại vi MMIO (UART, LED, Keyboard, Mouse) qua bridge adapter.
Main Memory RAM chính chứa code và biến chương trình; mô phỏng độ trễ truy cập vật lý 20 chu kỳ.
UART Giao tiếp nối tiếp theo ký tự; in output chương trình và nhận input console (MMIO 0x10000000).
LED Matrix Ma trận màu 32x32; ghi word trong vùng 0xFF000000 cập nhật màu pixel (0x00RRGGBB).
Keyboard Đệm phím nhấn dưới dạng mã ASCII để chương trình poll (MMIO 0xFFFF0000).
Mouse Báo tọa độ con trỏ (X, Y) và trạng thái click khi tương tác trên canvas LED Matrix (MMIO 0xFF100000).

Cache, MMU và bus

  • Đường CPU chính đi qua RISC-V Core -> MMU -> Cache -> TileLink-UH -> Main Memory.
  • MMIO như UART/LED/Keyboard/Mouse đi qua TileLink-UL và thường không cache.
  • Cache view có 3 tab: L1I cho instruction fetch, L1D cho data access, L2 shared cache.
  • Bảng cache hiển thị set/way/tag/dirty và thống kê read/write/hit/miss.
  • MMU view hiển thị nội dung TLB: VPN, PPN và thuộc tính trang (V = valid, R/W/X = quyền truy cập, C = cacheable — rút gọn từ page table entry của RISC-V Sv32).
  • Page table phần mềm nằm trong memory nên không hiển thị riêng; log MMU giúp thấy translate, hit/miss và permission fault.
  • Dùng Systems Log Console để thấy request/response CPU, MMU, cache, TileLink, DMA theo trình tự thời gian.
Thành phần Cấu hình/ý nghĩa
L1I / L1D 16 sets x 4 ways, block 64 byte; L1I dùng cho instruction fetch, L1D dùng cho load/store dữ liệu.
L2 64 sets x 4 ways, block 64 byte; shared phía dưới L1I/L1D.
MMU Page size cố định 4 KB, TLB 16 entries fully associative (LRU); địa chỉ chưa map dùng identity fallback (VA = PA).
Cacheability Main memory cacheable; UART/LED/Keyboard/Mouse/DMA registers là non-cacheable để MMIO phản ánh trạng thái thiết bị ngay.
TileLink TileLink-UH cho đường memory/cache/DMA registers, TileLink-UL cho MMIO chậm; bridge nối hai fabric khi request đi sang vùng còn lại.

Debugging checklist

Triệu chứng Nguyên nhân hay gặp Cách kiểm tra
Unknown mnemonic/directive Sai tên lệnh hoặc directive chưa hỗ trợ. Tra bảng Instruction set/Directives; chú ý dấu chấm trong lệnh float như fadd.s.
Unknown opcode khi chạy Assembler mã hóa được nhưng CPU chưa thực thi instruction đó, thường gặp với fence. Tránh đặt fence trong chương trình runtime hiện tại; dùng log CPU để xem PC dừng ở instruction nào.
Immediate out of range addi/lw/sw chỉ có immediate 12-bit; branch/jump có range riêng. Dùng li để nạp hằng lớn hoặc tách lui/addi.
Không nhảy đúng label Label đặt trong section sai hoặc branch offset không align. Assemble xong xem Instruction Memory và cột Source.
Register không đổi Ghi vào x0, hoặc lệnh chưa chạy do PC/branch. Step từng lệnh, quan sát PC và dòng được highlight.
UART không in ký tự TX chưa ready hoặc địa chỉ sai. Poll bit0 ở UART_STATUS trước khi ghi TX; nếu cần chờ truyền xong, poll bit4 TX busy về 0.
LED không sáng Tính sai offset pixel hoặc màu bằng 0. Offset phải nhân 4; màu nên dạng 0x00RRGGBB.
Run quá lâu Vòng lặp vô hạn không có exit/breakpoint. Đặt breakpoint hoặc thêm li a7,93; ecall.
Unsupported syscall ID a7 không thuộc bảng syscall của simulator hoặc bị ghi đè trước ecall. Step tới ngay trước ecall và kiểm tra a7, a0-a2.
DMA không chạy Chưa enable, descriptor chưa đủ 3 word, config sai mode/length, hoặc đang poll sai DONE/BUSY bit. Đọc CTRL: bit31 busy, bit2/bit30 done, bit29 error; lọc log module DMA và TileLink.
MMU permission fault Page chưa map hoặc thiếu quyền R/W/X/cacheable phù hợp. Lọc log module MMU (dòng [MMU] FAULT) hoặc dùng syscall 100 để map lại với flags đúng.
Float khác kỳ vọng Simulator chưa mô phỏng đầy đủ FCSR/fflags/frm và không đảm bảo bit-exact mọi corner case IEEE 754. Kiểm tra tab Floating Point, bit pattern bằng fmv.x.w, và dùng rounding mode rõ ràng cho fcvt.

Glossary (thuật ngữ)

Các thuật ngữ thường gặp khi dùng trình mô phỏng, sắp theo bảng chữ cái. Số liệu cấu hình (TLB, cache, trang) đúng với cấu hình thực tế của simulator.

Thuật ngữ Giải thích
Breakpoint Điểm dừng đặt tại một dòng lệnh; khi PC chạm tới, CPU tạm dừng để bạn quan sát thanh ghi và bộ nhớ. Đặt bằng cách click vào gutter trong Editor.
Cache hit / miss Hit là khi dữ liệu cần truy cập đã có trong cache (tag trùng, valid); miss là khi không có và phải lấy từ cấp thấp hơn (L2 hoặc Main Memory).
Cacheable / non-cacheable Main Memory là cacheable; các vùng MMIO (UART, LED, Keyboard, Mouse, thanh ghi DMA) là non-cacheable để phản ánh trạng thái thiết bị ngay.
Directive Chỉ thị cho assembler bắt đầu bằng dấu chấm (.text, .data, .word, .asciz, .eqv), không phải lệnh CPU; dùng để khai báo section, dữ liệu và hằng số.
Dirty bit Cờ (modified) đánh dấu một dòng cache đã từng bị ghi. Trình mô phỏng này dùng write-through nên dữ liệu được ghi xuống bộ nhớ ngay khi store; cờ dirty được đặt nhưng không kích hoạt ghi-ngược khi thay thế dòng.
DMA Direct Memory Access — khối truyền dữ liệu giữa bộ nhớ và thiết bị mà không cần CPU sao chép từng word. Cấu hình qua thanh ghi tại 0xFFED0000 (CTRL và DESC FIFO), kết nối qua TileLink-UH.
ECALL / Syscall Lệnh ecall kích hoạt dịch vụ hệ thống do simulator cung cấp (in số/chuỗi, đọc nhập, thoát chương trình...); mã dịch vụ đặt trong a7, tham số trong a0..a2. Ví dụ a7=93 là exit.
FPU / rounding mode Đơn vị dấu phẩy động xử lý lệnh float (fadd.s, fcvt...). Rounding mode (rne, rtz, rdn, rup, rmm, hoặc dyn) đặt cách làm tròn; bỏ trống thì assembler dùng dyn.
Fully associative Tổ chức trong đó một mục có thể nằm ở bất kỳ vị trí nào (không ràng buộc theo set). TLB của MMU dùng kiểu fully associative 16 entry.
Identity mapping (fallback) Khi một địa chỉ ảo (VA) không có trong page table, MMU ánh xạ thẳng VA = PA. Đây là cơ chế dự phòng giúp chương trình chạy được mà không cần thiết lập bảng trang.
Immediate Hằng số mã hóa trực tiếp trong lệnh. Lệnh kiểu I (addi, lw, sw...) có immediate 12-bit có dấu; hằng lớn dùng li hoặc tách lui/addi.
IPS Instructions Per Second — số lệnh CPU thực thi mỗi giây, làm chỉ số tốc độ mô phỏng. Không phản ánh tốc độ phần cứng thật, chỉ là thông lượng của trình mô phỏng.
Little-endian Quy ước lưu byte thấp của một word ở địa chỉ thấp. Directive dữ liệu (.word, .float...) và bộ nhớ đều theo little-endian.
LRU Least Recently Used — chính sách thay thế chọn loại bỏ mục lâu nhất chưa được dùng khi cần chỗ trống. Cả cache (L1/L2) và TLB của MMU đều dùng LRU.
MMIO Memory-Mapped I/O — thiết bị ngoại vi được điều khiển bằng cách đọc/ghi vào địa chỉ bộ nhớ cố định (UART, LED, Keyboard, Mouse, DMA). Các vùng này non-cacheable và đi qua TileLink-UL.
MMU Memory Management Unit — dịch địa chỉ ảo sang vật lý và kiểm tra quyền truy cập. Cấu hình cố định trang 4 KB, TLB 16 entry, theo mô hình rút gọn của RISC-V Sv32; dùng identity mapping khi chưa có trang.
Page (trang) Đơn vị bộ nhớ MMU quản lý khi dịch địa chỉ. Kích thước cố định 4 KB; địa chỉ ảo chia thành VPN (số trang) và offset trong trang.
PPN Physical Page Number — số trang vật lý sau khi dịch, ghép với offset để tạo địa chỉ thực. Hiển thị trong bảng TLB của MMU view.
Pseudo-instruction Lệnh tiện ích do assembler dịch thành một hoặc nhiều lệnh thật (vd li, mv, la, nop, j). Giúp viết mã gọn nhưng CPU vẫn chỉ thực thi lệnh cơ sở.
Relocation %hi / %lo Cặp helper tách địa chỉ một label thành 20 bit cao (%hi, dùng với lui) và 12 bit thấp có dấu (%lo, dùng với addi/lw/sw) để nạp địa chỉ 32-bit qua hai lệnh.
Set Một nhóm trong cache mà địa chỉ ánh xạ tới theo index; mỗi set chứa nhiều way. L1I/L1D có 16 set, L2 có 64 set (mỗi set 4 way).
Set-associative Tổ chức cache trong đó mỗi địa chỉ ánh xạ vào một set cố định nhưng có thể nằm ở một trong nhiều way của set đó. Cache ở đây là 4-way set-associative.
Tag Phần địa chỉ lưu trong cache để xác định dòng đang giữ thuộc khối bộ nhớ nào; so tag với địa chỉ truy cập (kèm bit valid) để quyết định hit hay miss.
TileLink (UH / UL) Giao thức bus nối các khối SoC. TileLink-UH (Uncached Heavyweight) cho đường tốc độ cao memory/cache/thanh ghi DMA; TileLink-UL (Uncached Lightweight) cho MMIO tiện ích chậm; bridge nối hai fabric khi request đi sang vùng còn lại.
TLB Translation Lookaside Buffer — bộ đệm các phép dịch VPN→PPN gần đây để tăng tốc MMU. Cấu hình 16 entry fully associative, thay thế LRU; TLB hit tránh phải tra page table.
Two-pass assembler Quy trình biên dịch hai lượt: lượt 1 thu thập địa chỉ các label, lượt 2 mã hóa lệnh và điền địa chỉ; nhờ vậy có thể tham chiếu label nằm phía sau.
Valid bit Cờ cho biết một dòng cache (hoặc entry TLB) đang chứa dữ liệu hợp lệ. Tra cứu chỉ tính là hit khi valid được đặt và tag/VPN trùng khớp.
VPN Virtual Page Number — số trang ảo, phần cao của địa chỉ ảo (bỏ 12 bit offset của trang 4 KB). MMU dùng VPN để tra TLB tìm ra PPN.
Way Một vị trí chứa dòng cache bên trong một set; số way là độ kết hợp (associativity). Cache ở đây 4 way mỗi set, nên một set giữ tối đa 4 dòng.
Write-through Chính sách ghi của cache trong trình mô phỏng này: lệnh store vừa cập nhật dòng cache vừa ghi đồng thời xuống cấp thấp hơn ngay. Không có bước ghi-ngược (write-back) khi thay thế; dòng victim bị loại bỏ trực tiếp. Cả L1I/L1D và L2 đều dùng write-through.

Ví dụ mẫu

UART: in hai ký tự

Ghi ASCII vào TX, poll status trước khi gửi byte tiếp theo.

LED Matrix: tô gradient

Duyệt 32x32 pixel và ghi word màu 0x00RRGGBB.

Syscall: in chuỗi rồi exit

Dùng a7=4 để print string và a7=93 để exit.

DMA: copy chuỗi ra UART

Đẩy descriptor 3 word, start DMA, poll DONE rồi chờ UART hết busy.

Vòng lặp & rẽ nhánh: tổng 1..N

Tính 1+2+...+N bằng blt/beq/addi/add, in kết quả bằng syscall 1.

Số thực (float): (a+b)*c

Dùng fcvt.s.w, fadd.s, fmul.s; xem bit pattern qua fmv.x.w và in bằng fcvt.w.s.

Số nguyên: giai thừa N!

Vòng lặp nhân dồn bằng mul (RV32M), in kết quả bằng syscall 1.