Sequence reordering to resolve data hazards in RISC-V assembly

Viewed 405

For the following sequence of RISC-V code, I am trying to identify the data hazards that cannot be resolved by data forwarding. Is it possible to overcome the hazards by reordering the code sequence? If yes, can anyone show the new sequence?

Here is my code:

loop: slli  s2, s1, 2
      add   s3, s2, s0
      lw    t0, 0(s3)
      add   t1, t2, t0
      sw    t1, 20(s3)
      addi  s1, s1, 1
      beq   s1, s5, loop
1 Answers

Which data hazards can be resolved by forwarding is entirely dependent on the particular implementation of RISC-V architecture that you're using. I'll assume the traditional 5-stage RISC-V pipeline with forwarding presented in the Patterson & Hennessey textbooks, and take a stab at your question.

This pipeline has stages instruction fetch (IF), instruction decode (ID), execute (EX), memory (MEM), and writeback (WB). The execute stage computes values for register-register and register-immediate operations and computes addresses for memory (lw/sw) and control transfer (branch/jump) operations, and the memory stage reads data for lw and writes data for sw. Data could be forwarded from the end of the execute, memory, or writeback stages to the beginning of a previous stage for a subsequent instruction.

In the code snippet you included, there would be 5 data hazards:

(1) slli s2, s1, 2 and add s3, s2, s0, for register s2

Here, register s2 is written by slli and read by add. The new value is computed by the end of the EX stage of the first instruction and needed by the beginning of the EX stage of the next instruction, so it can be resolved with forwarding.

(2) add s3, s2, s0 and lw t0, 0(s3) for register s3

Here, register s3 is written by add and read by lw. The new value is computed by the end of the EX stage of the first instruction and needed by the beginning of the EX stage of the next instruction, so it can be resolved with forwarding.

(3) lw t0, 0(s3) and add t1, t2, t0 for register t0

Here, register t0 is written by lw and read by add. The new value is computed by the end of the MEM stage of the first instruction and needed by the beginning of the EX stage of the next instruction, so it canNOT be resolved with forwarding.

(4) add t1, t2, t0 and sw t1, 20(s3) for register t1

Here, register t1 is written by add and read by sw. The new value is computed by the end of the EX stage of the first instruction and needed by the beginning of the MEM stage of the next instruction, so it can be resolved with forwarding.

(5) addi s1, s1, 1 and beq s1, s5, loop for register s1

Here, register s1 is written by addi and read by beq. The new value is computed by the end of the EX stage of the first instruction. Usually for RISC-V pipelines without any optimizations for control hazards, for branch instructions, registers are compared during EX in parallel with the computation of program counter + offset to get the branch destination. The control hazard here is a separate issue, but the data hazard is resolvable by forwarding.

So of the 5 hazards, only one is not resolvable by data forwarding. Can it be resolved by instruction reordering? Yes. Take a look at addi s1, s1, 1. Before the addi, s1 is not read or written by any instruction after the first slli. If we move that instruction, so the resulting code looks like this:

loop: slli  s2, s1, 2
      add   s3, s2, s0
      lw    t0, 0(s3)
      addi  s1, s1, 1
      add   t1, t2, t0
      sw    t1, 20(s3)
      beq   s1, s5, loop

This way, the lw instruction that retrieves the data to be written into t0 will have completed the MEM stage by the time the new value of t0 is needed by the add t1, t2, t0 instruction.

With this reordering, all data hazards could be resolved with forwarding, and no stalls would be necessary.

Related