查看: 1544|回复: 0
收起左侧

E203数据冲突处理OITF

[复制链接]

  离线 

  • TA的每日心情
    奋斗
    2021-3-3 12:32
  • 签到天数: 10 天

    [LV.3]

    发表于 2021-3-6 16:02:39 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 皋陶 于 2021-3-6 16:04 编辑

    流水线的数据冲突分为三类:WAR,RAW,WAW

    参考链接:3.3 流水线相关冲突及解决办法_v3.0 https://wenku.baidu.com/view/e066926d48d7c1c708a14508.html

    • WAR: write after read 相关性,又称先读后写相关性。比如下面的指令序列,第一条指令会读取x4,第二条指令会写x4。在流水线中,如果第二条指令比第一条指令先写x4,则第一条指令就会读出错误的值。
               add x5, x4,x6
               add x4, x3, x2
    • WAW: write after write 相关性,又称先写后写相关性。比如下面的指令序列,两条指令都会写x5。在流水线中,如果第二条指令比第一条指令先写x5,就会引起逻辑错误。
               add x5, x4,x6
               add x5, x3, x2
    • RAW:read after write相关性,又称先写后读相关性。比如下面指令序列,如果第二条指令,在第一条指令写x5之前,第二条指令先读x4,就会引起逻辑错误。
               add x5, x4,x6
               add x4, x5, x2

          由于蜂鸟E200系列是按序派遣,按顺序写回的微架构,在指令派遣时候就已经从通用寄存器数组中读取了源操作数。后续执行的指令写回regfile的操作不可能影响到前面指令的读取,所以不可能发生WAR相关性造成的数据冲突。

          正在派遣的指令处在流水线的第二级,假设之前派遣的指令是单周期指令,则前序指令肯定已经完成了执行且将结果写回了Regfile。因此正在派遣的指令不可能会发生RAW数据冲突。但是假设之前派遣的指令是多周期指令(长指令),由于指令需要多个周期才能写回结果。因此正在派遣的指令可能会产生前序相关的RAW相关性。

         正在派遣的指令处在流水线的第二级,假设之前派遣的指令是单周期指令,则前序指令肯定已经完成了执行且将结果写回了Regfile。因此正在派遣的指令不可能会发生WAW数据冲突。但是假设之前派遣的指令是多周期指令(长指令),由于指令需要多个周期才能写回结果。因此正在派遣的指令可能会产生前序相关的WAW相关性。

        为了能检测出长指令的RAW和WAW相关性,蜂鸟E200使用了一个outstanding instruction track fifo(OITF)模块。在流水线的派遣(Dispatch)点,每一次派遣一个长指令,则会在OITF中分配一个表项(Entry),在这个表项中会存储该长指令的结果寄存器索引。在流水线的写回(Write-back)点,每次按顺序写回一个长指令之后,就会将此指令在OITF中的表项移除。

          每条指令派遣时,都会将本指令的源操作数和目的操作数寄存器索引和OITF中的各个表项进行比对,从而判断本指令是否与已经被派遣出,且尚未写回的长指令产生RAW和WAW相关性。如果产生相关性,则stall住当前指令的派遣。如果没有RAW和WAW相关性,且该指令为多周期长指令,把该指令写入OITF,如果OITF是full,则仍要stall住管线,等待OITF释放空间后,再写入并派遣。

       在writeback模块,会进行长指令写回仲裁,长指令写回regfile后,会释放OITF中相应的表项。

    国内芯片技术交流-E203数据冲突处理OITFrisc-v单片机中文社区(1)

    OITF代码如下,如果fifo full,则dis_ready=0, 与dispatch模块握手失败,不会发送新的dispatch进来。如果不为空,会发送新的指令进来进行判断。
    1. `include "e203_defines.v"

    2. module e203_exu_oitf (
    3.   output dis_ready,

    4.   input  dis_ena, //dispatch a long instruction enable signal
    5.   input  ret_ena, //write back a long instruction enable signal

    6.   output [`E203_ITAG_WIDTH-1:0] dis_ptr,  //write pointer
    7.   output [`E203_ITAG_WIDTH-1:0] ret_ptr,  //read pointer

    8.   output [`E203_RFIDX_WIDTH-1:0] ret_rdidx,
    9.   output ret_rdwen,
    10.   output ret_rdfpu,
    11.   output [`E203_PC_SIZE-1:0] ret_pc,

    12.   input  disp_i_rs1en, // enable if current dispatch instruction fetch first source operand  
    13.   input  disp_i_rs2en, // ...
    14.   input  disp_i_rs3en, // ...
    15.   input  disp_i_rdwen, // enable if current dispatch instruction write back to register
    16.   input  disp_i_rs1fpu, // enable if current dispath instruction need to read float gpr
    17.   input  disp_i_rs2fpu, //...
    18.   input  disp_i_rs3fpu, //...
    19.   input  disp_i_rdfpu,  //enable if current dipatch instruction need to write back to float register files.
    20.   //register index
    21.   input  [`E203_RFIDX_WIDTH-1:0] disp_i_rs1idx,
    22.   input  [`E203_RFIDX_WIDTH-1:0] disp_i_rs2idx,
    23.   input  [`E203_RFIDX_WIDTH-1:0] disp_i_rs3idx,
    24.   input  [`E203_RFIDX_WIDTH-1:0] disp_i_rdidx,
    25.   input  [`E203_PC_SIZE    -1:0] disp_i_pc, //pc of current dispatch instruciotn

    26.   output oitfrd_match_disprs1, //dispatch instruction rs1 is same as any item of result register in oitf
    27.   output oitfrd_match_disprs2, //...
    28.   output oitfrd_match_disprs3, //...
    29.   output oitfrd_match_disprd,  //dispatch instruction rd is same as any item of result register in oitf.
    30.   //if empty, no conflict
    31.   output oitf_empty,
    32.   input  clk,
    33.   input  rst_n
    34. );

    35.   wire [`E203_OITF_DEPTH-1:0] vld_set;
    36.   wire [`E203_OITF_DEPTH-1:0] vld_clr;
    37.   wire [`E203_OITF_DEPTH-1:0] vld_ena;
    38.   wire [`E203_OITF_DEPTH-1:0] vld_nxt;
    39.   wire [`E203_OITF_DEPTH-1:0] vld_r; //if it is valid signal in all item
    40.   wire [`E203_OITF_DEPTH-1:0] rdwen_r;// if it is write back register in all item
    41.   wire [`E203_OITF_DEPTH-1:0] rdfpu_r; //result register in all item if are float
    42.   wire [`E203_RFIDX_WIDTH-1:0] rdidx_r[`E203_OITF_DEPTH-1:0]; //register index in all items
    43.   // The PC here is to be used at wback stage to track out the
    44.   //  PC of exception of long-pipe instruction
    45.   wire [`E203_PC_SIZE-1:0] pc_r[`E203_OITF_DEPTH-1:0];

    46.   wire alc_ptr_ena = dis_ena;  //dispatch a long instruction enable signal, as write pointer enable signal
    47.   wire ret_ptr_ena = ret_ena;  //write back a long instruction enable signal, as read pointer enable signal

    48.   wire oitf_full ;

    49.   wire [`E203_ITAG_WIDTH-1:0] alc_ptr_r; //write pointer, long instruction dispatch
    50.   wire [`E203_ITAG_WIDTH-1:0] ret_ptr_r; //read pointer, long instruction write back

    51.   generate
    52.   if(`E203_OITF_DEPTH > 1) begin: depth_gt1//{
    53.       //extra mark bit for write full
    54.       wire alc_ptr_flg_r;
    55.       wire alc_ptr_flg_nxt = ~alc_ptr_flg_r;
    56.       wire alc_ptr_flg_ena = (alc_ptr_r == ($unsigned(`E203_OITF_DEPTH-1))) & alc_ptr_ena;

    57.       sirv_gnrl_dfflr #(1) alc_ptr_flg_dfflrs(alc_ptr_flg_ena, alc_ptr_flg_nxt, alc_ptr_flg_r, clk, rst_n);

    58.       wire [`E203_ITAG_WIDTH-1:0] alc_ptr_nxt;
    59.       //if write to fifo depth, write ptr = 0,otherwise write ptr = write ptr + 1
    60.       assign alc_ptr_nxt = alc_ptr_flg_ena ? `E203_ITAG_WIDTH'b0 : (alc_ptr_r + 1'b1);

    61.       sirv_gnrl_dfflr #(`E203_ITAG_WIDTH) alc_ptr_dfflrs(alc_ptr_ena, alc_ptr_nxt, alc_ptr_r, clk, rst_n);

    62.       //extra mark bit for read empty
    63.       wire ret_ptr_flg_r;
    64.       wire ret_ptr_flg_nxt = ~ret_ptr_flg_r;
    65.       wire ret_ptr_flg_ena = (ret_ptr_r == ($unsigned(`E203_OITF_DEPTH-1))) & ret_ptr_ena;

    66.       sirv_gnrl_dfflr #(1) ret_ptr_flg_dfflrs(ret_ptr_flg_ena, ret_ptr_flg_nxt, ret_ptr_flg_r, clk, rst_n);

    67.       wire [`E203_ITAG_WIDTH-1:0] ret_ptr_nxt;
    68.       //if read to fifo depth, read ptr = 0, otherwise read prt = read prt + 1
    69.       assign ret_ptr_nxt = ret_ptr_flg_ena ? `E203_ITAG_WIDTH'b0 : (ret_ptr_r + 1'b1);

    70.       sirv_gnrl_dfflr #(`E203_ITAG_WIDTH) ret_ptr_dfflrs(ret_ptr_ena, ret_ptr_nxt, ret_ptr_r, clk, rst_n);
    71.       //empty, full mark
    72.       assign oitf_empty = (ret_ptr_r == alc_ptr_r) &   (ret_ptr_flg_r == alc_ptr_flg_r);
    73.       assign oitf_full  = (ret_ptr_r == alc_ptr_r) & (~(ret_ptr_flg_r == alc_ptr_flg_r));
    74.   end//}
    75.   else begin: depth_eq1//}{
    76.       assign alc_ptr_r =1'b0;
    77.       assign ret_ptr_r =1'b0;
    78.       assign oitf_empty = ~vld_r[0];
    79.       assign oitf_full  = vld_r[0];
    80.   end//}
    81.   endgenerate//}

    82.   assign ret_ptr = ret_ptr_r;
    83.   assign dis_ptr = alc_ptr_r;

    84. ////
    85. //// // If the OITF is not full, or it is under retiring, then it is ready to accept new dispatch
    86. //// assign dis_ready = (~oitf_full) | ret_ena;
    87. // To cut down the loop between ALU write-back valid --> oitf_ret_ena --> oitf_ready ---> dispatch_ready --- > alu_i_valid
    88. //   we exclude the ret_ena from the ready signal
    89. assign dis_ready = (~oitf_full);

    90.   wire [`E203_OITF_DEPTH-1:0] rd_match_rs1idx;
    91.   wire [`E203_OITF_DEPTH-1:0] rd_match_rs2idx;
    92.   wire [`E203_OITF_DEPTH-1:0] rd_match_rs3idx;
    93.   wire [`E203_OITF_DEPTH-1:0] rd_match_rdidx;

    94.   genvar i;
    95.   generate //{
    96.       for (i=0; i<`E203_OITF_DEPTH; i=i+1) begin:oitf_entries//{
    97.         //every time, assign a item and write pointer same as current i, then
    98.         //valid set is high
    99.         assign vld_set[i] = alc_ptr_ena & (alc_ptr_r == i);
    100.         //every time, assign a item and read pointer same as current i, then
    101.         //valid clr is high
    102.         assign vld_clr[i] = ret_ptr_ena & (ret_ptr_r == i);
    103.         assign vld_ena[i] = vld_set[i] |   vld_clr[i];
    104.         assign vld_nxt[i] = vld_set[i] | (~vld_clr[i]);

    105.         sirv_gnrl_dfflr #(1) vld_dfflrs(vld_ena[i], vld_nxt[i], vld_r[i], clk, rst_n);
    106.         //Payload only set, no need to clear
    107.         sirv_gnrl_dffl #(`E203_RFIDX_WIDTH) rdidx_dfflrs(vld_set[i], disp_i_rdidx, rdidx_r[i], clk);
    108.         sirv_gnrl_dffl #(`E203_PC_SIZE    ) pc_dfflrs   (vld_set[i], disp_i_pc   , pc_r[i]   , clk);
    109.         sirv_gnrl_dffl #(1)                 rdwen_dfflrs(vld_set[i], disp_i_rdwen, rdwen_r[i], clk);
    110.         sirv_gnrl_dffl #(1)                 rdfpu_dfflrs(vld_set[i], disp_i_rdfpu, rdfpu_r[i], clk);
    111.         //compare dispatch source operand with result register in fifo
    112.         assign rd_match_rs1idx[i] = vld_r[i] & rdwen_r[i] & disp_i_rs1en & (rdfpu_r[i] == disp_i_rs1fpu) & (rdidx_r[i] == disp_i_rs1idx);
    113.         assign rd_match_rs2idx[i] = vld_r[i] & rdwen_r[i] & disp_i_rs2en & (rdfpu_r[i] == disp_i_rs2fpu) & (rdidx_r[i] == disp_i_rs2idx);
    114.         assign rd_match_rs3idx[i] = vld_r[i] & rdwen_r[i] & disp_i_rs3en & (rdfpu_r[i] == disp_i_rs3fpu) & (rdidx_r[i] == disp_i_rs3idx);
    115.         assign rd_match_rdidx [i] = vld_r[i] & rdwen_r[i] & disp_i_rdwen & (rdfpu_r[i] == disp_i_rdfpu ) & (rdidx_r[i] == disp_i_rdidx );

    116.       end//}
    117.   endgenerate//}
    118.   //rs1 in fifo, so RAW relative
    119.   assign oitfrd_match_disprs1 = |rd_match_rs1idx;
    120.   //rs2 in fifo, so RAW relative
    121.   assign oitfrd_match_disprs2 = |rd_match_rs2idx;
    122.   //rs3 in fifo, so RAW relative
    123.   assign oitfrd_match_disprs3 = |rd_match_rs3idx;
    124.   //rd in fifo, so WAW relative
    125.   assign oitfrd_match_disprd  = |rd_match_rdidx ;

    126.   assign ret_rdidx = rdidx_r[ret_ptr];
    127.   assign ret_pc    = pc_r [ret_ptr];
    128.   assign ret_rdwen = rdwen_r[ret_ptr];
    129.   assign ret_rdfpu = rdfpu_r[ret_ptr];

    130. endmodule
    复制代码




    上一篇:E203 CSR rtl实现分析
    下一篇:RV32FDQ/RV64RDQ指令集(1)
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-4-25 18:36 , Processed in 0.627776 second(s), 48 queries .

    快速回复 返回顶部 返回列表