Menu Close

RISC-V 总线和流水线(3)流水线介绍

1.流水线简介

 

相关参考文章:

RISC-V教学教案

 

在介绍流水线之前,先简介一下状态机(Finite-State Machine,FSM)。状态机CPU具有一组状态,以及一个将输入符号和当前状态映射到下一个状态的转换函数。 每次CPU仅执行一种状态,然后循环重复。

FII RISC-V有状态机版本(v2.01,v2.02),相对于5级经典状态(取指,译码,执行,访存,回写)的CPU而言,FII CPU只有三级状态,将其中的四级状态两两合并,最后的三级状态分别是取指,译码和执行,访存和回写。状态相关代码模块如下所示(更多的细节可以点击这里)。

`DBG_INFO reg [ 2: 0 ] instr_st = 0;

reg [ 2: 0 ] instr_st_nxt = 0;



always@( posedge sys_clk )
if (( rst_n == 1'b0 ) | i_cpu_reset )     instr_st <= IDLE;
else    instr_st <= instr_st_nxt;

always @ ( * )
begin
    case ( instr_st )
    //IDLE是FPGA板处于上电复位时的状态
    //正常的执行状态是fetch,execution,和write back.
    //每个时钟周期仅执行一个状态,一个完整的循环至少需要3个时钟周期
    //如果有长周期指令,执行时间会更长
    IDLE:   // 0
    begin
    
        if(!i_cpu_reset)
            instr_st_nxt = I_FCH;
        else
            instr_st_nxt = IDLE;
            
    end
    I_FCH:   // 1,取指
    begin
    
        if(i_cpu_reset) instr_st_nxt = IDLE;
        else instr_st_nxt = I_EXE;
        
    end
    I_EXE:   // 2 译码和执行
    begin
    
        if ( i_ls_need )
        begin
        
            if ( ls_rib_ok )
                instr_st_nxt = I_WB;
            else
                instr_st_nxt = I_EXE;
                
        end
        else 
            instr_st_nxt = I_WB;
            
    end
    I_WB:   // 3 访存和回写
    begin
    
        instr_st_nxt = I_FCH;
        
    end
    default : instr_st_nxt = IDLE;
    endcase
end

 

 

2.流水线指令执行示例

这里有一个汇编示例文件,如图1所示。

%title插图%num

图1 汇编示例

 

%title插图%num

图2 状态机在时钟周期下的相应状态

 

图2中的数字表示时钟周期,不同的指令状态用不同的颜色绘制。 它显示了对于状态机CPU:

  • 时钟周期1:FCH,取指令,ADDI
  • 时钟周期2:EXE,执行ADDI
  • 时钟周期3:WB,将X0 + 0的结果写入a5
  • 时钟周期4:FCH,取指令,ADDI
  • 时钟周期5:EXE,执行ADDI
  • 时钟周期6:WB,将X0 + 0的结果写入s0

对于相同的汇编示例代码,流水线执行的方式有所不同,3级流水线的示例参见图3。

%title插图%num

图3 相同时钟周期中流水线状态与状态机状态的比较

 

对于流水线:

  • 时钟周期1:FCH,取指令,ADDI
  • 时钟周期2:EXE & FCH,执行ADDI& 获取指令ADDI
  • 时钟周期3: WB & EXE & FCH,将X0 + 0的结果写入a5 & 执行ADDI &获取指令SB
  • 时钟周期4:FCH & WB & EXE,获取指令ADDI& 将X0 +0的结果写入s0 & 执行SB

 

尽管对于每条指令(如2个ADDI和SB),它们仍需要3个时钟周期才能完成,但是在同一时钟周期下,3条指令将被同时执行。除了时钟周期1和2,流水线没有被完全填充,因此执行效率不高,其他时钟周期都同时执行3个指令。对于从时钟周期1到时钟周期12的相同时间段,状态机执行4条指令,而流水线至少执行10条指令。当时钟速度相同时,流水线CPU的效率绝对高于状态机CPU。

计算机体系结构中的流水线也被称为数据流水线。它将一个重复的流程分解为几个子流程,每个子流程与其他子流程并行运行。由于此工作方法与工厂中的生产流水线非常相似,因此称为流水线技术,即同时执行多个子流程。

经典的5级流水线包括:

  • 取指令(fetch instruction)
  • 指令解码器(instruction decoder)
  • 执行(execution)
  • 存储器访问(memory access)
  • 回写(writeback)。

FII RISC-V将指令解码和执行,存储器访问和回写结合在一起,形成3级流水线:

  • 取指令(FCH)
  • 执行(EXE)
  • 回写(WB)。

 

3.流水线分类

图4显示了3级流水线。根据执行顺序,可以将流水线分为顺序流水线乱序流水线。如果流水线具有反馈,则将其定义为非线性流水线。与之相反,如果流水线中的数据从第一级流到最后一级,则它是线性流水线。流水线有不同的阶段,多至31个阶段(hyper pipelined technology,超级流水线技术)。开发和使用不同的流水线CPU是因为在相同的生产过程和相同的时钟下,流水线CPU指令执行的效率和主频得到了极大的提高。

%title插图%num

图4 RISCV 3级流水线

 

4.流水线冲突

流水线CPU也为高性能付出了代价,例如,它的逻辑一般比状态机逻辑更复杂。 此外,流水线CPU主要会产生三种冲突:数据冲突结构冲突控制冲突

  • 数据冲突

当流水线不同阶段的指令表现出数据依赖性时,就会发生数据危险。 例如,在图5中,指令2依赖于于指令1,s0既是指令1的结果,也是指令2中的加数。当指令1将结果回写到寄存器时,指令2使用了未更新的错误s0值执行。解决方案是bypass该值,这意味着直接在回写之前,将指令1结果中的s0值传递给指令2。

%title插图%num

图5 数据冲突

 

  • 结构冲突

当流水线中的两个或更多指令需要相同资源时,就会发生结构冲突。 例如,当从存储块中提取指令时,与此同时,另一条指令正在写回到存储块中。 解决方案是在后面的指令前添加流水线气泡(nop,无操作),或增加可用硬件资源。

%title插图%num

图6 结构冲突

 

  • 控制冲突

当流水线对分支预测做出错误决定时会发生控制冲突,因此必须丢弃已引入流水线的指令。 例如,在图7中,当执行j loop时,紧随其后的指令已被取出。 但是,PC(Program Counter,程序计数器)将跳至loop标签处,而不是指向已获取的指令。 在这种情况下,流水线将以nop(无操作)的形式执行已经获取的指令。

%title插图%num

图7 控制冲突

Posted in FPGA, RISC-V, RISC-V, RISC-V 教案, 应用开发, 开发板, 教材与教案, 文章

发表评论

相关链接