CPU流水線
CPU的五級架構,也稱為五級流水線,是一種用於提高中央處理器(CPU)性能的設計架構,它將指令的執行過程分為五個階段,以實現並行處理。以下是五級流水線的簡要說明:
取指(IF - Instruction Fetch):在這個階段,CPU 從內存中提取下一條指令,並將其存儲在指令緩存中以供後續處理。
解碼(ID - Instruction Decode):在這個階段,CPU 對取得的指令進行解碼,識別出指令的類型和操作數,以確定如何執行。
執行(EX - Execute):在這個階段,CPU 執行指令所包含的操作,例如算術運算、邏輯運算等。
存儲(MEM - Memory Access):在這個階段,CPU 訪問記憶體(RAM)以讀取或寫入數據,這包括從記憶體中讀取數據或將計算結果寫回記憶體。
回寫(WB - Write Back):在這個階段,CPU 將執行完畢的指令的結果寫回 CPU 的寄存器文件或記憶體,以便供後續的指令使用。
對於處理器的流水線可以參考這個網站,有更祥細的說明。而不論是怎樣的處理器架構,基本上都是這五級流水線的延伸,而我們今天主要就是來實現基本的一個指令的流水線。
流水線實現及測試
首先我們將一道指令的pipe透過下面程式碼實現,
ALISS::run_pipe()
{
uint32_t insn = ALISS::IF(pc);
ALISS::ID_EX_WB(insn);
#ifdef INSN_DEBUG
dump_insn(insn);
#endif
pc = next_pc;
}
其中insn會透過IF得到相應的運算程式碼(OP Code),而CPU就是根據對應的OP Code去執行。接下來我們將得出來的OpCode丟到ID_EX_WB內,這裡將流水線的解碼、執行、回寫等部分結合在一起,原因如下:
但這樣子做的缺點則是將來如果想要擴充為時序模擬器的話會較不方便。
測試的程式碼則如下,我們今天先測試已經實現的IF及pc=next_pc段,對於IF我們可以簡單地修改昨天的ELF Loader的部分,因為在我們想實現的RISCV-64bit IMA我們的指令長度固定為一個word (32-bit),因此我們可以很簡單的寫出下面的程式碼。
uint32_t ALISS::IF()
{
return get_mem_w(pc);
}
TEST(IFTestSuite, InstFetchTest) {
const char* test = "test.elf";
ALISS::memory = (uint8_t *)std::malloc(4 * 1024 * 1024); //4MB size for test
ALISS::loadElf(test);
EXPECT_EQ(ALISS::IF(), 0x4197);
}
而pc = next_pc的部分,在沒有跳轉等指令時由於指令長度固定為一個word,因此執行完一個指令後pc的位置通常都是pc + 4,因此我們可以先簡單的在ID_EX_WB(insn)內寫入pc = pc + 4並進行測試。
void ALISS::ID_EX_WB(uint32_t insn)
{
///implement insn here
next_pc = pc + 4;
}
TEST(ID_EX_WB_TestSuite, PCNextTest) {
const char* test = "test.elf";
ALISS::memory = (uint8_t *)std::malloc(4 * 1024 * 1024); //4MB size for test
ALISS::loadElf(test);
ALISS::rum_pipe();
EXPECT_EQ(ALISS::pc, 0x1011a) //0x10116 + 4;
}
確認測試完成,收工。
碎碎念 : 今天打到一半的時候點到下面的it邦使用說明就跳掉了...這告訴我們隨時儲存草稿有益身心健康