simulate-cpu-architecture
Acerca de
Esta habilidad permite a los desarrolladores diseñar y simular una CPU mínima desde cero, incluyendo la definición de un ISA, la construcción del datapath y la implementación del ciclo de búsqueda-decodificación-ejecución. Es un ejercicio culminante para componer bloques de lógica combinacional y secuencial en un procesador completo. Úsala para comprender profundamente la arquitectura de la CPU, siguiendo la ejecución de un programa ciclo de reloj por ciclo de reloj.
Instalación rápida
Claude Code
Recomendadonpx skills add pjt222/agent-almanac -a claude-code/plugin add https://github.com/pjt222/agent-almanacgit clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/simulate-cpu-architectureCopia y pega este comando en Claude Code para instalar esta habilidad
Documentación
模擬 CPU 架構
從零設計一最小但完整之 CPU:定義指令集架構、組合 ALU 與暫存器檔為資料路徑、設計控制單元為每一指令階段產生正確訊號、實現取指-解碼-執行循環、模擬一小程式至完成、並逐時鐘週期驗證每一暫存器與記憶體狀態。
適用時機
- 從第一原理學習或教授計算機架構
- 為 FPGA 或教學模擬器設計自訂處理器
- 驗證對指令於閘級與暫存器傳輸層執行之理解
- 建構 CPU 之軟體模擬(Python、JavaScript 或結構化逐步說明)
- 將 design-logic-circuit 之組合塊與 build-sequential-circuit 之時序塊組合為可運作之系統
輸入
- 必要:處理器複雜度目標——4 位元、8 位元或 16 位元資料寬度;通用暫存器數(2-16)
- 必要:最小指令集——至少:load、store、add、subtract、bitwise AND/OR、branch、halt
- 選擇性:直接定址以外之定址模式(立即、暫存器間接、索引)
- 選擇性:附加指令(multiply、shift、compare、用於子程式之 jump-and-link)
- 選擇性:記憶體大小與字寬
- 選擇性:管線階段(單週期、多週期或管線化)——預設為多週期
- 選擇性:實現媒介——軟體模擬(Python/JS)、HDL(Verilog/VHDL)或紙上演練
步驟
步驟一:定義指令集架構
指明程式設計師為此 CPU 寫機器碼所需知之一切:
- 資料寬度:選擇資料(ALU 運算元大小)與位址之位元寬度。常見選擇:8 位元資料/8 位元位址(256 位元組可定址)、16 位元資料/16 位元位址。
- 暫存器檔:定義通用暫存器之數及任何特殊用途暫存器。
- 通用:R0-R(N-1)。決定 R0 是否硬接至零(簡化指令編碼)。
- 特殊用途:程式計數器(PC)、指令暫存器(IR)、狀態/旗標暫存器(Zero、Carry、Negative、Overflow)。
- 指令格式:設計固定寬度之指令字。將位元分為欄位:
- Opcode:識別運算。以 K 位元,可支援至 2^K 條指令。
- 暫存器欄位:源與目的暫存器位址。N 個暫存器時,每欄位需 ceil(log2(N)) 位元。
- 立即/偏移欄位:用於常數或分支偏移。用剩餘位元。
- 指令目錄:定義每條指令之助記符、opcode 編碼、運算元欄位、運算(以 RTL 表示法)及受影響旗標。
- 定址模式:定義運算元如何定位。
- 暫存器:運算元在暫存器中。
- 立即:運算元嵌入指令中。
- 直接:運算元位址在指令中。
- 暫存器間接:運算元位址在暫存器中。
## ISA Specification
- **Data width**: [N] bits
- **Address width**: [M] bits
- **Registers**: [count] general-purpose + [list of special-purpose]
- **Instruction width**: [W] bits
### Instruction Format
| Field | Bits | Width |
|----------|-----------|-------|
| Opcode | [W-1:X] | [n] |
| Rd | [X-1:Y] | [n] |
| Rs | [Y-1:Z] | [n] |
| Imm | [Z-1:0] | [n] |
### Instruction Catalog
| Mnemonic | Opcode | Format | RTL Operation | Flags |
|----------|--------|-----------|------------------------|-------|
| LOAD | 0000 | Rd, [addr]| Rd <- MEM[addr] | - |
| STORE | 0001 | Rs, [addr]| MEM[addr] <- Rs | - |
| ADD | 0010 | Rd, Rs | Rd <- Rd + Rs | Z,C,N |
| ... | ... | ... | ... | ... |
| HALT | 1111 | - | Stop execution | - |
預期: 完整之 ISA 規格,每條指令具獨一 opcode、明確之運算元欄位、無歧義之 RTL 描述及記錄之旗標效應。指令編碼須可無歧義解碼。
失敗時: 若指令字過窄無法編碼所有需要欄位,要麼加寬指令、減少暫存器數、用變長指令(解碼較複雜),要麼將指令拆為次運算。若 opcode 衝突,重新分配編碼。
步驟二:設計資料路徑
建構移動與變換資料之暫存器傳輸層硬體:
- ALU:以 design-logic-circuit 技能設計。ALU 取二 N 位元運算元與一運算選擇訊號,產生 N 位元結果及旗標輸出(Zero、Carry、Negative、Overflow)。
- 運算:ADD、SUB(透過二補數加)、AND、OR、XOR、NOT、SHIFT LEFT、SHIFT RIGHT、PASS-THROUGH(用於搬移與載入)。
- ALU 選擇寬度須容納所有所需運算。
- 暫存器檔:以 build-sequential-circuit 設計。一組暫存器具:
- 二讀埠(源 A、源 B)——以暫存器位址為輸入之組合讀。
- 一寫埠(目的)——由 RegWrite 控制訊號啟用之時鐘寫。
- 若 R0 硬接至零,覆蓋對 R0 之寫。
- 程式計數器(PC):N 位元暫存器具:
- 遞增邏輯(為下一順序指令之 PC + instruction_width/8)。
- 分支/跳轉目標之載入輸入。
- 由 PCsrc 訊號控制、於遞增與分支目標間選擇之多工器。
- 記憶體介面:分離或統一之指令與資料記憶體。
- 哈佛架構:分離之指令記憶體(執行期間僅讀)與資料記憶體(讀寫)。較簡,允許同時取指與資料存取。
- 馮諾依曼架構:指令與資料共用單一記憶體。需於不同週期排序取指與資料存取。
- 互連:連接組件之多工器與匯流排:
- ALU 輸入 A 多工器:暫存器讀埠 A 或 PC(用於 PC 相對定址)。
- ALU 輸入 B 多工器:暫存器讀埠 B 或符號擴展之立即值。
- 暫存器寫資料多工器:ALU 結果或記憶體讀資料(用於 load)。
- 記憶體位址多工器:PC(用於指令取指)或 ALU 結果(用於 load/store)。
## Datapath Components
| Component | Width | Ports / Signals |
|----------------|--------|------------------------------------|
| ALU | [N]-bit| OpA, OpB, ALUop -> Result, Flags |
| Register File | [N]-bit| RdAddrA, RdAddrB, WrAddr, WrData, RegWrite -> RdDataA, RdDataB |
| PC | [M]-bit| PCnext, PCwrite -> PCout |
| Instruction Mem| [W]-bit| Addr -> Instruction |
| Data Memory | [N]-bit| Addr, WrData, MemRead, MemWrite -> RdData |
## Datapath Multiplexers
| Mux Name | Inputs | Select Signal | Output |
|-------------|----------------------|---------------|-------------|
| ALU_B_mux | RegDataB, Immediate | ALUsrc | ALU OpB |
| WrData_mux | ALU Result, MemData | MemToReg | Reg WrData |
| PC_mux | PC+1, BranchTarget | PCsrc | PC next |
預期: 完整之資料路徑圖(以組件表與多工器表呈現),其中 ISA 中每條指令皆有可行路徑,使其資料能由源經 ALU、暫存器檔與記憶體流至目的。
失敗時: 若某指令無法以當前資料路徑執行(如 LOAD 無自記憶體至暫存器之路徑),加入缺少之多工器或資料路徑。逐條走過每指令之 RTL 運算,並追蹤所需訊號流經資料路徑。
步驟三:設計控制單元
建構為每條指令編排資料路徑之邏輯:
- 識別控制訊號:列出資料路徑中之每一多工器選擇、暫存器寫使能、記憶體讀/寫使能與 ALU 運算選擇訊號。
- 單週期控制(最簡):純組合控制單元,於一時鐘週期內由當前指令之 opcode 欄位導出所有控制訊號。
- 多週期控制(學習推薦):以 build-sequential-circuit 設計之有限狀態機,將每指令拆為階段:
- Fetch:自 PC 位址讀取指令;存入 IR;遞增 PC。
- Decode:以 IR 欄位讀暫存器檔;符號擴展立即欄位。
- Execute:執行 ALU 運算或計算記憶體位址。
- Memory access(僅 load/store):自資料記憶體讀或寫之。
- Write-back:將結果寫至目的暫存器。
- 控制訊號表:對每條指令與每一階段,指明每控制訊號之值。
- 硬接式 vs. 微程式式:
- 硬接式:控制 FSM 由閘與正反器構成。較快,較不靈活。
- 微程式式:微指令 ROM 存每狀態之控制訊號。每微指令含控制訊號值與下一狀態欄位。較慢,但易修改。
## Control Signals
| Signal | Width | Function |
|-----------|-------|---------------------------------------|
| ALUop | [k] | Selects ALU operation |
| ALUsrc | 1 | 0=register, 1=immediate for ALU B |
| RegWrite | 1 | Enable register file write |
| MemRead | 1 | Enable data memory read |
| MemWrite | 1 | Enable data memory write |
| MemToReg | 1 | 0=ALU result, 1=memory data to register |
| PCsrc | 1 | 0=PC+1, 1=branch target |
| IRwrite | 1 | Enable instruction register load |
## Multi-Cycle Control FSM
| State | Active Signals | Next State |
|---------|----------------------------------------|-------------------|
| FETCH | MemRead, IRwrite, PC <- PC+1 | DECODE |
| DECODE | Read registers, sign-extend immediate | EXECUTE |
| EXECUTE | ALUop=[per instruction], ALUsrc=[...] | MEM_ACCESS or WB |
| MEM_ACC | MemRead or MemWrite | WRITE_BACK |
| WB | RegWrite, MemToReg=[...] | FETCH |
預期: 控制單元(組合或 FSM)為每條指令之每階段產生正確之控制訊號值,無相衝訊號(如同一記憶體上同時 MemRead 與 MemWrite)。
失敗時: 若有控制訊號衝突,階段未妥善分離。確保 load 與 store 於不同階段存取記憶體,或記憶體介面支援於分離埠之同時讀寫。若 FSM 狀態過多,檢查某些指令是否共享階段而可合併。
步驟四:實現取指-解碼-執行循環
連接資料路徑與控制單元為可運作處理器:
- 時鐘分配:將系統時鐘連至所有正反器(PC、IR、暫存器檔、控制 FSM 狀態暫存器)。所有狀態更新於同一時鐘邊緣發生。
- 階段排序:將控制 FSM 輸出接至資料路徑控制訊號。FSM 每時鐘週期前進一狀態,驅動資料路徑經 Fetch -> Decode -> Execute -> Memory -> Write-back。
- 指令取指:於 FETCH 階段,PC 驅動指令記憶體位址匯流排。所取指令載入 IR。PC 遞增一指令寬度。
- 指令解碼:於 DECODE 階段,IR 之 opcode 欄位驅動控制單元以判定指令類型。IR 之暫存器位址驅動暫存器檔讀埠。
- 執行及之後:餘下階段視指令類型而定:
- ALU 指令:Execute(ALU 計算)、Write-back(結果至暫存器)。
- Load:Execute(ALU 計算位址)、Memory(讀資料記憶體)、Write-back(資料至暫存器)。
- Store:Execute(ALU 計算位址)、Memory(寫資料記憶體)。
- Branch:Execute(ALU 比較或檢查旗標)、條件性更新 PC。
- Halt:FSM 進終止狀態並停前進。
- 中斷與例外處理(選擇性):加入機制以保存 PC 並跳至處理器位址。需附加控制狀態與原因暫存器。
## Cycle Execution Summary
| Instruction Type | Phases | Cycles |
|-----------------|--------------------------------|--------|
| ALU (reg-reg) | Fetch, Decode, Execute, WB | 4 |
| Load | Fetch, Decode, Execute, Mem, WB| 5 |
| Store | Fetch, Decode, Execute, Mem | 4 |
| Branch (taken) | Fetch, Decode, Execute | 3 |
| Branch (not taken)| Fetch, Decode, Execute | 3 |
| Halt | Fetch, Decode | 2 |
預期: 全連通之處理器,控制 FSM 為每指令類型驅動資料路徑經正確階段序列,所有狀態轉換於時鐘邊緣同步發生。
失敗時: 若處理器卡死(永不達 HALT)或產生錯誤結果,最可能因為某特定階段之控制訊號錯誤。用步驟五之逐週期追蹤隔離失敗週期。若 PC 不正確遞增,檢查 FETCH 階段佈線。若寫至錯誤暫存器,檢查 IR 之暫存器位址欄位提取。
步驟五:模擬一小程式並驗證
執行具體程式並逐時鐘週期驗證預期狀態:
- 寫測試程式:選一程式小至可完整追蹤(5-15 條指令)但複雜至能演練多種指令類型。費氏數列計算為理想:用 load-immediate、add、branch 與 halt。
- 初始化狀態:所有暫存器置零。將程式自位址 0 開始載入指令記憶體。設 PC = 0。將控制 FSM 置 FETCH 狀態。
- 逐週期追蹤:對每時鐘週期記錄:
- 控制 FSM 狀態與階段名
- PC 值與正取指/執行之指令
- ALU 輸入、運算與結果
- 暫存器檔讀寫
- 記憶體讀寫
- 旗標暫存器值
- 所有控制訊號值
- 與手算驗證:獨立計算每指令完成後(非每週期——每指令需多週期)之預期暫存器與記憶體狀態。將模擬追蹤與此預期快照比對。
- 邊界情況:驗證以下行為:
- 分支不採(PC 正常遞增)
- 分支採(PC 載入分支目標)
- load 後立即使用所載暫存器(檢查寫回是否於下次解碼讀之前完成)
- 寫至 R0(若硬接零,寫應無效)
- HALT 指令(處理器乾淨停止)
## Test Program: Fibonacci (first 8 terms)
| Addr | Instruction | Mnemonic | Comment |
|------|---------------|------------------|----------------------|
| 0x00 | [encoding] | LOAD R1, #1 | R1 = 1 (F1) |
| 0x01 | [encoding] | LOAD R2, #1 | R2 = 1 (F2) |
| 0x02 | [encoding] | LOAD R3, #6 | R3 = 6 (loop count) |
| 0x03 | [encoding] | ADD R4, R1, R2 | R4 = R1 + R2 |
| 0x04 | [encoding] | MOV R1, R2 | R1 = R2 |
| 0x05 | [encoding] | MOV R2, R4 | R2 = R4 |
| 0x06 | [encoding] | SUB R3, R3, #1 | R3 = R3 - 1 |
| 0x07 | [encoding] | BNZ 0x03 | Branch if R3 != 0 |
| 0x08 | [encoding] | HALT | Stop |
## Cycle-by-Cycle Trace (excerpt)
| Cycle | Phase | PC | IR | ALU Op | Result | RegWrite | Flags |
|-------|---------|-----|----------|----------|--------|----------|-------|
| 1 | FETCH | 0x00| LOAD R1,1| - | - | No | - |
| 2 | DECODE | 0x01| LOAD R1,1| - | - | No | - |
| 3 | EXECUTE | 0x01| LOAD R1,1| PASS #1 | 1 | No | - |
| 4 | WB | 0x01| LOAD R1,1| - | - | R1 <- 1 | - |
| ... | ... | ... | ... | ... | ... | ... | ... |
## Expected Final State
| Register | Value | Description |
|----------|-------|---------------------|
| R1 | [val] | Second-to-last Fib |
| R2 | [val] | Last computed Fib |
| R3 | 0 | Loop counter done |
| R4 | [val] | Same as R2 |
| PC | 0x09 | One past HALT |
預期: 逐週期追蹤與預期最終狀態相符。每指令產生正確之暫存器與記憶體更新。程式於 HALT 終止,暫存器中含正確費氏值。
失敗時: 比對預期與實際狀態之首次分歧。常見因:(1) 某指令類型之 ALU 運算選擇錯誤——檢查控制訊號表。(2) 分支偏移計算差一——驗證分支是 PC 相對於當前還是下一指令位址。(3) 寫回寫至錯誤暫存器——檢查暫存器位址欄位提取。(4) 旗標未正確更新——對致差錯之具體運算元追蹤 ALU 旗標邏輯。
驗證
- ISA 至少含 load、store、add、subtract、AND、OR、branch 與 halt 指令
- 每指令具獨一 opcode 與無歧義編碼
- 資料路徑為每指令之 RTL 運算提供有效訊號路徑
- ALU 支援所有所需運算且旗標生成正確
- 暫存器檔有足夠讀寫埠以滿足指令格式
- 控制單元為每指令之每階段產生正確訊號
- 無控制訊號衝突(如同一記憶體埠之同時讀寫)
- 取指-解碼-執行循環完全連通且時鐘化
- 測試程式執行至完成且最終狀態正確
- 逐週期追蹤已與手算驗證
- 分支採與不採案例皆已驗證
- HALT 指令乾淨停止執行
常見陷阱
- 分支偏移差一:分支可能相對當前 PC、PC+1 或分支後之指令。於 ISA 中定義慣例並一致實現。分支目標之差一錯誤為 CPU 設計最單一常見之臭蟲。
- 多週期中之寫回/解碼相依:若指令 I 於寫回階段寫某暫存器,同時指令 I+1 於解碼階段讀該暫存器,讀可能取舊值。多週期 CPU(一次一指令)不為問題。管線化 CPU 則需轉送或暫停。
- 取指時忘記遞增 PC:若 FETCH 階段未遞增 PC,CPU 將永遠執行同一指令。為極常見之佈線錯誤。
- ALU 旗標鎖存:旗標應僅於 ALU 指令時更新,非於 load、store 或 branch。若旗標無條件更新,比較與分支間之 load 將破壞比較結果。
- 無號 vs. 有號混淆:於 ISA 定義時決定算術為有號(二補數)或無號,並依此實現 ALU 與旗標邏輯。Carry 旗標於有號 vs. 無號運算中語義不同。
- 記憶體對齊:若資料寬度與指令寬度不同,或指令多位元組,定義對齊規則。位元組可定址記憶體中之 16 位元指令佔兩位址;PC 須遞增 2 而非 1。
- 首次設計過於複雜:自最簡可能 CPU 起(8 位元、4 暫存器、8 指令、單週期或多週期、無管線)。複雜可後加;可運作之簡單設計教益勝於損壞之複雜者。
相關技能
design-logic-circuit— 設計 ALU、多工器、解碼器與其他組合塊build-sequential-circuit— 設計暫存器檔、程式計數器、控制 FSM 與其他時序塊evaluate-boolean-expression— 簡化硬接控制單元之控制邏輯方程derive-theoretical-result— 形式化效能分析(CPI、吞吐、Amdahl 定律)
Repositorio GitHub
Habilidades relacionadas
content-collections
MetaEsta habilidad proporciona una configuración probada en producción para Content Collections, una herramienta centrada en TypeScript que transforma archivos Markdown/MDX en colecciones de datos con tipado seguro mediante validación Zod. Úsala al construir blogs, sitios de documentación o aplicaciones Vite + React con mucho contenido para garantizar seguridad de tipos y validación automática de contenido. Abarca todo, desde la configuración del plugin de Vite y compilación MDX hasta la optimización de despliegue y validación de esquemas.
polymarket
MetaEsta habilidad permite a los desarrolladores crear aplicaciones con la plataforma de mercados de predicción Polymarket, incluyendo la integración de API para operaciones y datos de mercado. También proporciona transmisión de datos en tiempo real a través de WebSocket para monitorear operaciones en vivo y actividad del mercado. Úsela para implementar estrategias de trading o crear herramientas que procesen actualizaciones de mercado en tiempo real.
creating-opencode-plugins
MetaEsta habilidad ayuda a los desarrolladores a crear complementos de OpenCode que se conectan a más de 25 tipos de eventos, como comandos, archivos y operaciones LSP. Proporciona la estructura del complemento, las especificaciones de la API de eventos y los patrones de implementación para módulos en JavaScript/TypeScript. Úsala cuando necesites interceptar, monitorear o extender el ciclo de vida del asistente de IA de OpenCode con lógica personalizada basada en eventos.
sglang
MetaSGLang es un framework de alto rendimiento para el servicio de LLM que se especializa en generación rápida y estructurada para JSON, expresiones regulares y flujos de trabajo de agentes utilizando su caché de prefijos RadixAttention. Ofrece una inferencia significativamente más rápida, especialmente para tareas con prefijos repetidos, lo que lo hace ideal para salidas complejas y estructuradas, y conversaciones multiturno. Elige SGLang sobre alternativas como vLLM cuando necesites decodificación restringida o estés construyendo aplicaciones con uso extensivo de prefijos compartidos.
