Scoreboard in Rocket Core
Today we talk about the Scoreboard in Rocket Core. In fact, the Score Board in Rocke Core is very simple: 32 bit to record the status of each register. The class Scoreboard defined a class of this simple score board and the two instance is
sboard for normal registers and
fp_sboard for float point registers.
How does it work?
The class Scoreboard is a little bit convoluted. In fact, you could understand it as a array of bit, with a size of 32. Each bit stands for one register. For example, the
sboard.set(True, 5) will set the 5th bit to “busy”. Similarly,
sboard.clear(True, 5) will set the 5th bit to “not busy”.
sboard.read(5) will return whether the 5th register is busy or not. The function
readBypassed(rd) seems to return the result of next cycle. But not used in current version.
When to update the scoreboard?
To discuss when to update the scoreboard, we should know the two types of the “write into the registers”:
A) In general pipeline, (let’s say
add), when the instrucion come into the write back stage, the result of the
add is ready for the writing. So the value be written to the register in the write back stage. In this senario, the score board will not be used.
B) Another type of “write into registers” is, the “ll” in the code (which means “long lantency”). The “ll” write includes:
- Multiplier instructions
- Memory instructions and cache miss
- ROCC instructions
In the pipeline of these instrucions, the value cannot get ready before the writeback stage. Consequently, the register should be marked as “busy” to avoid hazards. Here, we need to use scoreboard. You can see the logic from these code:
val wb_set_sboard = wb_ctrl.div || wb_dcache_miss || wb_ctrl.rocc ... sboard.set(wb_set_sboard && wb_wen, wb_waddr)
See? if the instruction is div/cache miss/rocc, and writeback is enabled, the
sboard is updated.
When to clear it? See
sboard.clear(ll_wen, ll_waddr). Here, the “ll” include the three cases above. You can read the writeback stage to find it out.
When to read the scoreboard?
Now, we have figured out how the scoreboard various. But where do we use it? This is quite simple. The only usage of
val id_sboard_hazard = checkHazards(hazard_targets, rd => sboard.read(rd) && !id_sboard_clear_bypass(rd))
checkHazards to check the possible hazards. The
hazard_target is a seq of registers used (rx1/rx2/rd). And the express after the comma is to check whether the sboard of the register is “not busy” (in the next cycle, so need
id_sboard_hazard will eventually lead to
ctrl_stalld and the pipeline will stall.
So far, we finished the analysis of scoreboard. As for the scoreboard of float point, I didn’t focus on it, but it should be similar.