Skip to main content Link Menu Expand (external link) Document Search Copy Copied

RISC-V Pipelined Processor Hazard Unit

Circuits Wed Dec 4th by 11:59pm in your Project07 GitHub repo

There is no interactive grading for Project07

Deliverables

  1. For this project you will extend a basic pipeline processor implementation to include a Hazard Unit with additional data paths, MUXes, and control lines so that normal RISC-V programs can execute properly without the need to insert nop instructions (addi zero, zero, zero) to deal with data and control hazards. The given implementation is a 5-stage pipeline processor that includes pipeline registers between each stage. This processor can properly execute code that includes enough nop instructions inserted between instructions so that registers can be updated in the Write Back (WB) stage before they are read from the Decode RegFile (DR) stage by the next instruction. In addition, using nops allow jumps to update the PC so that subseqent instuctions are not started before the updated PC is known.

  2. You will evolve the given implementation to include data path additions, MUXes, control lines and a Hazard Unit, which provides support for register forwarding for data dependencies, stalling for memory reads, and flushing for jumps and branches. Your ultimate goal is to remove the need for nop instructions to properly execute code and to allow the pipeline to run at the fastest rate possible.

  3. You will commit the entire implementation of your pipelined processor, including the given circuits and ROMs, to your assignment repo. Your top-level processor must be named project07.dig.

Requirements

For this project you will evolve the given processor design to include data path additions and a Hazard Unit. The Hazard Unit gives the processor the ability to automatically handle the hazard conditions described in the following test cases.

00-add-3nop.s

This test should pass on the starter pipeline so that you can see how nop instructions allow code to execute properly without the need for a Hazard Unit.

01-add-2nop.s

As we will discuss in class, a simple modification to the DR stage can remove the need for one nop, that is only two nop instructions instead of three between useful instructions. All you need to do is invert the CLK signle input to the RegFile. This allows the WB stage to update the the destination register on the first half of the clock cycle so that the instruction in the DR stage can read it on the second half of the clock cycle.

02-jal.s

This shows an example of jal and should pass once you invert the clock to the RegFile in the DR stage. You will notice that four nop instructions are needed after jal to get it to function properly.

03-ld.s

This show an example of using sd and ld. This should also pass after you invert the clock to the RegFile.

04-add-fwd.s

main:
    li a1, 3
    li a2, 4
    add a0, a1, a2   # a0 should be 7
    unimp            # marker instruction

This program illustrates a data hazard, since a0 depends on the Writeback (WB) stage of the two immediate-form li (addi) instructions. Your Hazard Unit will enable register forwarding so that the values of a1 and a2 are available when the add instruction begins the Execute (EX) stage.

This test requires the implementation of forwarding from the MEM and WB stages to the EX stage if a instructions in these stages are going to write to RD0 or RD1. Here is is an outline of what is needed:

  • New datapath lines that connect ALUR_3 and the MR_4 MUX output to two new MUXex in the EX stage.
  • There will be two EX MUXes. One for RD0 and one for RD1.
    • That is the RD0 from the DR/EX registers will go to the MUX and the output of the MUX will go to all the inputs where RD0 was original connected. Same for RD1.
  • The RD0 MUX will have three inputs: RD0, ALUR_3, and MR_4 and the selector is called FRD0.
  • The RD1 MUX will have three inputs: RD1, ALUR_3, and MR_4 and the seledtor is called FRD1.
  • The logic in the Hazard Unit for for FRD0, looks like this:
    if ((RR0_2 == WR_3) && (RFW_3)) {
        FRD0 = 2;
    } else if ((RR0_2 == WR_4) && (RFW_4)) {
        FRD0 = 1;
    } else {
        FRD0 = 0;
    }
    

Notice that that this give priority to the closest instruction to the current instruction in the EX stage. Consider this example:

foo:
    addi a0, zero, 3
    addi a0, zero, 4
    add a0, a0, a0

In this case the hazard unit should ensure that 4 is forward to the EX stage of the add insruction.

05-ld-stl.s

main:
    li a0, 0
    li a1, 4
    sd a1, (a0)
    ld a2, (a0)
    addi a0, a2, 1      # a0 should be 5
    unimp               # marker instruction

This program illustrates the need to Flush the EX/MEM registers and Stall the pipeline, since the addi instruction depends on the value loaded by the ld instruction. Your Hazard Unit will enable a Stall in the appropriate Pipeline Registers.

Here is an outline of the implementation:

  • We need to be able to flush the EX/MEM register so that we don’t propogate the instruction in the EX stage. Essentially we need to insert a NOP. To do this, we can just set the CLR input to the EX/MEM registers to 1.
  • We need to stall all the instructions in EX, DR, and IF:
    • We just need to disable (set enable to 0) on the DR/EX registers, IF/DR registers, and the PC.
  • Here is the logic we need in the Hazard Unit:
    if ((RFW_3 == 1) && (MLD_3 == 1) && ((RR0_2 == WR_3) || (RR1_2 == WR_3))) {
        PC_EN = 0;
        IF_DR_EN = 0;
        DR_EX_EN = 0;
        EX_MEM_CLR = 1;
    } else {
        PC_EN = EN_ORG;
        IF_DR_EN = 1;
        DR_EX_EN = 1;
        EX_MEM_CLR = CLR_ORG;
    }
    

Note that your Hazard Unit should preserve the original EN and CLR lines to the pipeline registers. That is, EN and CLR should still work as expected. This will also be useful for debugging the tests manually.

06-jal-fls.s

main:
    li a0, 3
    jal foo
    unimp               # marker instruction
foo:
    addi a0, a0, 4      # a0 should be 7
    ret

This program illustrates a Control Hazard. Since the jal instruction means that subsequent instructions (the marker) should not be executed, we need to update the PC in the EX stage and flush the pipeline upto EX.

Here is an outline of the implementation:

  • The second input to the PCBr MUX should come from the ALU Result in the EX stage (not from the MR_4 MUX).
  • The PCBr MUX selector should come from PCbr_2, not PCbr_4.
  • The Hazard Units need the following logic to Flush IF/DR and DR/EX:
    if (PCbr_2 == 1) {
       IF_EX_CLR = 1;
       EX_DR_CLR = 1;
    } else {
       IF_EX_CLR = CLR_ORG;
       EX_DR_CLR = CLR_ORG;
    }
    

07-branch.s

This is a simple conditional branch test. If you implement the flush logic for the 06-jal-fls.s correctly, this test should pass.

08-fibrec.s

This is the only “full program” that computes fibrec(10), which is 55. This should work if you pass all the previous tests.

Given

  1. You may use any of the circuits shown in lecture, including the pipeline registers and disassembly circuit.

  2. The project07 starter circuits includes a simplified pipelined processor including:
    1. Support for RAM including ld and sd
    2. An implementation of the ASCII-based disassembler, including the decoder which outputs the inum to match the disassembler’s ROM.
    3. Instruction memory, including assembly source and hex for the tests described above.
  3. You may use any of Digital’s built-in components, or your own if you prefer.

Rubric

  • 10 pts: passes 00-add-3nop, 01-add-2nop, 02-jal, 03-ld test cases
  • 50 pts: passes the 04-add-fwd test case
  • 20 pts: passes the 05-ld-stl test case
  • 10 pts: passes the 06-jal-fls test case
  • 5 pts: passes the 07-branch test case
  • 5 pts: passes the 08-fibrec test case

Extra Credit

  • (10 points) Get all the Project06 tests to run on your Project07 pipelined processor.