計(jì):WBsel與MemRM控制信號的硬件復(fù)用原理與實(shí)踐)
在實(shí)際的單周期 CPU 設(shè)計(jì)教學(xué)中初學(xué)者常常會困惑于控制信號WBsel和MemRM的作用。它們看起來都像是“選擇器”一個用于選擇寫回寄存器的數(shù)據(jù)來源一個用于控制內(nèi)存讀寫似乎只是兩個獨(dú)立的控制單元。但深入其硬件實(shí)現(xiàn)層面你會發(fā)現(xiàn)一個關(guān)鍵的設(shè)計(jì)思想硬件復(fù)用。這并非簡單的“找不同”而是通過精心設(shè)計(jì)的電路讓同一組物理硬件在不同的控制信號下執(zhí)行不同的功能從而在有限的晶體管資源內(nèi)實(shí)現(xiàn)更復(fù)雜的指令集。本文將帶你從零開始理解WBsel和MemRM在單周期 CPU 數(shù)據(jù)通路中的角色并重點(diǎn)剖析它們背后“硬件復(fù)用”的實(shí)現(xiàn)邏輯。你將看到一個看似簡單的多路選擇器MUX如何成為連接運(yùn)算器、內(nèi)存和寄存器堆的關(guān)鍵樞紐以及如何通過控制信號的組合讓 ALU 的輸出既能作為運(yùn)算結(jié)果又能作為內(nèi)存地址。本文適合正在學(xué)習(xí)計(jì)算機(jī)組成原理、數(shù)字邏輯設(shè)計(jì)尤其是嘗試用 Verilog/VHDL 實(shí)現(xiàn)單周期 CPU 的讀者。跟隨本文你將能清晰地畫出包含數(shù)據(jù)選擇的數(shù)據(jù)通路并理解每一條控制信號線是如何被精確生成的。1. 核心概念數(shù)據(jù)通路中的“岔路口”與“交警”在深入代碼之前必須建立對單周期 CPU 數(shù)據(jù)通路的整體認(rèn)知。數(shù)據(jù)通路如同城市道路數(shù)據(jù)在其中流動。而WBsel和MemRM這類信號就是路口的“交警”和“岔路口的指示牌”它們不生產(chǎn)數(shù)據(jù)而是指揮數(shù)據(jù)的流向。1.1 什么是指令執(zhí)行的數(shù)據(jù)流一條指令的執(zhí)行本質(zhì)上是數(shù)據(jù)在寄存器、運(yùn)算器ALU、內(nèi)存等部件間的一次定向流動。以 MIPS 架構(gòu)中的幾條典型指令為例add rd, rs, rt數(shù)據(jù)從rs和rt寄存器流出進(jìn)入 ALU 相加結(jié)果流回rd寄存器。lw rt, offset(rs)數(shù)據(jù)從rs寄存器流出與符號擴(kuò)展后的立即數(shù)offset在 ALU 相加得到內(nèi)存地址。CPU 根據(jù)此地址從內(nèi)存讀取數(shù)據(jù)最終流回rt寄存器。sw rt, offset(rs)數(shù)據(jù)從rs寄存器流出與立即數(shù)在 ALU 相加得到內(nèi)存地址同時將rt寄存器中的數(shù)據(jù)寫入該內(nèi)存地址??梢钥吹紸LU 在這三條指令中扮演了不同角色在add中是運(yùn)算器在lw和sw中則是地址計(jì)算器。這就是最基礎(chǔ)的硬件復(fù)用同一個 ALU 硬件在不同指令下用于完成不同語義的計(jì)算任務(wù)。1.2 WBsel寫回?cái)?shù)據(jù)的選擇器WBselWrite Back Select信號直接決定了最終要寫入目標(biāo)寄存器的數(shù)據(jù)從哪里來。在單周期 CPU 中寫回寄存器的數(shù)據(jù)來源通常有三種ALU 的運(yùn)算結(jié)果用于算術(shù)邏輯指令如add,sub,and,or等。數(shù)據(jù)存儲器Data Memory的輸出用于加載指令如lw從內(nèi)存讀出的數(shù)據(jù)需要寫回寄存器。下一條指令的地址PC4或其它值用于jal跳轉(zhuǎn)并鏈接等指令將返回地址保存到$ra寄存器。WBsel就是一個多路選擇器MUX的控制端。它根據(jù)當(dāng)前正在執(zhí)行的指令類型選擇上述三路或更多數(shù)據(jù)中的一路連接到寄存器堆的“寫數(shù)據(jù)”輸入端。// 一個簡化的 WBsel MUX 的 Verilog 描述 module wb_mux ( input [1:0] WBsel, // 2位控制信號可選4種來源 input [31:0] alu_result, // 來源1ALU運(yùn)算結(jié)果 input [31:0] mem_read_data, // 來源2內(nèi)存讀取數(shù)據(jù) input [31:0] pc_plus_4, // 來源3PC4用于JAL input [31:0] imm_ext, // 來源4立即數(shù)用于LUI等 output reg [31:0] wb_data // 輸出最終寫回寄存器的數(shù)據(jù) ); always (*) begin case (WBsel) 2b00: wb_data alu_result; 2b01: wb_data mem_read_data; 2b10: wb_data pc_plus_4; 2b11: wb_data imm_ext; default: wb_data 32b0; endcase end endmodule1.3 MemRM內(nèi)存訪問模式的控制信號MemRMMemory Read/Write Mode這個信號名稱可能因設(shè)計(jì)而異常見的是MemWrite和MemRead。它控制著數(shù)據(jù)存儲器DM的訪問行為。MemWrite當(dāng)為高電平時在時鐘有效沿將數(shù)據(jù)寫入指定地址的內(nèi)存單元。對應(yīng)sw指令。MemRead當(dāng)為高電平時根據(jù)地址輸出對應(yīng)內(nèi)存單元的數(shù)據(jù)。對應(yīng)lw指令。注意對于單周期設(shè)計(jì)MemRead信號有時可以省略因?yàn)橹灰粚懬业刂酚行?nèi)存模塊通常會持續(xù)輸出數(shù)據(jù)。但顯式地使用MemRead信號是更規(guī)范和安全的做法尤其在后續(xù)流水線設(shè)計(jì)中可以避免不必要的功耗和沖突。MemRM信號直接連接到數(shù)據(jù)存儲器的讀寫使能端。它的生成依賴于指令譯碼器對操作碼opcode的識別。2. 硬件復(fù)用的具體體現(xiàn)ALU 與地址計(jì)算現(xiàn)在我們來聚焦“硬件復(fù)用”的核心。為什么說WBsel和MemRM體現(xiàn)了硬件復(fù)用關(guān)鍵在于ALU 輸出端所連接的兩條路徑。2.1 數(shù)據(jù)通路交叉點(diǎn)分析觀察一個整合了lw/sw和 R-type 指令的數(shù)據(jù)通路圖或代碼你會發(fā)現(xiàn)一個關(guān)鍵結(jié)構(gòu)寄存器堆 Read Data 1 -- ALU 輸入端 A 寄存器堆 Read Data 2 -- 一個前導(dǎo) MUX -- ALU 輸入端 B ALU 輸出端 -- 連接到兩個下游部件 1. 數(shù)據(jù)存儲器的“地址”輸入端。 2. WBsel MUX 的“ALU結(jié)果”輸入端。這個結(jié)構(gòu)意味著對于lw和sw指令A(yù)LU 執(zhí)行的是“基址寄存器 偏移量”的加法其輸出ALUResult被用作內(nèi)存地址送往數(shù)據(jù)存儲器。對于add等 R-type 指令A(yù)LU 執(zhí)行的是“rs rt”的加法其輸出ALUResult被作為運(yùn)算結(jié)果送往WBselMUX并最終可能寫回寄存器。復(fù)用點(diǎn)同一個 ALU 硬件同一組輸入端口同一個輸出端口因?yàn)橹噶畈煌漭敵鼋Y(jié)果被后續(xù)電路用于完全不同的目的??刂菩盘朅LUOp決定 ALU 執(zhí)行加、減、與、或等操作和ALUSrc決定 ALU 的第二個操作數(shù)來自寄存器還是立即數(shù)協(xié)同工作確保了 ALU 能為不同指令產(chǎn)生正確的輸出值。而WBsel和MemRM則負(fù)責(zé)將這個輸出值“引導(dǎo)”到正確的目的地。2.2 控制信號的協(xié)同生成硬件復(fù)用得以正確工作的前提是所有控制信號必須根據(jù)當(dāng)前指令精確、同步地生成。這由一個主控制器Control Unit完成。主控制器讀取指令的opcode和funct字段并產(chǎn)生一整組控制信號。以下是一個簡化的控制信號真值表展示了對于不同指令關(guān)鍵信號是如何設(shè)置的指令RegWrite(寫寄存器)MemtoReg(WBsel)MemWriteMemReadALUSrcALUOp功能描述add10 (來自ALU)000 (用rt)加法ALU結(jié)果寫回寄存器lw11 (來自內(nèi)存)011 (用立即數(shù))加法ALU計(jì)算地址讀內(nèi)存數(shù)據(jù)寫回寄存器sw0X (不寫回)101 (用立即數(shù))加法ALU計(jì)算地址將rt數(shù)據(jù)寫入內(nèi)存beq0X000 (用rt)減法ALU做減結(jié)果用于比較決定是否分支注意MemtoReg就是WBsel的一種常見命名當(dāng)其值為0時選擇 ALU 結(jié)果為1時選擇內(nèi)存數(shù)據(jù)。ALUSrc控制著 ALU 第二個操作數(shù)的 MUX是復(fù)用鏈路上的另一個關(guān)鍵“交警”。從表中可以清晰看到執(zhí)行l(wèi)w時ALUSrc1讓 ALU 用立即數(shù)做加法算地址MemRead1啟動內(nèi)存讀MemtoReg1讓寫回?cái)?shù)據(jù)選擇內(nèi)存輸出。執(zhí)行add時ALUSrc0讓 ALU 用兩個寄存器值做加法算結(jié)果MemRead0和MemWrite0讓內(nèi)存不工作MemtoReg0讓寫回?cái)?shù)據(jù)選擇 ALU 輸出。這就是硬件復(fù)用的精髓通過一組隨時間變化按指令變化的控制信號動態(tài)地配置數(shù)據(jù)通路中固定硬件單元之間的連接關(guān)系和功能從而用一套硬件支持多種指令。3. 從理論到實(shí)現(xiàn)一個簡化的單周期 CPU 關(guān)鍵模塊讓我們用 Verilog 代碼片段來具體化上述概念。這里不會給出完整 CPU而是聚焦于展示W(wǎng)Bsel、MemRM與數(shù)據(jù)通路其他部分的連接。3.1 頂層模塊的數(shù)據(jù)通路連接假設(shè)我們已經(jīng)有了以下模塊pc_reg程序計(jì)數(shù)器、imem指令存儲器、regfile寄存器堆、alu運(yùn)算器、dmem數(shù)據(jù)存儲器、control_unit控制器、sign_extend符號擴(kuò)展器以及多個mux多路選擇器。module single_cycle_cpu ( input wire clk, input wire rst_n ); // 指令獲取階段 wire [31:0] pc_current, pc_next, pc_plus_4; wire [31:0] instruction; // ... PC更新邏輯 ... // 譯碼階段 wire [5:0] opcode instruction[31:26]; wire [4:0] rs instruction[25:21]; wire [4:0] rt instruction[20:16]; wire [4:0] rd instruction[15:11]; wire [5:0] funct instruction[5:0]; wire [15:0] imm16 instruction[15:0]; wire [31:0] read_data1, read_data2; wire [31:0] sign_extended_imm; regfile REG_FILE ( .clk(clk), .we(RegWrite), // 來自控制器 .raddr1(rs), .rdata1(read_data1), .raddr2(rt), .rdata2(read_data2), .waddr(RegDst ? rd : rt), // RegDst是另一個選擇信號選擇寫目標(biāo) .wdata(write_data) // 來自最終的WB MUX ); sign_extend SIGN_EXT ( .imm16(imm16), .imm32(sign_extended_imm) ); // 執(zhí)行階段 wire [31:0] alu_src_b ALUSrc ? sign_extended_imm : read_data2; // ALUSrc控制MUX wire [31:0] alu_result; wire alu_zero; // 用于beq判斷 alu ALU ( .a(read_data1), .b(alu_src_b), .alu_ctrl(ALUCtrl), // ALUCtrl由ALU控制單元根據(jù)ALUOp和funct生成 .result(alu_result), .zero(alu_zero) ); // 內(nèi)存訪問階段 wire [31:0] mem_read_data; dmem DATA_MEM ( .clk(clk), .addr(alu_result), // 關(guān)鍵復(fù)用點(diǎn)ALU輸出作為內(nèi)存地址 .write_data(read_data2), .mem_write(MemWrite), // 來自控制器 .mem_read(MemRead), // 來自控制器 .read_data(mem_read_data) ); // 寫回階段 wire [31:0] write_data; // 要寫回寄存器的數(shù)據(jù) // WBsel MUX (這里用MemtoReg信號名) assign write_data MemtoReg ? mem_read_data : alu_result; // 更復(fù)雜的WBsel可能還需要選擇pc_plus_4等這里做了簡化 // 控制單元 control_unit CTRL ( .opcode(opcode), .RegDst(RegDst), .RegWrite(RegWrite), .ALUSrc(ALUSrc), .ALUOp(ALUOp), // 給ALU控制單元的指令類型提示 .MemWrite(MemWrite), .MemRead(MemRead), .MemtoReg(MemtoReg), .Branch(Branch) // ... 其他信號 ); // ALU控制單元 alu_control ALU_CTRL ( .ALUOp(ALUOp), .funct(funct), .ALUCtrl(ALUCtrl) ); endmodule關(guān)鍵代碼解釋dmem模塊的.addr(alu_result)這是硬件復(fù)用的核心體現(xiàn)。無論 ALU 進(jìn)行的是算術(shù)運(yùn)算還是地址計(jì)算其結(jié)果都連接到內(nèi)存地址線。assign write_data MemtoReg ? mem_read_data : alu_result;這是WBsel此處叫MemtoReg的簡化實(shí)現(xiàn)。它決定了寫回?cái)?shù)據(jù)是來自內(nèi)存還是 ALU??刂菩盘朅LUSrc,MemWrite,MemRead,MemtoReg全部由control_unit根據(jù)opcode產(chǎn)生。它們像一套組合拳共同指揮單周期內(nèi)數(shù)據(jù)的流動。3.2 控制單元的實(shí)現(xiàn)片段控制單元是硬件復(fù)用的“大腦”。它本質(zhì)上是一個大的組合邏輯電路也可以用時序邏輯實(shí)現(xiàn)狀態(tài)但單周期常用組合邏輯。module control_unit ( input [5:0] opcode, output reg RegDst, RegWrite, ALUSrc, output reg MemWrite, MemRead, MemtoReg, output reg Branch, output reg [1:0] ALUOp ); always (*) begin // 默認(rèn)值防止產(chǎn)生鎖存器 {RegDst, RegWrite, ALUSrc, MemWrite, MemRead, MemtoReg, Branch, ALUOp} 10b0; case (opcode) 6b000000: begin // R-type: add, sub, etc. RegDst 1b1; RegWrite 1b1; ALUSrc 1b0; MemWrite 1b0; MemRead 1b0; MemtoReg 1b0; Branch 1b0; ALUOp 2b10; // 告訴ALU控制單元去查funct字段 end 6b100011: begin // lw RegDst 1b0; // 目標(biāo)寄存器是rt RegWrite 1b1; ALUSrc 1b1; // 第二個操作數(shù)用立即數(shù) MemWrite 1b0; MemRead 1b1; // 關(guān)鍵啟動讀內(nèi)存 MemtoReg 1b1; // 關(guān)鍵寫回?cái)?shù)據(jù)來自內(nèi)存 Branch 1b0; ALUOp 2b00; // ALU執(zhí)行加法算地址 end 6b101011: begin // sw RegWrite 1b0; // 不寫寄存器 ALUSrc 1b1; // 第二個操作數(shù)用立即數(shù) MemWrite 1b1; // 關(guān)鍵啟動寫內(nèi)存 MemRead 1b0; MemtoReg 1bX; // 不關(guān)心 Branch 1b0; ALUOp 2b00; // ALU執(zhí)行加法算地址 end // ... 其他指令如beq, addi等 ... default: begin // 處理未定義指令可將所有控制信號置為0或進(jìn)入異常 {RegDst, RegWrite, ALUSrc, MemWrite, MemRead, MemtoReg, Branch, ALUOp} 10b0; end endcase end endmodule這個控制單元清晰地展示了指令如何“翻譯”成控制信號。對于lw和swALUOp都是00指示加法ALUSrc都是1使用立即數(shù)這使得 ALU 執(zhí)行相同的地址計(jì)算操作。而復(fù)用的“分流”工作則由MemWrite/MemRead和MemtoReg來完成。4. 常見問題與調(diào)試當(dāng)硬件復(fù)用出錯時理解了原理但在實(shí)現(xiàn)中硬件復(fù)用相關(guān)的錯誤非常普遍。下面列出幾個典型問題及其排查思路。4.1 問題一lw指令讀回的數(shù)據(jù)錯誤現(xiàn)象仿真時lw指令執(zhí)行后目標(biāo)寄存器中的值不是預(yù)期內(nèi)存地址中的數(shù)據(jù)可能是零、ALU計(jì)算結(jié)果或其他隨機(jī)值。排查步驟檢查MemRead信號在lw指令執(zhí)行周期用波形圖查看MemRead是否被置為1。如果為0內(nèi)存模塊可能不會驅(qū)動數(shù)據(jù)總線導(dǎo)致讀回?cái)?shù)據(jù)為高阻態(tài)在仿真中可能顯示為0或X。檢查內(nèi)存地址查看dmem.addr輸入的值是否正確。它應(yīng)該等于$rs sign_extend(offset)。如果不正確檢查ALUSrc信號和符號擴(kuò)展模塊。檢查MemtoReg(WBsel) 信號在寫回階段MemtoReg必須為1才能將內(nèi)存輸出選通到寄存器堆的寫數(shù)據(jù)端口。如果它為0寫回的將是 ALU 結(jié)果即內(nèi)存地址本身。檢查數(shù)據(jù)存儲器初始化確認(rèn)你測試的內(nèi)存地址區(qū)域已正確初始化了數(shù)據(jù)。在仿真中內(nèi)存初始內(nèi)容可能全為0。4.2 問題二sw指令未能寫入內(nèi)存現(xiàn)象執(zhí)行sw指令后查看目標(biāo)內(nèi)存地址數(shù)據(jù)未更新。排查步驟檢查MemWrite信號這是最可能的原因。在sw指令執(zhí)行周期MemWrite必須為1并且通常需要在時鐘上升沿有效。在波形圖中確認(rèn)其時序。檢查寫入地址和數(shù)據(jù)確認(rèn)dmem.addr來自 ALU和dmem.write_data來自$rt的值是否正確。檢查內(nèi)存模塊的寫時序你的dmem模塊是否在clk上升沿且MemWrite1時才執(zhí)行寫操作實(shí)現(xiàn)是否正確檢查寄存器堆的讀端口sw指令的$rt寄存器數(shù)據(jù)是通過read_data2端口讀出的確認(rèn)該連接正確。4.3 問題三R-type 指令結(jié)果錯誤地影響了內(nèi)存現(xiàn)象執(zhí)行add等指令時內(nèi)存中某個地址的數(shù)據(jù)意外被修改。排查步驟檢查MemWrite信號是否意外激活在 R-type 指令周期MemWrite必須為0。如果控制器邏輯有誤可能錯誤地將其置1。檢查 ALU 輸出地址是否越界雖然MemWrite0但如果 ALU 計(jì)算結(jié)果恰好是一個合法的內(nèi)存地址而內(nèi)存模塊對地址譯碼是始終有效的那么當(dāng)MemWrite因毛刺或競爭冒險變?yōu)?時就可能發(fā)生意外寫入。確保MemWrite信號干凈穩(wěn)定。這是硬件復(fù)用帶來的潛在風(fēng)險因?yàn)?ALU 輸出始終連著內(nèi)存地址線任何對內(nèi)存的誤操作都源于控制信號MemWrite/MemRead的失效。在更復(fù)雜的設(shè)計(jì)中需要加入地址范圍檢查或內(nèi)存保護(hù)單元。4.4 問題四綜合后電路行為與仿真不一致現(xiàn)象RTL 仿真完全正確但燒錄到 FPGA 或 ASIC 后CPU 行為異常。排查思路時鐘與復(fù)位確保實(shí)際硬件的時鐘和復(fù)位信號干凈、無毛刺。單周期 CPU 對時鐘質(zhì)量要求高。未初始化的寄存器在硬件上電時寄存器、內(nèi)存內(nèi)容未知。確保你的設(shè)計(jì)有可靠的復(fù)位電路將所有狀態(tài)單元PC、寄存器堆等初始化為確定值。這與“按鍵功能復(fù)用兼顧硬件復(fù)位電路”的思想一致一個可靠的復(fù)位電路是復(fù)雜數(shù)字系統(tǒng)包括復(fù)用邏輯正確啟動的基礎(chǔ)。關(guān)鍵路徑與時序違例單周期 CPU 在一個時鐘周期內(nèi)完成所有操作取指、譯碼、執(zhí)行、訪存、寫回。如果組合邏輯路徑太長例如從指令讀出到寄存器寫回經(jīng)過的級數(shù)太多可能導(dǎo)致建立時間違例。需要使用靜態(tài)時序分析STA工具檢查并考慮插入寄存器進(jìn)行流水線化??刂菩盘柕纳蛇壿嬤^于復(fù)雜如果控制單元的組合邏輯延遲很大它產(chǎn)生的MemWrite、MemtoReg等信號可能會比其他數(shù)據(jù)路徑信號晚到導(dǎo)致一個周期內(nèi)不同部件動作不同步??梢試L試將控制信號寄存器化流水線寄存器但這會引入控制冒險是流水線 CPU 要解決的問題。5. 最佳實(shí)踐與擴(kuò)展方向理解了單周期 CPU 中基礎(chǔ)的硬件復(fù)用后你可以將其思想應(yīng)用到更復(fù)雜的設(shè)計(jì)中并遵循以下實(shí)踐。5.1 設(shè)計(jì)最佳實(shí)踐清晰的模塊劃分與信號命名像本文一樣將數(shù)據(jù)通路與控制通路分離??刂菩盘柮麘?yīng)體現(xiàn)其功能如MemtoReg比WBsel_0更清晰。為所有控制信號設(shè)置安全默認(rèn)值在控制單元的case語句或if-else鏈之外為所有輸出信號賦默認(rèn)值通常是0或無效狀態(tài)。這可以避免綜合出鎖存器并確保未定義指令不會導(dǎo)致系統(tǒng)崩潰。編寫全面的測試程序不要只測試一條指令。編寫一個包含lw、sw、R-type、分支指令的混合測試程序驗(yàn)證數(shù)據(jù)通路在所有復(fù)用場景下都能正確協(xié)作。特別要測試邊界情況如訪問內(nèi)存地址0。波形圖調(diào)試是必備技能熟練使用仿真工具的波形視圖同時觀察指令、數(shù)據(jù)、地址和控制信號的變化。將關(guān)鍵信號如opcode,alu_result,MemWrite,MemRead,MemtoReg, 寄存器寫地址和寫數(shù)據(jù)添加到波形中。5.2 擴(kuò)展方向從單周期到流水線單周期 CPU 是理解硬件復(fù)用的絕佳模型但效率低下。現(xiàn)代 CPU 采用流水線技術(shù)而這讓硬件復(fù)用與沖突處理變得更加復(fù)雜。結(jié)構(gòu)冒險如果指令和數(shù)據(jù)共用同一個存儲器那么在流水線的取指階段和訪存階段可能同時需要訪問它這就是結(jié)構(gòu)冒險。解決方案是使用分離的指令緩存I-Cache和數(shù)據(jù)緩存D-Cache。這可以看作是一種“資源復(fù)制”而非“復(fù)用”但根源是為了解決復(fù)用沖突。數(shù)據(jù)冒險一條指令需要用到前一條指令的計(jì)算結(jié)果例如add $1, $2, $3后面緊跟著lw $4, 0($1)。在流水線中add的結(jié)果在寫回階段才寫回$1但lw在譯碼階段就需要讀$1來計(jì)算地址。這導(dǎo)致了“先寫后讀”RAW冒險。解決方案包括數(shù)據(jù)前遞和流水線停頓。數(shù)據(jù)前遞是更高級的“硬件復(fù)用”思想它復(fù)用尚未寫回但已存在于流水線中間階段的數(shù)據(jù)直接旁路給需要它的后續(xù)指令??刂泼半U分支指令如beq的結(jié)果在流水線較晚階段才確定但處理器需要提前知道下一條指令是什么。這會導(dǎo)致流水線清空帶來性能損失。解決方案包括分支預(yù)測、延遲槽等。這涉及到對程序計(jì)數(shù)器PC來源的“復(fù)用”選擇是 PC4還是分支目標(biāo)地址進(jìn)行預(yù)測和修正。從單周期到流水線硬件復(fù)用的層次從“部件功能復(fù)用”上升到了“數(shù)據(jù)路徑和時間的復(fù)用與沖突管理”。理解單周期中WBsel和MemRM的協(xié)作是邁向這些更復(fù)雜概念的第一步。當(dāng)你開始設(shè)計(jì)流水線 CPU并需要處理數(shù)據(jù)前遞、冒險檢測等模塊時你會更加深刻地體會到計(jì)算機(jī)體系結(jié)構(gòu)設(shè)計(jì)的藝術(shù)很大程度上就是在高效復(fù)用與解決復(fù)用帶來的沖突之間尋找平衡。