系列文章 : [gem5] 從零開始的 gem5 學習筆記
在 fetchLine 的時候,會把 FetchRequest 的 state 改為 FetchRequest::InTranslation
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L188
並且將Fetch1Request push 進 requests queue
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L192C5-L192C28
再來會發一個 MMU 的 request,以便取得正確的位址
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L197
然後會進入 arch specific code,這邊以 RISC-V 為例子
會進入 gem5::RiscvISA::TLB::translateTiming
https://github.com/gem5/gem5/blob/v25.1.0.0/src/arch/riscv/tlb.cc#L622
假如 translate 完成後,會呼叫 translation->finish 這個 callback function
https://github.com/gem5/gem5/blob/v25.1.0.0/src/arch/riscv/tlb.cc#L629
finish 這個 callback function 來自 BaseMMU::TranslationFetchRequest 會繼承 BaseMMU::Translation
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.hh#L106-L108
https://github.com/gem5/gem5/blob/v25.1.0.0/src/arch/generic/mmu.hh#L58-L85
並且 FetchRequest 會 override 這個 callback function
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L240
MMU 結束後會呼叫 Fetch1::handleTLBResponse
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L253
在 Fetch1::handleTLBResponse 裡面,會將 FetchRequest 的 state 改為 FetchRequest::Translated,表示這個 Request 已經經過 MMU 的 translate 了。
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L271
接下來會 icachePort.sendTimingReq,會把 Packet 送出去給外部的裝置。
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L335
假如外部裝置可以接收這個 Packet,則會 return true。
會將 FetchReqeust 的 state 改為 FetchRequest::RequestIssuing,代表這個 Request 已經 Issue 到 bus 上了,等待 bus 回傳的結果!
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L340
假如外部裝置沒辦法接收這個 Packet,則會 return false。 minor CPU 需要等待外部裝置可以接受 Packet 的時候,外部裝置會呼叫 sendRetryReq,觸發 minor CPU 的 recvReqRetry,並重新 icachePort.sendTimingReq。
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L464
只要成功的將這個 Request 送到 Bus 上,就會呼叫 moveFromRequestsToTransfers,把 requests queue 的 Request 交給 transfers queue。
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L327
最後我們就等待外部的裝置呼叫 sendTimingResp,將 memory request 回送給 minor CPU,並觸發 minor CPU 的 recvTimingResp。
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L417
因為 minor CPU 的 recvTimingResp 設計為永遠 return true,表示永遠都可以接收 Resp,不會有失敗的情況。
當我們收到來自外部裝置的回應之後,我們可以把 FetchRequest 的 state 標示為 FetchRequest::Complete。表示漫長的 memory request 之旅終於結束了。
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L432
整理一下 FetchRequest 的五種狀態
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.hh#L117
FetchRequest 會依序走過這五種狀態。整理一下 Source Device ( 也就是 minor CPU ) 的 Port 會呼叫哪些 function
sendRetryReq,通知 minor CPU 可以再次呼叫 icachePort.sendTimingReq。icachePort.sendTimingReq return false,表示外部裝置在忙碌中。外部裝置會主動呼叫 sendRetryReq,最後會呼叫 icachePort.recvReqRetry,這時候我們可以再送一次 icachePort.sendTimingReq。icachePort.recvTimingResp 永遠都會 return true,所以就沒有實作 icachePort.sendRetryResp。Fetch1 的 FetchRequestPtr 有兩個 Queue
InTranslation, Translated 的 requestsRequestIssuing, Complete 的 requests最後 Fetch1 想要拿資料的話,就會從 transfers 裡面拿已經確定 Complete 的 Request 裡的資料
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L671
https://github.com/gem5/gem5/blob/v25.1.0.0/src/cpu/minor/fetch1.cc#L688