openc910源码LSU系列之<66>


//==========================================================
//                Pass data to data entry
//==========================================================
//------------------judge r signal--------------------------
//----------r id------------------------
assign lfb_biu_r_id_hit     = biu_lsu_r_vld
                              &&  (biu_lsu_r_id[4:3] ==  BIU_LFB_ID_T);
assign lfb_biu_id_2to0[2:0] = biu_lsu_r_id[2:0];

assign lfb_addr_entry_resp_set[LFB_ADDR_ENTRY-1:0]  = 
                {
   LFB_ADDR_ENTRY{
   lfb_biu_r_id_hit && lfb_data_not_full}}
                & lfb_r_id_hit_addr_ptr[LFB_ADDR_ENTRY-1:0];
//----------r resp----------------------
// &Force("bus","biu_lsu_r_resp",3,0); @359
assign lfb_r_resp_share     = biu_lsu_r_resp[3];
assign lfb_r_resp_err       = (biu_lsu_r_resp[1:0] ==  DECERR)
                              ||  (biu_lsu_r_resp[1:0] ==  SLVERR);

//------------------create ptr------------------------------
// &CombBeg; @365
always @( lfb_data_entry_vld[1:0])
begin
lfb_data_create_ptr[LFB_DATA_ENTRY-1:0]   = {
   LFB_DATA_ENTRY{
   1'b0}};
casez(lfb_data_entry_vld[LFB_DATA_ENTRY-1:0])
  2'b?0:lfb_data_create_ptr[0]  = 1'b1;
  2'b01:lfb_data_create_ptr[1]  = 1'b1;
  default:lfb_data_create_ptr[LFB_DATA_ENTRY-1:0]   = {
   LFB_DATA_ENTRY{
   1'b0}};
endcase
// &CombEnd; @372
end
//------------------create signal---------------------------
//if no vld, or only one vld and full, then create
assign lfb_data_wait_surplus  = |lfb_data_entry_wait_surplus[LFB_DATA_ENTRY-1:0];


assign lfb_data_create_vld          = lfb_biu_r_id_hit
                                      &&  !lfb_data_wait_surplus;
assign lfb_data_create_dp_vld       = lfb_data_create_vld;
assign lfb_data_create_gateclk_en   = lfb_data_create_vld;

assign lfb_data_entry_create_vld[LFB_DATA_ENTRY-1:0]        = {
   LFB_DATA_ENTRY{
   lfb_data_create_vld}}
                                                              & lfb_data_create_ptr[LFB_DATA_ENTRY-1:0];

assign lfb_data_entry_create_dp_vld[LFB_DATA_ENTRY-1:0]     = {
   LFB_DATA_ENTRY{
   lfb_data_create_dp_vld}}
                                                              & lfb_data_create_ptr[LFB_DATA_ENTRY-1:0];

assign lfb_data_entry_create_gateclk_en[LFB_DATA_ENTRY-1:0] = {
   LFB_DATA_ENTRY{
   lfb_data_create_gateclk_en}}
                                                                & lfb_data_create_ptr[LFB_DATA_ENTRY-1:0];

//------------------first pass ptr--------------------------
// &CombBeg; @393
always @( lfb_biu_id_2to0[2:0])
begin
lfb_r_id_hit_addr_ptr[LFB_ADDR_ENTRY-1:0] = {
   LFB_ADDR_ENTRY{
   1'b0}};
case(lfb_biu_id_2to0[2:0])
  3'd0:lfb_r_id_hit_addr_ptr[0] = 1'b1;
  3'd1:lfb_r_id_hit_addr_ptr[1] = 1'b1;
  3'd2:lfb_r_id_hit_addr_ptr[2] = 1'b1;
  3'd3:lfb_r_id_hit_addr_ptr[3] = 1'b1;
  3'd4:lfb_r_id_hit_addr_ptr[4] = 1'b1;
  3'd5:lfb_r_id_hit_addr_ptr[5] = 1'b1;
  3'd6:lfb_r_id_hit_addr_ptr[6] = 1'b1;
  3'd7:lfb_r_id_hit_addr_ptr[7] = 1'b1;
  default:lfb_r_id_hit_addr_ptr[LFB_ADDR_ENTRY-1:0] = {
   LFB_ADDR_ENTRY{
   1'b0}};
endcase
// &CombEnd; @406
end

assign lfb_pass_addr_5to4[1:0]  = {
   2{
   lfb_r_id_hit_addr_ptr[0]}} & lfb_addr_entry_addr_tto4_0[1:0]
                                  | {
   2{
   lfb_r_id_hit_addr_ptr[1]}} & lfb_addr_entry_addr_tto4_1[1:0]
                                  | {
   2{
   lfb_r_id_hit_addr_ptr[2]}} & lfb_addr_entry_addr_tto4_2[1:0]
                                  | {
   2{
   lfb_r_id_hit_addr_ptr[3]}} & lfb_addr_entry_addr_tto4_3[1:0]
                                  | {
   2{
   lfb_r_id_hit_addr_ptr[4]}} & lfb_addr_entry_addr_tto4_4[1:0]
                                  | {
   2{
   lfb_r_id_hit_addr_ptr[5]}} & lfb_addr_entry_addr_tto4_5[1:0]
                                  | {
   2{
   lfb_r_id_hit_addr_ptr[6]}} & lfb_addr_entry_addr_tto4_6[1:0]
                                  | {
   2{
   lfb_r_id_hit_addr_ptr[7]}} & lfb_addr_entry_addr_tto4_7[1:0];

//lfb first pass ptr is used to assign data_entry pass_ptr
// &CombBeg; @418
always @( lfb_pass_addr_5to4[1:0])
begin
lfb_first_pass_ptr[3:0]  = 4'b0;
case(lfb_pass_addr_5to4[1:0])
  2'd0:lfb_first_pass_ptr[0]  = 1'b1;
  2'd1:lfb_first_pass_ptr[1]  = 1'b1;
  2'd2:lfb_first_pass_ptr[2]  = 1'b1;
  2'd3:lfb_first_pass_ptr[3]  = 1'b1;
  default:lfb_first_pass_ptr[3:0]  = 4'b0;
endcase
// &CombEnd; @427
end

这部分代码主要处理从BIU(Bus Interface Unit)接收的数据,并将其传递给加载填充缓冲区(Load Fill Buffer, LFB)的数据条目。关键部分包括:

  1. 处理BIU返回的响应信号(Judging BIU Response Signal)

    • lfb_biu_r_id_hit:检测BIU返回的ID是否与LFB期望的ID匹配。
    • lfb_biu_id_2to0:获取BIU返回数据的ID的低3位。
  2. 生成数据创建指针(Generate Data Creation Pointer)

    • lfb_data_create_ptr:根据LFB数据条目的有效性,生成一个指向创建位置的指针。
  3. 创建数据条目信号(Create Data Entry Signal)

    • lfb_data_create_vldlfb_data_create_dp_vldlfb_data_create_gateclk_en:基于BIU的响应和LFB的状态生成数据条目的创建信号。
  4. 传递地址到数据条目(Pass Address to Data Entry)

    • lfb_pass_addr_5to4:从地址条目传递地址到数据条目。
    • lfb_first_pass_ptr:根据传递的地址生成第一次传递指针。
  5. 处理BIU返回的数据

    • 判断BIU的返回数据是否有错误(如DECERR或SLVERR)。
    • 根据BIU返回的ID和响应,更新LFB的相应地址条目。
  6. 更新LFB状态

    • 根据BIU的响应和LFB内部逻辑,更新LFB的状态,如是否有额外的等待(lfb_data_wait_surplus)。

总体而言,这部分代码负责处理从BIU返回的数据,并将其正确地安置在LFB的数据条目中,以保证数据缓存的一致性和处理器对内存的有效访问。


//==========================================================
//                Linefill state machine
//==========================================================
//----------------------registers---------------------------
//+-----+
//| vld |
//+-----+
always @(posedge lfb_lf_sm_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    lfb_lf_sm_vld       <=  1'b0;
  else if(lfb_lf_sm_req)
    lfb_lf_sm_vld       <=  1'b1;
  else if(lfb_lf_sm_cnt)
    lfb_lf_sm_vld       <=  1'b0;
end

//+------------+---------+---------+------+
//| refill way | addr_id | data_id | addr |
//+------------+---------+---------+------+
always @(posedge lfb_lf_sm_req_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
  begin
    lfb_lf_sm_dcache_share                <=  1'b0;
    lfb_lf_sm_refill_way                  <=  1'b0;
    lfb_lf_sm_addr_id[LFB_ADDR_ENTRY-1:0] <=  {
   LFB_ADDR_ENTRY{
   1'b0}};
    lfb_lf_sm_data_id[LFB_DATA_ENTRY-1:0] <=  {
   LFB_DATA_ENTRY{
   1'b0}};
    lfb_lf_sm_addr_tto6[`PA_WIDTH-7:0]    <=  {
   `PA_WIDTH-6{
   1'b0}};
  end
  else if(lfb_lf_sm_req  &&  lfb_lf_sm_permit)
  begin
    lfb_lf_sm_dcache_share                <=  lfb_lf_sm_data_dcache_share;
    lfb_lf_sm_refill_way                  <=  lfb_lf_sm_req_refill_way;
    lfb_lf_sm_addr_id[LFB_ADDR_ENTRY-1:0] <=  lfb_lf_sm_req_addr_ptr[LFB_ADDR_ENTRY-1:0];
    lfb_lf_sm_data_id[LFB_DATA_ENTRY-1:0] <=  lfb_lf_sm_req_data_ptr[LFB_DATA_ENTRY-1:0];
    lfb_lf_sm_addr_tto6[`PA_WIDTH-7:0]    <=  lfb_lf_sm_req_addr_tto6[`PA_WIDTH-7:0];
  end
end

//+-----+------+
//| cnt | bias |
//+-----+------+
//cnt is used for control path, bias is used for data path
always @(posedge lfb_lf_sm_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    lfb_lf_sm_cnt                         <=  1'b0;
  else if(lfb_lf_sm_create_vld)
    lfb_lf_sm_cnt                         <=  1'b0;
  else if(dcache_arb_lfb_ld_grnt)
    lfb_lf_sm_cnt                         <=  !lfb_lf_sm_cnt;
end

这段代码是负责处理加载填充缓冲区(Load Fill Buffer, LFB)中的linefill状态机(Linefill State Machine)。状态机管理着从外部内存加载数据到LFB的过程。主要组成部分如下:

  1. Valid Register (lfb_lf_sm_vld)

    • 这个寄存器指示状态机是否处于有效状态。它在接收到linefill请求(lfb_lf_sm_req)时被设置,当计数器(lfb_lf_sm_cnt)活跃时被重置。
  2. State Machine Registers

    • 这些寄存器存储状态机的当前状态,包括:

      • lfb_lf_sm_dcache_share:指示当前linefill是否与数据缓存共享。
      • lfb_lf_sm_refill_way:存储linefill操作的方式。
      • lfb_lf_sm_addr_id:地址条目的ID。
      • lfb_lf_sm_data_id:数据条目的ID。
      • lfb_lf_sm_addr_tto6:当前操作地址的部分字段。
    • 这些寄存器在状态机接收到有效的linefill请求且被允许执行时更新。

  3. Count Register (lfb_lf_sm_cnt)

    • 这个寄存器用于控制状态机的路径,当数据缓存向LFB发出加载授权(dcache_arb_lfb_ld_grnt)时,它会改变其值。这有助于控制状态机的流程,确保正确地处理加载操作。

综上所述,这部分代码是实现LFB功能的关键,它控制着从内存到LFB的数据加载过程,确保数据以正确的方式被加载和更新。通过这种方式,LFB有效地协调了缓存和内存之间的数据交换


//------------------create singal---------------------------
assign lfb_lf_sm_permit     = !lfb_lf_sm_vld ||  lfb_lf_sm_cnt;
assign lfb_lf_sm_req        = |lfb_data_entry_lf_sm_req[LFB_DATA_ENTRY-1:0];
assign lfb_lf_sm_create_vld = lfb_lf_sm_req
                              &&  lfb_lf_sm_permit;

//------------------create info-----------------------------
// &CombBeg; @490
always @( lfb_data_entry_lf_sm_req[1:0])
begin
lfb_lf_sm_req_data_ptr[LFB_DATA_ENTRY-1:0] = {
   LFB_DATA_ENTRY{
   1'b0}};
casez(lfb_data_entry_lf_sm_req[LFB_DATA_ENTRY-1:0])
  2'b?1:lfb_lf_sm_req_data_ptr[0] = 1'b1;
  2'b10:lfb_lf_sm_req_data_ptr[1] = 1'b1;
  default:lfb_lf_sm_req_data_ptr[LFB_DATA_ENTRY-1:0] = {
   LFB_DATA_ENTRY{
   1'b0}};
endcase
// &CombEnd; @497
end

assign lfb_lf_sm_data_grnt[LFB_DATA_ENTRY-1:0]  = {
   LFB_DATA_ENTRY{
   lfb_lf_sm_create_vld}}
                                                  & lfb_lf_sm_req_data_ptr[LFB_DATA_ENTRY-1:0];

assign lfb_lf_sm_req_addr_ptr[LFB_ADDR_ENTRY-1:0] = {
   LFB_ADDR_ENTRY{
   lfb_lf_sm_req_data_ptr[0]}}
                                                      & lfb_data_entry_addr_id_0[LFB_ADDR_ENTRY-1:0]
                                                    | {
   LFB_ADDR_ENTRY{
   lfb_lf_sm_req_data_ptr[1]}}
                                                      & lfb_data_entry_addr_id_1[LFB_ADDR_ENTRY-1:0];

assign lfb_lf_sm_req_addr_tto6[`PA_WIDTH-7:0]  =
                {
   `PA_WIDTH-6{
   lfb_lf_sm_req_addr_ptr[0]}}  & lfb_addr_entry_addr_tto4_0[`PA_WIDTH-5:2]
                | {
   `PA_WIDTH-6{
   lfb_lf_sm_req_addr_ptr[1]}}  & lfb_addr_entry_addr_tto4_1[`PA_WIDTH-5:2]
                | {
   `PA_WIDTH-6{
   lfb_lf_sm_req_addr_ptr[2]}}  & lfb_addr_entry_addr_tto4_2[`PA_WIDTH-5:2]
                | {
   `PA_WIDTH-6{
   lfb_lf_sm_req_addr_ptr[3]}}  & lfb_addr_entry_addr_tto4_3[`PA_WIDTH-5:2]
                | {
   `PA_WIDTH-6{
   lfb_lf_sm_req_addr_ptr[4]}}  & lfb_addr_entry_addr_tto4_4[`PA_WIDTH-5:2]
                | {
   `PA_WIDTH-6{
   lfb_lf_sm_req_addr_ptr[5]}}  & lfb_addr_entry_addr_tto4_5[`PA_WIDTH-5:2]
                | {
   `PA_WIDTH-6{
   lfb_lf_sm_req_addr_ptr[6]}}  & lfb_addr_entry_addr_tto4_6[`PA_WIDTH-5:2]
                | {
   `PA_WIDTH-6{
   lfb_lf_sm_req_addr_ptr[7]}}  & lfb_addr_entry_addr_tto4_7[`PA_WIDTH-5:2];


assign lfb_lf_sm_req_depd           = |(lfb_lf_sm_req_addr_ptr[LFB_ADDR_ENTRY-1:0]  & lfb_addr_entry_depd[LFB_ADDR_ENTRY-1:0]);
assign lfb_lf_sm_req_refill_way     = |(lfb_lf_sm_req_addr_ptr[LFB_ADDR_ENTRY-1:0]  & lfb_addr_entry_refill_way[LFB_ADDR_ENTRY-1:0]);
assign lfb_lf_sm_data_dcache_share  = |(lfb_lf_sm_req_data_ptr[LFB_DATA_ENTRY-1:0]  & lfb_data_entry_dcache_share[LFB_DATA_ENTRY-1:0]);

//------------------refill wakeup req-----------------------
assign lfb_lf_sm_refill_wakeup      = lfb_lf_sm_req_depd
                                      &&  lfb_lf_sm_create_vld;
//----------------------settle addr-------------------------
//-----------------data-----------------
assign lfb_lf_sm_data512[511:0]     = {
   512{
   lfb_lf_sm_data_id[0]}} & lfb_data_entry_data_0[511:0]
                                      | {
   512{
   lfb_lf_sm_data_id[1]}} & lfb_data_entry_data_1[511:0];

assign lfb_lf_sm_data256[255:0]     = lfb_lf_sm_cnt
                                      ? lfb_lf_sm_data512[511:256]
                                      : lfb_lf_sm_data512[255:0];

assign lfb_lf_sm_data_settle[255:0] = lfb_lf_sm_refill_way
                                      ? {
   lfb_lf_sm_data256[127:0],lfb_lf_sm_data256[255:128]}
                                      : lfb_lf_sm_data256[255:0];

这段代码详细描述了加载填充缓冲区(Load Fill Buffer, LFB)中的linefill状态机逻辑。这个状态机负责管理数据从内存到LFB的加载过程。

  1. 状态机创建信号 (lfb_lf_sm_permit, lfb_lf_sm_req, lfb_lf_sm_create_vld)

    • lfb_lf_sm_permit:当状态机处于非激活状态或计数器激活时,允许创建新的linefill请求。
    • lfb_lf_sm_req:如果有任何数据条目需要linefill请求,则设置。
    • lfb_lf_sm_create_vld:当存在有效的linefill请求且允许执行时设置。
  2. 创建信息 (lfb_lf_sm_req_data_ptr)

    • 此段代码识别发起linefill请求的数据条目,并生成相应的指针。
  3. linefill状态机寄存器

    • 包括缓存共享标记(lfb_lf_sm_dcache_share)、要填充的方式(lfb_lf_sm_refill_way)、地址ID和数据ID。
  4. linefill唤醒请求 (lfb_lf_sm_refill_wakeup)

    • 当linefill请求与依赖项相关联且有效时,产生唤醒信号。
  5. 数据安置 (lfb_lf_sm_data_settle)

    • 此段代码处理从数据条目接收的512位数据,根据当前的计数器状态和填充方式,选择适当的256位数据进行处理。

综上所述,这部分代码的主要功能是协调和管理LFB中的linefill操作,确保数据以正确的顺序和方式从内存加载到LFB中。


//----------------------cache interface---------------------
assign lfb_dcache_arb_ld_req  = lfb_lf_sm_vld;
assign lfb_dcache_arb_st_req  = lfb_lf_sm_vld;
assign lfb_dcache_arb_serial_req  = lfb_lf_sm_vld &&  !lfb_lf_sm_cnt;

//---------------tag array--------------
// &Force("output", "lfb_dcache_arb_ld_tag_req"); @644
assign lfb_dcache_arb_ld_tag_req        = lfb_lf_sm_vld &&  lfb_lf_sm_cnt;
assign lfb_dcache_arb_ld_tag_gateclk_en = lfb_dcache_arb_ld_tag_req;
// &Force("output", "lfb_dcache_arb_ld_tag_idx"); @647
assign lfb_dcache_arb_ld_tag_idx[8:0]   = lfb_lf_sm_addr_tto6[8:0];
assign lfb_dcache_arb_ld_tag_din[53:0]  = {
   1'b1,lfb_lf_sm_addr_tto6[`PA_WIDTH-7:8],1'b1,lfb_lf_sm_addr_tto6[`PA_WIDTH-7:8]};
// &Force("output", "lfb_dcache_arb_ld_tag_wen"); @654
assign lfb_dcache_arb_ld_tag_wen[1:0]   = lfb_lf_sm_cnt
                                          ? {
   lfb_lf_sm_refill_way,!lfb_lf_sm_refill_way}
                                          : 2'b0;

assign lfb_dcache_arb_st_tag_req        = lfb_dcache_arb_ld_tag_req;
assign lfb_dcache_arb_st_tag_gateclk_en = lfb_dcache_arb_ld_tag_req;
assign lfb_dcache_arb_st_tag_idx[8:0]   = lfb_dcache_arb_ld_tag_idx[8:0];
assign lfb_dcache_arb_st_tag_din[51:0]  = {
   lfb_lf_sm_addr_tto6[`PA_WIDTH-7:8],lfb_lf_sm_addr_tto6[`PA_WIDTH-7:8]};
assign lfb_dcache_arb_st_tag_wen[1:0]   = lfb_dcache_arb_ld_tag_wen[1:0];

//---------------dirty array------------
assign lfb_dcache_arb_st_dirty_req      = lfb_dcache_arb_ld_tag_req;
assign lfb_dcache_arb_st_dirty_gateclk_en = lfb_dcache_arb_ld_tag_req;
assign lfb_dcache_arb_st_dirty_idx[8:0] = lfb_lf_sm_addr_tto6[8:0];
assign lfb_dcache_arb_st_dirty_din[6:0] = {
   !lfb_lf_sm_refill_way,1'b0,lfb_lf_sm_dcache_share,1'b1,1'b0,lfb_lf_sm_dcache_share,1'b1};
assign lfb_dcache_arb_st_dirty_wen[6:0] = {
   1'b1,{
   3{
   lfb_lf_sm_refill_way}},{
   3{
   !lfb_lf_sm_refill_way}}};

//---------------data array-------------
assign lfb_dcache_arb_ld_data_gateclk_en[7:0] = {
   8{
   lfb_lf_sm_vld}};
assign lfb_dcache_arb_ld_data_idx[10:0] = {
   lfb_lf_sm_addr_tto6[8:0],lfb_lf_sm_cnt,lfb_lf_sm_refill_way};
assign lfb_dcache_arb_ld_data_low_din[127:0]  = lfb_lf_sm_data_settle[127:0];
assign lfb_dcache_arb_ld_data_high_din[127:0] = lfb_lf_sm_data_settle[255:128];
//assign lsu_dcache_ld_data_wen[31:0]           = 32'hffff_ffff;

//----------------------pop signal--------------------------
assign lfb_lf_sm_addr_pop_req[LFB_ADDR_ENTRY-1:0] = {
   LFB_ADDR_ENTRY{
   lfb_lf_sm_vld &&  lfb_lf_sm_cnt}}
                                                    & lfb_lf_sm_addr_id[LFB_ADDR_ENTRY-1:0];

assign lfb_lf_sm_data_pop_req[LFB_DATA_ENTRY-1:0] = {
   LFB_DATA_ENTRY{
   lfb_lf_sm_vld &&  lfb_lf_sm_cnt}}
                                                    & lfb_lf_sm_data_id[LFB_DATA_ENTRY-1:0];

assign lfb_data_addr_pop_req[LFB_ADDR_ENTRY-1:0]  = lfb_data_entry_addr_pop_req_0[LFB_ADDR_ENTRY-1:0]
                                                    | lfb_data_entry_addr_pop_req_1[LFB_ADDR_ENTRY-1:0];

这段代码展示了加载填充缓冲区(LFB)与缓存(例如数据缓存)接口的逻辑。关键部分包括:

  1. 缓存接口信号

    • lfb_dcache_arb_ld_reqlfb_dcache_arb_st_req:当状态机有效时,向缓存发送加载(ld)和存储(st)请求。
    • lfb_dcache_arb_serial_req:状态机有效且计数器未激活时,发送序列请求。
  2. 标签数组(Tag Array)接口

    • 管理数据缓存中的标签部分,包括读取和写入操作。当状态机有效且计数器激活时,生成相关的控制信号。
  3. 脏位数组(Dirty Array)接口

    • 用于标记缓存中脏数据(已被修改但尚未写回到内存)。控制信号与标签数组接口类似。
  4. 数据数组(Data Array)接口

    • 管理缓存中的数据部分。根据状态机的当前状态和需要填充的方式,选择适当的数据进行处理。
  5. 弹出信号(Pop Signal)

    • 当状态机完成一次操作并准备进行下一步操作时,生成相应的弹出信号。
//==========================================================
//                Maintain wakeup queue
//==========================================================
//----------------------registers---------------------------
//+--------------+
//| wakeup_queue |
//+--------------+
//the queue stores the instructions waiting for wakeup
//the 12 bit of wakeup_queue is for mcic
always @(posedge lfb_wakeup_queue_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    lfb_wakeup_queue[LSIQ_ENTRY:0]  <=  {
   LSIQ_ENTRY+1{
   1'b0}};
  else if(rtu_yy_xx_flush)
    lfb_wakeup_queue[LSIQ_ENTRY:0]  <=  {
   LSIQ_ENTRY+1{
   1'b0}};
  else if(ld_da_lfb_set_wakeup_queue ||  lfb_pop_depd_ff)
    lfb_wakeup_queue[LSIQ_ENTRY:0]  <=  lfb_wakeup_queue_next[LSIQ_ENTRY:0];
end

//+-------------+
//| depd_pop_ff |
//+-------------+
//if depd pop, this will set to 1, and clear wakeup_queue next cycle
// &Force("output","lfb_pop_depd_ff"); @720
always @(posedge lfb_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    lfb_pop_depd_ff     <=  1'b0;
  else if(lfb_addr_pop_depd
      ||  lfb_addr_pop_discard_vld
      ||  rb_lfb_boundary_depd_wakeup
      ||  lfb_lf_sm_refill_wakeup
      ||  lm_lfb_depd_wakeup)
    lfb_pop_depd_ff     <=  1'b1;
  else
    lfb_pop_depd_ff     <=  1'b0;
end

//----------------forward to depd_pop_ff------------------
assign lfb_addr_pop_depd        = |(lfb_addr_entry_pop_vld[LFB_ADDR_ENTRY-1:0]
                                    & lfb_addr_entry_depd[LFB_ADDR_ENTRY-1:0]);
assign lfb_addr_pop_discard_vld = |(lfb_addr_entry_pop_vld[LFB_ADDR_ENTRY-1:0]
                                    & lfb_addr_entry_discard_vld[LFB_ADDR_ENTRY-1:0]);

//------------------update wakeup queue---------------------
assign lfb_wakeup_queue_after_pop[LSIQ_ENTRY:0] = lfb_pop_depd_ff
                                                  ? {
   LSIQ_ENTRY+1{
   1'b0}}
                                                  : lfb_wakeup_queue[LSIQ_ENTRY:0];

assign lfb_wakeup_queue_next[LSIQ_ENTRY:0]  = lfb_wakeup_queue_after_pop[LSIQ_ENTRY:0]
                                              | {
   LSIQ_ENTRY+1{
   ld_da_lfb_set_wakeup_queue}}
                                                & ld_da_lfb_wakeup_queue_next[LSIQ_ENTRY:0];

//------------------------wakeup----------------------------
assign lfb_depd_wakeup[LSIQ_ENTRY-1:0]  = lfb_pop_depd_ff
                                          ? lfb_wakeup_queue[LSIQ_ENTRY-1:0]
                                          : {
   LSIQ_ENTRY{
   1'b0}};

assign lfb_mcic_wakeup                  = (lfb_pop_depd_ff  ||  rtu_yy_xx_flush)
                                          ? lfb_wakeup_queue[LSIQ_ENTRY]
                                          : 1'b0;
//==========================================================
//                for avoid deadlock with no rready
//==========================================================
assign lfb_addr_create_vld        = lfb_addr_rb_create_vld || lfb_addr_pfu_create_vld;
assign lfb_no_rcl_cnt_create[3:0] = {
   3'b0,lfb_addr_create_vld && cp0_lsu_dcache_en};
assign lfb_no_rcl_cnt_pop[3:0]    = {
   3'b0,vb_lfb_rcl_done} 
                                    + {
   3'b0,snq_lfb_bypass_invalid[0]}
                                    + {
   3'b0,snq_lfb_bypass_invalid[1]};

assign lfb_no_rcl_cnt_updt_vld    = lfb_addr_create_vld && cp0_lsu_dcache_en
                                    || vb_lfb_rcl_done 
                                    || |snq_lfb_bypass_invalid[1:0]; 

assign lfb_no_rcl_cnt_updt_val[3:0] = lfb_no_rcl_cnt[3:0]
                                      + lfb_no_rcl_cnt_create[3:0] 
                                      - lfb_no_rcl_cnt_pop[3:0]; 

always @(posedge lfb_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    lfb_no_rcl_cnt[3:0]   <=  4'b0;
  else if(lfb_no_rcl_cnt_updt_vld)
    lfb_no_rcl_cnt[3:0]   <=  lfb_no_rcl_cnt_updt_val[3:0];
end

assign lfb_nc_rready_grnt     = (lfb_no_rcl_cnt[3:0] <= 4'd1);
assign lfb_ca_rready_grnt     = (lfb_no_rcl_cnt[3:0] <  4'd1);
assign lfb_rb_nc_rready_grnt  = lfb_nc_rready_grnt;
assign lfb_rb_ca_rready_grnt  = lfb_ca_rready_grnt;
assign lfb_pfu_rready_grnt    = lfb_ca_rready_grnt;

//for rready,if all addr entry has resp,then not deassert rready
assign lfb_addr_all_resp      = !(|lfb_addr_entry_not_resp[LFB_ADDR_ENTRY-1:0]);
//==========================================================
//              Interface to other module
//==========================================================
//---------------------hit idx------------------------------
assign lfb_ld_da_hit_idx        = |lfb_addr_entry_ld_da_hit_idx[LFB_ADDR_ENTRY-1:0];
assign lfb_st_da_hit_idx        = |lfb_addr_entry_st_da_hit_idx[LFB_ADDR_ENTRY-1:0];
assign lfb_rb_biu_req_hit_idx   = |lfb_addr_entry_rb_biu_req_hit_idx[LFB_ADDR_ENTRY-1:0];
assign lfb_pfu_biu_req_hit_idx  = |lfb_addr_entry_pfu_biu_req_hit_idx[LFB_ADDR_ENTRY-1:0];
//assign lfb_snq_stall            = |lfb_addr_entry_snq_create_hit_idx[LFB_ADDR_ENTRY-1:0];
assign lfb_wmb_read_req_hit_idx = |lfb_addr_entry_wmb_read_req_hit_idx[LFB_ADDR_ENTRY-1:0];
assign lfb_wmb_write_req_hit_idx= |lfb_addr_entry_wmb_write_req_hit_idx[LFB_ADDR_ENTRY-1:0];

//for snq
// &Force("output","lfb_snq_bypass_data_id"); @804
assign lfb_snq_bypass_hit          = |lfb_addr_entry_snq_bypass_hit[LFB_ADDR_ENTRY-1:0];
assign lfb_snq_bypass_data_id[1:0] = lfb_data_entry_vld[LFB_DATA_ENTRY-1:0]
                                     & {
   lfb_addr_entry_snq_bypass_hit[LFB_ADDR_ENTRY-1:0] == lfb_data_entry_addr_id_1[LFB_ADDR_ENTRY-1:0],
                                        lfb_addr_entry_snq_bypass_hit[LFB_ADDR_ENTRY-1:0] == lfb_data_entry_addr_id_0[LFB_ADDR_ENTRY-1:0]};
assign lfb_snq_bypass_share        = |(lfb_snq_bypass_data_id[1:0] & lfb_data_entry_dcache_share[1:0]);
//----------------interface to biu--------------------------
assign lfb_data_not_full        = !(&lfb_data_entry_full[LFB_DATA_ENTRY-1:0]);
assign lsu_biu_r_linefill_ready = lfb_data_not_full || lfb_addr_all_resp;
//------------------full/empty signal-----------------------
assign lfb_addr_empty           = !(|lfb_addr_entry_vld[LFB_ADDR_ENTRY-1:0]);
assign lfb_data_empty           = !(|lfb_data_entry_vld[LFB_DATA_ENTRY-1:0]);
// &Force("output","lfb_empty"); @816
assign lfb_empty                = lfb_addr_empty  &&  lfb_data_empty  &&  !lfb_vb_req_unmask;
// &Force("output","lfb_addr_full"); @818
assign lfb_addr_full            = &lfb_addr_entry_vld[LFB_ADDR_ENTRY-1:0];
assign lfb_addr_less2           = &(lfb_addr_entry_vld[LFB_ADDR_ENTRY-1:0]
                                    | lfb_addr_create_ptr[LFB_ADDR_ENTRY-1:0]);
assign lsu_had_lfb_addr_entry_vld[LFB_ADDR_ENTRY-1:0] = lfb_addr_entry_vld[LFB_ADDR_ENTRY-1:0];
assign lsu_had_lfb_addr_entry_rcl_done[LFB_ADDR_ENTRY-1:0]  = lfb_addr_entry_rcl_done[LFB_ADDR_ENTRY-1:0];
assign lsu_had_lfb_addr_entry_dcache_hit[LFB_ADDR_ENTRY-1:0]= lfb_addr_entry_dcache_hit[LFB_ADDR_ENTRY-1:0];
assign lsu_had_lfb_data_entry_vld[LFB_DATA_ENTRY-1:0] = lfb_data_entry_vld[LFB_DATA_ENTRY-1:0];
assign lsu_had_lfb_data_entry_last[LFB_DATA_ENTRY-1:0] = lfb_data_entry_last[LFB_DATA_ENTRY-1:0];
assign lsu_had_lfb_wakeup_queue[LSIQ_ENTRY:0] = lfb_wakeup_queue[LSIQ_ENTRY:0];
assign lsu_had_lfb_lf_sm_vld  = lfb_lf_sm_vld;

//==========================================================
//        interface to hpcp
//==========================================================
assign ld_hit_prefetch = |ld_hit_prefetch_first[LFB_ADDR_ENTRY-1:0]; 

这段代码涉及多个关键部分,主要是关于加载填充缓冲区(LFB)的唤醒队列管理、避免死锁、与其他模块的接口以及性能计数器的接口。具体来说:

  1. 唤醒队列管理

    • lfb_wakeup_queue:存储等待唤醒的指令。
    • lfb_pop_depd_ff:当有依赖项被弹出时设置为1,随后清除唤醒队列。
    • 唤醒信号被发送到相关的部分,以通知等待的指令可以继续执行。
  2. 避免死锁

    • lfb_no_rcl_cnt:追踪当前没有接收到响应的LFB创建请求的数量。
    • 根据当前的未响应请求数量,控制是否授予rready信号。
  3. 与其他模块的接口

    • 提供一系列信号,如lfb_ld_da_hit_idxlfb_st_da_hit_idx,用于指示LFB中是否有与特定请求相匹配的项。
    • 处理来自BIU(总线接口单元)的响应,判断数据是否完整。
  4. 性能计数器接口

    • ld_hit_prefetch:指示是否有加载操作命中预取。

相关推荐

  1. openc910LSU系列66

    2024-01-09 16:02:01       51 阅读
  2. arm64架构下编译安装kafka —— 筑梦

    2024-01-09 16:02:01       28 阅读
  3. 华为鲲鹏ARM处理器920916系列

    2024-01-09 16:02:01       114 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-09 16:02:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-09 16:02:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-01-09 16:02:01       87 阅读
  4. Python语言-面向对象

    2024-01-09 16:02:01       96 阅读

热门阅读

  1. golang学习-流程控制

    2024-01-09 16:02:01       58 阅读
  2. pytest-mock 数据模拟

    2024-01-09 16:02:01       79 阅读
  3. 用 Socket.D 替代原生 WebSocket 做前端开发

    2024-01-09 16:02:01       65 阅读
  4. 常见连读技巧

    2024-01-09 16:02:01       75 阅读
  5. Linux CentOS官方文档之U盘安装

    2024-01-09 16:02:01       58 阅读
  6. ACP科普:为什么Scrum的冲刺周期不变?

    2024-01-09 16:02:01       55 阅读
  7. socket从客户端向主机传输一个文件

    2024-01-09 16:02:01       55 阅读
  8. Scrum产品负责人(CSPO)认证Scrum Product Owner

    2024-01-09 16:02:01       56 阅读
  9. Redis面试题5

    2024-01-09 16:02:01       51 阅读