openc910源码LSU系列之<96>

ct_lsu_pfu_pfb_entry

module ct_lsu_pfu_pfb_entry(
  amr_wa_cancel,
  cp0_lsu_icg_en,
  cp0_lsu_l2_st_pref_en,
  cp0_lsu_pfu_mmu_dis,
  cp0_yy_clk_en,
  cp0_yy_priv_mode,
  cpurst_b,
  ld_da_ldfifo_pc,
  ld_da_page_sec_ff,
  ld_da_page_share_ff,
  ld_da_pfu_act_dp_vld,
  ld_da_pfu_act_vld,
  ld_da_pfu_evict_cnt_vld,
  ld_da_pfu_pf_inst_vld,
  ld_da_ppfu_va,
  ld_da_ppn_ff,
  lsu_pfu_l1_dist_sel,
  lsu_pfu_l2_dist_sel,
  lsu_special_clk,
  pad_yy_icg_scan_en,
  pfb_no_req_cnt_val,
  pfb_timeout_cnt_val,
  pfu_biu_pe_req_sel_l1,
  pfu_dcache_pref_en,
  pfu_get_page_sec,
  pfu_get_page_share,
  pfu_get_ppn,
  pfu_get_ppn_err,
  pfu_get_ppn_vld,
  pfu_l2_pref_en,
  pfu_mmu_pe_req_sel_l1,
  pfu_pfb_create_pc,
  pfu_pfb_create_stride,
  pfu_pfb_create_stride_neg,
  pfu_pfb_create_strideh_6to0,
  pfu_pfb_create_type_ld,
  pfu_pfb_entry_biu_pe_req_grnt_x,
  pfu_pfb_entry_biu_pe_req_src_v,
  pfu_pfb_entry_biu_pe_req_x,
  pfu_pfb_entry_create_dp_vld_x,
  pfu_pfb_entry_create_gateclk_en_x,
  pfu_pfb_entry_create_vld_x,
  pfu_pfb_entry_evict_x,
  pfu_pfb_entry_from_lfb_dcache_hit_x,
  pfu_pfb_entry_from_lfb_dcache_miss_x,
  pfu_pfb_entry_hit_pc_x,
  pfu_pfb_entry_l1_page_sec_x,
  pfu_pfb_entry_l1_page_share_x,
  pfu_pfb_entry_l1_pf_addr_v,
  pfu_pfb_entry_l1_vpn_v,
  pfu_pfb_entry_l2_page_sec_x,
  pfu_pfb_entry_l2_page_share_x,
  pfu_pfb_entry_l2_pf_addr_v,
  pfu_pfb_entry_l2_vpn_v,
  pfu_pfb_entry_mmu_pe_req_grnt_x,
  pfu_pfb_entry_mmu_pe_req_src_v,
  pfu_pfb_entry_mmu_pe_req_x,
  pfu_pfb_entry_priv_mode_v,
  pfu_pfb_entry_vld_x,
  pfu_pop_all_part_vld,
  st_da_page_sec_ff,
  st_da_page_share_ff,
  st_da_pc,
  st_da_pfu_act_vld,
  st_da_pfu_evict_cnt_vld,
  st_da_pfu_pf_inst_vld,
  st_da_ppfu_va,
  st_da_ppn_ff
);

ct_lsu_pfu_pfb_entry 模块看起来是更大微架构的一部分,很可能与处理器中的负载存储单元(LSU)有关,特别是涉及到预取单元(PFU)中的预取缓冲(PFB)管理。模块的输入和输出暗示它负责处理 CPU 中预取的各个方面。

输入和输出分析

  1. 控制和配置输入:

    • cp0_lsu_icg_encp0_lsu_l2_st_pref_encp0_lsu_pfu_mmu_dis 等,可能是来自控制寄存器(在 MIPS 架构中可能是 CP0)的配置信号,决定 LSU 或 PFU 的操作方式,如启用/禁用某些功能。
  2. 时钟和重置输入:

    • cpurst_blsu_special_clkcp0_yy_clk_en 与时钟门控和重置功能相关,对电源管理和初始化至关重要。
  3. 地址和数据输入:

    • ld_da_ppfu_vald_da_ppn_ffst_da_ppfu_vast_da_ppn_ff 表明该模块处理虚拟和物理地址,暗示涉及地址转换或缓存管理。
  4. 预取和缓存控制:

    • pfu_dcache_pref_enpfu_l2_pref_en 表示对不同缓存级别预取的启用信号。
    • pfu_pfb_create_* 输入暗示创建预取缓冲区条目,包括步幅计算和类型确定(加载或存储)。
  5. 页表和安全输入:

    • ld_da_page_sec_ffld_da_page_share_ffst_da_page_sec_ffst_da_page_share_ff 可能与页面表条目相关,指示内存页面的安全性和共享属性。
  6. 预取缓冲管理:

    • pfu_pfb_entry_* 输入和输出是管理预取缓冲条目的核心。它们处理预取请求的创建、有效性、逐出和命中检测。
  7. 加载和存储输入:

    • 诸如 ld_da_ldfifo_pcst_da_pc 之类与加载(ld_)和存储(st_)操作相关的信号表明与基于加载/存储指令的数据预取交互。

功能概述

  • 该模块似乎根据当前加载/存储请求和页面表信息管理预取缓冲条目。
  • 它可能与数据缓存(L1)以及可能的更高级别缓存(L2)进行交互,以决定预取决策。
  • 该模块可能负责根据步幅模式(顺序访问检测)和页面属性(如安全性和共享性)确定是否预取数据。
  • 处理加载和存储预取请求表明采用了全面的预取方法,旨在减少缓存未命中并提高性能。
  • MMU(内存管理单元)相关信号的存在表明其在地址转换或处理虚拟到物理地址映射中的作用。
parameter TIMEOUT_BW          = 8;
parameter PC_LEN              = 15;
//==========================================================
//                 Instance of Gated Cell  
//==========================================================
assign pfu_pfb_entry_clk_en = pfu_pfb_entry_vld
                              ||  pfu_pfb_entry_create_gateclk_en;
// &Instance("gated_clk_cell", "x_lsu_pfu_pfb_entry_gated_clk"); @42
gated_clk_cell  x_lsu_pfu_pfb_entry_gated_clk (
  .clk_in               (lsu_special_clk     ),
  .clk_out              (pfu_pfb_entry_clk   ),
  .external_en          (1'b0                ),
  .global_en            (cp0_yy_clk_en       ),
  .local_en             (pfu_pfb_entry_clk_en),
  .module_en            (cp0_lsu_icg_en      ),
  .pad_yy_icg_scan_en   (pad_yy_icg_scan_en  )
);

// &Connect(.clk_in        (lsu_special_clk     ), @43
//          .external_en   (1'b0               ), @44
//          .global_en     (cp0_yy_clk_en      ), @45
//          .module_en     (cp0_lsu_icg_en     ), @46
//          .local_en      (pfu_pfb_entry_clk_en), @47
//          .clk_out       (pfu_pfb_entry_clk  )); @48

//create clk
assign pfu_pfb_entry_create_clk_en = pfu_pfb_entry_create_gateclk_en;
// &Instance("gated_clk_cell", "x_lsu_pfu_pfb_entry_create_gated_clk"); @52
gated_clk_cell  x_lsu_pfu_pfb_entry_create_gated_clk (
  .clk_in                      (lsu_special_clk            ),
  .clk_out                     (pfu_pfb_entry_create_clk   ),
  .external_en                 (1'b0                       ),
  .global_en                   (cp0_yy_clk_en              ),
  .local_en                    (pfu_pfb_entry_create_clk_en),
  .module_en                   (cp0_lsu_icg_en             ),
  .pad_yy_icg_scan_en          (pad_yy_icg_scan_en         )
);

// &Connect(.clk_in        (lsu_special_clk     ), @53
//          .external_en   (1'b0               ), @54
//          .global_en     (cp0_yy_clk_en      ), @55
//          .module_en     (cp0_lsu_icg_en     ), @56
//          .local_en      (pfu_pfb_entry_create_clk_en), @57
//          .clk_out       (pfu_pfb_entry_create_clk)); @58

//pf_inst_vld clk
assign pfu_pfb_entry_all_pf_inst_clk_en = pfu_pfb_entry_vld
                                             &&  (ld_da_pfu_pf_inst_vld || st_da_pfu_pf_inst_vld)
                                          || pfu_pfb_entry_biu_pe_req
                                          || pfu_pfb_entry_create_gateclk_en;
// &Instance("gated_clk_cell", "x_lsu_pfu_pfb_entry_all_pf_inst_gated_clk"); @65
gated_clk_cell  x_lsu_pfu_pfb_entry_all_pf_inst_gated_clk (
  .clk_in                           (lsu_special_clk                 ),
  .clk_out                          (pfu_pfb_entry_all_pf_inst_clk   ),
  .external_en                      (1'b0                            ),
  .global_en                        (cp0_yy_clk_en                   ),
  .local_en                         (pfu_pfb_entry_all_pf_inst_clk_en),
  .module_en                        (cp0_lsu_icg_en                  ),
  .pad_yy_icg_scan_en               (pad_yy_icg_scan_en              )
);

时钟门控单元(Gated Clock Cell)

  1. 基础结构:

    • gated_clk_cell 是一个标准的时钟门控单元,用于根据不同的使能信号开启或关闭时钟信号。这对于动态电源管理非常重要,因为它允许在不需要时关闭模块的时钟,从而节省能源。
  2. 时钟使能信号(Clock Enable Signals):

    • pfu_pfb_entry_clk_en:这是一个主要的时钟使能信号,由 pfu_pfb_entry_vld(预取缓冲区条目有效)或 pfu_pfb_entry_create_gateclk_en(预取缓冲区条目创建的额外门控时钟使能)控制。
    • pfu_pfb_entry_create_clk_en:专用于控制预取缓冲区条目创建逻辑的时钟使能信号。
    • pfu_pfb_entry_all_pf_inst_clk_en:这个使能信号控制与所有预取指令相关的逻辑的时钟,涉及加载(ld_da_pfu_pf_inst_vld)和存储(st_da_pfu_pf_inst_vld)预取指令的有效性,以及来自BIU(总线接口单元)的请求(pfu_pfb_entry_biu_pe_req)。
  3. 时钟门控单元的连接:

    • 每个时钟门控单元实例都连接了相同的输入和输出信号,但是使用了不同的本地使能(local_en)信号。这些实例包括:x_lsu_pfu_pfb_entry_gated_clkx_lsu_pfu_pfb_entry_create_gated_clkx_lsu_pfu_pfb_entry_all_pf_inst_gated_clk
    • 共同的输入包括 lsu_special_clk(特殊时钟输入),cp0_yy_clk_en(全局使能),cp0_lsu_icg_en(模块使能),和 pad_yy_icg_scan_en(扫描使能,用于测试模式)。

功能和重要性

  • 动态电源管理: 通过在不同的操作阶段启用或禁用时钟,这种方法可以显著减少处理器的功耗。
  • 性能优化: 时钟门控还可以减少不必要的计算和内存访问,从而提高整体性能。
  • 模块化设计: 使用标准的 gated_clk_cell 模块说明了代码的模块化设计,易于维护和更新。
//==========================================================
//                 Register
//==========================================================
//+----+--------+----------------------+
//| pc | stride | stride_be_cache_line |
//+----+--------+----------------------+
always @(posedge pfu_pfb_entry_create_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
  begin
    pfu_pfb_entry_pc[PC_LEN-1:0]        <=  {PC_LEN{1'b0}};
    pfu_pfb_entry_stride[10:0]          <=  11'b0;
    pfu_pfb_entry_strideh_6to0[6:0]     <=  7'b0;
    pfu_pfb_entry_stride_neg            <=  1'b0;
    pfu_pfb_entry_type_ld               <=  1'b0;
  end
  else if(pfu_pfb_entry_create_dp_vld)
  begin
    pfu_pfb_entry_pc[PC_LEN-1:0]        <=  pfu_pfb_create_pc[PC_LEN-1:0];
    pfu_pfb_entry_stride[10:0]          <=  pfu_pfb_create_stride[10:0];
    pfu_pfb_entry_strideh_6to0[6:0]     <=  pfu_pfb_create_strideh_6to0[6:0];
    pfu_pfb_entry_stride_neg            <=  pfu_pfb_create_stride_neg;
    pfu_pfb_entry_type_ld               <=  pfu_pfb_create_type_ld;
  end
end

//+-------------+
//| timeout_cnt |
//+-------------+
always @(posedge pfu_pfb_entry_all_pf_inst_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    pfu_pfb_entry_timeout_cnt[TIMEOUT_BW-1:0] <=  {TIMEOUT_BW{1'b0}};
  else if(pfu_pfb_entry_create_dp_vld ||  pfu_pfb_entry_pf_inst_vld)
    pfu_pfb_entry_timeout_cnt[TIMEOUT_BW-1:0] <=  {TIMEOUT_BW{1'b0}};
  else if(pipe_evict_cnt_vld &&  !pfu_pfb_entry_timeout_cnt_full)
    pfu_pfb_entry_timeout_cnt[TIMEOUT_BW-1:0] <=  pfu_pfb_entry_timeout_cnt[TIMEOUT_BW-1:0]
                                                  + {{TIMEOUT_BW-1{1'b0}},1'b1};
end

//+-------------+
//| no_req_cnt |
//+-------------+
always @(posedge pfu_pfb_entry_all_pf_inst_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    pfu_pfb_entry_no_req_cnt[5:0] <=  {6{1'b0}};
  else if(pfu_pfb_entry_create_dp_vld ||  pfu_pfb_entry_biu_pe_req)
    pfu_pfb_entry_no_req_cnt[5:0] <=  {6{1'b0}};
  else if(pfu_pfb_entry_pf_inst_vld && !pfu_pfb_entry_no_req_cnt_full)
    pfu_pfb_entry_no_req_cnt[5:0] <=  pfu_pfb_entry_no_req_cnt[5:0]
                                                  + {{5{1'b0}},1'b1};
end
//+-------+
//| evict |
//+-------+
always @(posedge pfu_pfb_entry_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    pfu_pfb_entry_evict     <=  1'b0;
  else if(pfu_pfb_entry_create_dp_vld ||  pfu_pfb_entry_evict_clr)
    pfu_pfb_entry_evict     <=  1'b0;
  else if(pfu_pfb_entry_evict_set)
    pfu_pfb_entry_evict     <=  1'b1;
end

//+------------+
//| confidence |
//+------------+
always @(posedge pfu_pfb_entry_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    pfu_pfb_entry_confidence[2:0]     <=  3'b0;
  else if(pfu_pfb_entry_create_dp_vld)
    pfu_pfb_entry_confidence[2:0]     <=  3'b110;
  else if(pfu_pfb_entry_confidence_set)
    pfu_pfb_entry_confidence[2:0]     <=  pfu_pfb_entry_confidence_next[2:0];
end

寄存器定义和更新逻辑

  1. 程序计数器(PC)和步幅(Stride)寄存器:

    • 这些寄存器在 pfu_pfb_entry_create_clk 的上升沿更新。
    • 在复位信号 cpurst_b 为低电平时,寄存器被清零。
    • pfu_pfb_entry_create_dp_vld 信号有效时,从对应的创建信号(pfu_pfb_create_*)中获取值。
  2. 超时计数器(Timeout Counter):

    • pfu_pfb_entry_all_pf_inst_clk 的上升沿更新。
    • 在复位时或者当 pfu_pfb_entry_create_dp_vldpfu_pfb_entry_pf_inst_vld 有效时,计数器被重置为零。
    • pipe_evict_cnt_vld 有效且计数器未满时,计数器递增。
  3. 无请求计数器(No Request Counter):

    • 类似于超时计数器,但它在 pfu_pfb_entry_biu_pe_req 有效时也会重置。
    • pfu_pfb_entry_pf_inst_vld 有效且计数器未满时,计数器递增。
  4. 逐出标志(Evict Flag):

    • pfu_pfb_entry_clk 的上升沿更新。
    • 在复位时或者当 pfu_pfb_entry_create_dp_vldpfu_pfb_entry_evict_clr 有效时,逐出标志被清除。
    • pfu_pfb_entry_evict_set 有效时,逐出标志被设置。
  5. 置信度寄存器(Confidence Register):

    • pfu_pfb_entry_clk 的上升沿更新。
    • 在复位时被清零。
    • pfu_pfb_entry_create_dp_vld 有效时,置信度被设置为特定值(3’b110)。
    • pfu_pfb_entry_confidence_set 有效时,从 pfu_pfb_entry_confidence_next 获取下一个值。

功能和重要性

  • 这些寄存器为处理器中的预取逻辑提供了必要的状态信息,例如预取的地址(PC 和 Stride)、预取请求的状态(逐出标志和置信度)以及超时和无请求计数器,用于跟踪预取请求的进度和有效性。
  • 这种精细的状态管理对于优化预取策略和提高缓存命中率至关重要,可以减少延迟和提高处理器性能。
//==========================================================
//                 pipe info select
//==========================================================
assign pipe_cmp_inst_vld = pfu_pfb_entry_type_ld
                           ? ld_da_pfu_pf_inst_vld
                           : st_da_pfu_pf_inst_vld;

assign pipe_cmp_pc[PC_LEN-1:0] = pfu_pfb_entry_type_ld
                                 ? ld_da_ldfifo_pc[PC_LEN-1:0]
                                 : st_da_pc[PC_LEN-1:0];

assign pipe_evict_cnt_vld = ld_da_pfu_evict_cnt_vld || st_da_pfu_evict_cnt_vld;

assign pipe_act_vld       = pfu_pfb_entry_type_ld
                            ? ld_da_pfu_act_vld
                            : st_da_pfu_act_vld; 

assign pipe_ppfu_va[`PA_WIDTH-1:0]  = pfu_pfb_entry_type_ld
                                      ? ld_da_ppfu_va[`PA_WIDTH-1:0]
                                      : st_da_ppfu_va[`PA_WIDTH-1:0];

assign pipe_page_sec    = pfu_pfb_entry_type_ld
                          ? ld_da_page_sec_ff
                          : st_da_page_sec_ff; 

assign pipe_page_share  = pfu_pfb_entry_type_ld
                          ? ld_da_page_share_ff
                          : st_da_page_share_ff; 

assign pipe_ppn[`PA_WIDTH-13:0] = pfu_pfb_entry_type_ld
                                  ? ld_da_ppn_ff[`PA_WIDTH-13:0]
                                  : st_da_ppn_ff[`PA_WIDTH-13:0];

//st will not trigger l1 prefetch
assign l1_pref_en = pfu_dcache_pref_en
                    && pfu_pfb_entry_vld 
                    && pfu_pfb_entry_type_ld;
//==========================================================
//                 Caucalate pf_inst signal
//==========================================================
assign pfu_pfb_entry_hit_pc       = pfu_pfb_entry_vld
                                    &&  (pipe_cmp_pc[PC_LEN-1:0]
                                        ==  pfu_pfb_entry_pc[PC_LEN-1:0]);
assign pfu_pfb_entry_pf_inst_vld  = pfu_pfb_entry_hit_pc
                                    &&  pipe_cmp_inst_vld;
assign pfu_pfb_entry_act_vld      = pfu_pfb_entry_hit_pc
                                    &&  pipe_act_vld;

//for new inst create
assign pfu_pfb_entry_hit_pc_for_new = pfu_pfb_entry_hit_pc
                                      && !(pfu_pfb_entry_type_ld ^ ld_da_pfu_act_dp_vld);
//==========================================================
//                 no req evict
//==========================================================
//when pfb entry not send req for many inst,then set evict
assign pfu_pfb_entry_no_req_cnt_full = (pfu_pfb_entry_no_req_cnt[5:0]
                                        == pfb_no_req_cnt_val[5:0]);

管道信息选择

  1. 指令有效性(pipe_cmp_inst_vld):

    • 如果当前预取缓冲区条目是加载类型(pfu_pfb_entry_type_ld),则选择加载指令的有效性(ld_da_pfu_pf_inst_vld);否则选择存储指令的有效性(st_da_pfu_pf_inst_vld)。
  2. 程序计数器(PC):

    • 类似地,根据预取类型选择加载或存储指令的程序计数器(PC)。
  3. 逐出计数器有效性(pipe_evict_cnt_vld):

    • 指示加载或存储操作是否有效,以触发逐出计数器。
  4. 活动有效性(pipe_act_vld):

    • 根据预取类型选择加载或存储操作的活动有效性。
  5. 物理地址(pipe_ppfu_va)、页面安全性(pipe_page_sec)和页面共享性(pipe_page_share):

    • 分别根据预取类型选择加载或存储操作的相关属性。
  6. 物理页号(PPN):

    • 根据预取类型选择加载或存储操作的物理页号。
  7. L1预取使能(l1_pref_en):

    • 仅当是加载类型且数据缓存预取使能时,L1级预取才被使能。

预取指令信号计算

  • 命中PC(pfu_pfb_entry_hit_pc):

    • 当预取缓冲区条目有效且管道PC与预取缓冲区条目的PC相匹配时,认为命中。
  • 预取指令有效性(pfu_pfb_entry_pf_inst_vld):

    • 如果命中PC且管道中的指令有效,则预取指令有效。
  • 活动有效性(pfu_pfb_entry_act_vld):

    • 如果命中PC且管道中的活动有效,则活动有效。
  • 新指令创建时的命中PC(pfu_pfb_entry_hit_pc_for_new):

    • 用于处理新指令创建时的特殊情况,考虑加载类型与加载数据活动下沉有效性的异或。

无请求逐出

  • 无请求计数器满(pfu_pfb_entry_no_req_cnt_full):
    • 当预取缓冲区条目在很多指令中都没有发送请求时,触发逐出。

功能和重要性

  • 这部分代码显示了如何根据不同的指令类型(加载或存储)和预取缓冲区的状态来选择相应的管道信息。
  • 通过精确地控制预取逻辑,可以更有效地管理缓存,从而提高性能和减少延迟。
  • 特别是在处理复杂的缓存一致性和预取策略时,这种灵活的信息选择机制是非常重要的。
//==========================================================
//                Instance state machine
//==========================================================
// &ConnRule(s/^entry_/pfu_pfb_entry_/); @211
// &Instance("ct_lsu_pfu_pfb_tsm","x_ct_lsu_pfu_pfu_entry_tsm"); @212
ct_lsu_pfu_pfb_tsm  x_ct_lsu_pfu_pfu_entry_tsm (
  .cp0_lsu_icg_en                     (cp0_lsu_icg_en                    ),
  .cp0_yy_clk_en                      (cp0_yy_clk_en                     ),
  .cp0_yy_priv_mode                   (cp0_yy_priv_mode                  ),
  .cpurst_b                           (cpurst_b                          ),
  .entry_act_vld                      (pfu_pfb_entry_act_vld             ),
  .entry_biu_pe_req                   (pfu_pfb_entry_biu_pe_req          ),
  .entry_biu_pe_req_grnt              (pfu_pfb_entry_biu_pe_req_grnt     ),
  .entry_biu_pe_req_src               (pfu_pfb_entry_biu_pe_req_src      ),
  .entry_clk                          (pfu_pfb_entry_clk                 ),
  .entry_create_dp_vld                (pfu_pfb_entry_create_dp_vld       ),
  .entry_create_vld                   (pfu_pfb_entry_create_vld          ),
  .entry_dcache_hit_pop_req           (pfu_pfb_entry_dcache_hit_pop_req  ),
  .entry_from_lfb_dcache_hit          (pfu_pfb_entry_from_lfb_dcache_hit ),
  .entry_from_lfb_dcache_miss         (pfu_pfb_entry_from_lfb_dcache_miss),
  .entry_inst_new_va                  (pfu_pfb_entry_inst_new_va         ),
  .entry_l1_biu_pe_req_set            (pfu_pfb_entry_l1_biu_pe_req_set   ),
  .entry_l1_mmu_pe_req_set            (pfu_pfb_entry_l1_mmu_pe_req_set   ),
  .entry_l2_biu_pe_req_set            (pfu_pfb_entry_l2_biu_pe_req_set   ),
  .entry_l2_mmu_pe_req_set            (pfu_pfb_entry_l2_mmu_pe_req_set   ),
  .entry_mmu_pe_req                   (pfu_pfb_entry_mmu_pe_req          ),
  .entry_mmu_pe_req_grnt              (pfu_pfb_entry_mmu_pe_req_grnt     ),
  .entry_mmu_pe_req_src               (pfu_pfb_entry_mmu_pe_req_src      ),
  .entry_pf_inst_vld                  (pfu_pfb_entry_pf_inst_vld         ),
  .entry_pop_vld                      (pfu_pfb_entry_pop_vld             ),
  .entry_priv_mode                    (pfu_pfb_entry_priv_mode           ),
  .entry_reinit_vld                   (pfu_pfb_entry_reinit_vld          ),
  .entry_stride                       (pfu_pfb_entry_stride              ),
  .entry_stride_neg                   (pfu_pfb_entry_stride_neg          ),
  .entry_tsm_is_judge                 (pfu_pfb_entry_tsm_is_judge        ),
  .entry_vld                          (pfu_pfb_entry_vld                 ),
  .forever_cpuclk                     (lsu_special_clk                   ),
  .pad_yy_icg_scan_en                 (pad_yy_icg_scan_en                ),
  .pipe_va                            (pipe_ppfu_va                      )
);

// &Connect(.pipe_va             (pipe_ppfu_va         ), @213
//          .forever_cpuclk      (lsu_special_clk      )); @214

// &ConnRule(s/^entry_/pfu_pfb_entry_/); @216
// &Instance("ct_lsu_pfu_pfb_l1sm","x_ct_lsu_pfu_pfb_entry_l1sm"); @217
ct_lsu_pfu_pfb_l1sm  x_ct_lsu_pfu_pfb_entry_l1sm (
  .cp0_lsu_icg_en                         (cp0_lsu_icg_en                        ),
  .cp0_lsu_pfu_mmu_dis                    (cp0_lsu_pfu_mmu_dis                   ),
  .cp0_yy_clk_en                          (cp0_yy_clk_en                         ),
  .cpurst_b                               (cpurst_b                              ),
  .entry_biu_pe_req                       (pfu_pfb_entry_biu_pe_req              ),
  .entry_biu_pe_req_grnt                  (pfu_pfb_entry_biu_pe_req_grnt         ),
  .entry_biu_pe_req_src                   (pfu_pfb_entry_biu_pe_req_src          ),
  .entry_clk                              (pfu_pfb_entry_clk                     ),
  .entry_create_dp_vld                    (pfu_pfb_entry_create_dp_vld           ),
  .entry_inst_new_va                      (pfu_pfb_entry_inst_new_va             ),
  .entry_l1_biu_pe_req_set                (pfu_pfb_entry_l1_biu_pe_req_set       ),
  .entry_l1_cmp_va_vld                    (pfu_pfb_entry_l1_cmp_va_vld           ),
  .entry_l1_dist_strideh                  (pfu_pfb_entry_l1_dist_strideh         ),
  .entry_l1_mmu_pe_req_set                (pfu_pfb_entry_l1_mmu_pe_req_set       ),
  .entry_l1_page_sec                      (pfu_pfb_entry_l1_page_sec             ),
  .entry_l1_page_share                    (pfu_pfb_entry_l1_page_share           ),
  .entry_l1_pf_addr                       (pfu_pfb_entry_l1_pf_addr              ),
  .entry_l1_pf_va                         (pfu_pfb_entry_l1_pf_va                ),
  .entry_l1_pf_va_sub_inst_new_va         (pfu_pfb_entry_l1_pf_va_sub_inst_new_va),
  .entry_l1_vpn                           (pfu_pfb_entry_l1_vpn                  ),
  .entry_l1sm_reinit_req                  (pfu_pfb_entry_l1sm_reinit_req         ),
  .entry_l1sm_va_can_cmp                  (pfu_pfb_entry_l1sm_va_can_cmp         ),
  .entry_mmu_pe_req                       (pfu_pfb_entry_mmu_pe_req              ),
  .entry_mmu_pe_req_grnt                  (pfu_pfb_entry_mmu_pe_req_grnt         ),
  .entry_mmu_pe_req_src                   (pfu_pfb_entry_mmu_pe_req_src          ),
  .entry_pf_inst_vld                      (pfu_pfb_entry_pf_inst_vld             ),
  .entry_pop_vld                          (pfu_pfb_entry_pop_vld                 ),
  .entry_reinit_vld                       (pfu_pfb_entry_reinit_vld              ),
  .entry_stride_neg                       (pfu_pfb_entry_stride_neg              ),
  .entry_strideh                          (pfu_pfb_entry_strideh                 ),
  .entry_tsm_is_judge                     (pfu_pfb_entry_tsm_is_judge            ),
  .forever_cpuclk                         (lsu_special_clk                       ),
  .ld_da_page_sec_ff                      (ld_da_page_sec_ff                     ),
  .ld_da_page_share_ff                    (ld_da_page_share_ff                   ),
  .ld_da_ppn_ff                           (ld_da_ppn_ff                          ),
  .pad_yy_icg_scan_en                     (pad_yy_icg_scan_en                    ),
  .pfu_biu_pe_req_sel_l1                  (pfu_biu_pe_req_sel_l1                 ),
  .pfu_dcache_pref_en                     (l1_pref_en                            ),
  .pfu_get_page_sec                       (pfu_get_page_sec                      ),
  .pfu_get_page_share                     (pfu_get_page_share                    ),
  .pfu_get_ppn                            (pfu_get_ppn                           ),
  .pfu_get_ppn_err                        (pfu_get_ppn_err                       ),
  .pfu_get_ppn_vld                        (pfu_get_ppn_vld                       ),
  .pfu_mmu_pe_req_sel_l1                  (pfu_mmu_pe_req_sel_l1                 )
);

// &Connect(.forever_cpuclk      (lsu_special_clk      ), @218
//          .pfu_dcache_pref_en  (l1_pref_en           )); @219
// &Force("nonport","pfu_pfb_entry_l1_pf_va_sub_inst_new_va"); @220
// &Force("nonport","pfu_pfb_entry_l1_cmp_va_vld"); @221
// &Force("nonport","pfu_pfb_entry_l1sm_va_can_cmp"); @222

// &ConnRule(s/^entry_/pfu_pfb_entry_/); @224
// &Instance("ct_lsu_pfu_pfb_l2sm","x_ct_lsu_pfu_pfb_entry_l2sm"); @225
ct_lsu_pfu_pfb_l2sm  x_ct_lsu_pfu_pfb_entry_l2sm (
  .cp0_lsu_icg_en                      (cp0_lsu_icg_en                     ),
  .cp0_lsu_pfu_mmu_dis                 (cp0_lsu_pfu_mmu_dis                ),
  .cp0_yy_clk_en                       (cp0_yy_clk_en                      ),
  .cpurst_b                            (cpurst_b                           ),
  .entry_biu_pe_req                    (pfu_pfb_entry_biu_pe_req           ),
  .entry_biu_pe_req_grnt               (pfu_pfb_entry_biu_pe_req_grnt      ),
  .entry_biu_pe_req_src                (pfu_pfb_entry_biu_pe_req_src       ),
  .entry_clk                           (pfu_pfb_entry_clk                  ),
  .entry_create_dp_vld                 (pfu_pfb_entry_create_dp_vld        ),
  .entry_inst_new_va                   (pfu_pfb_entry_inst_new_va          ),
  .entry_l1_pf_va                      (pfu_pfb_entry_l1_pf_va             ),
  .entry_l2_biu_pe_req_set             (pfu_pfb_entry_l2_biu_pe_req_set    ),
  .entry_l2_cmp_va_vld                 (pfu_pfb_entry_l2_cmp_va_vld        ),
  .entry_l2_dist_strideh               (pfu_pfb_entry_l2_dist_strideh      ),
  .entry_l2_mmu_pe_req_set             (pfu_pfb_entry_l2_mmu_pe_req_set    ),
  .entry_l2_page_sec                   (pfu_pfb_entry_l2_page_sec          ),
  .entry_l2_page_share                 (pfu_pfb_entry_l2_page_share        ),
  .entry_l2_pf_addr                    (pfu_pfb_entry_l2_pf_addr           ),
  .entry_l2_pf_va_sub_l1_pf_va         (pfu_pfb_entry_l2_pf_va_sub_l1_pf_va),
  .entry_l2_vpn                        (pfu_pfb_entry_l2_vpn               ),
  .entry_l2sm_reinit_req               (pfu_pfb_entry_l2sm_reinit_req      ),
  .entry_l2sm_va_can_cmp               (pfu_pfb_entry_l2sm_va_can_cmp      ),
  .entry_mmu_pe_req                    (pfu_pfb_entry_mmu_pe_req           ),
  .entry_mmu_pe_req_grnt               (pfu_pfb_entry_mmu_pe_req_grnt      ),
  .entry_mmu_pe_req_src                (pfu_pfb_entry_mmu_pe_req_src       ),
  .entry_pf_inst_vld                   (pfu_pfb_entry_pf_inst_vld          ),
  .entry_pop_vld                       (pfu_pfb_entry_pop_vld              ),
  .entry_reinit_vld                    (pfu_pfb_entry_reinit_vld           ),
  .entry_stride_neg                    (pfu_pfb_entry_stride_neg           ),
  .entry_strideh                       (pfu_pfb_entry_strideh              ),
  .entry_tsm_is_judge                  (pfu_pfb_entry_tsm_is_judge         ),
  .forever_cpuclk                      (lsu_special_clk                    ),
  .ld_da_page_sec_ff                   (pipe_page_sec                      ),
  .ld_da_page_share_ff                 (pipe_page_share                    ),
  .ld_da_ppn_ff                        (pipe_ppn                           ),
  .pad_yy_icg_scan_en                  (pad_yy_icg_scan_en                 ),
  .pfu_biu_pe_req_sel_l1               (pfu_biu_pe_req_sel_l1              ),
  .pfu_get_page_sec                    (pfu_get_page_sec                   ),
  .pfu_get_page_share                  (pfu_get_page_share                 ),
  .pfu_get_ppn                         (pfu_get_ppn                        ),
  .pfu_get_ppn_err                     (pfu_get_ppn_err                    ),
  .pfu_get_ppn_vld                     (pfu_get_ppn_vld                    ),
  .pfu_l2_pref_en                      (pfu_l2_pref_en                     ),
  .pfu_mmu_pe_req_sel_l1               (pfu_mmu_pe_req_sel_l1              )
);

状态机实例化

  1. 顶级预取缓冲区状态机(ct_lsu_pfu_pfb_tsm):

    • 负责管理整个预取缓冲区条目的顶级状态,包括对预取请求的处理、预取缓冲区的管理等。
    • 接收多种信号,包括时钟信号(entry_clk)、复位信号(cpurst_b)、配置信号(如 cp0_lsu_icg_encp0_yy_clk_en)等。
  2. L1 预取缓冲区状态机(ct_lsu_pfu_pfb_l1sm):

    • 专门处理与 L1 缓存相关的预取逻辑。
    • 接收与 L1 缓存预取相关的信号,包括预取地址(entry_l1_pf_va)、步幅信息(entry_strideentry_stride_neg)等。
  3. L2 预取缓冲区状态机(ct_lsu_pfu_pfb_l2sm):

    • 用于处理与 L2 缓存相关的预取逻辑。
    • 接收与 L2 缓存预取相关的信号,类似于 L1 预取缓冲区状态机。

功能和重要性

  • 这些状态机代表了处理器中预取逻辑的不同层次。它们的存在确保了数据可以根据需要有效地从存储器中预取到缓存中。
  • 每个状态机都针对其特定的缓存级别(L1 或 L2)进行了优化,以最大化性能和效率。
  • 通过分离 L1 和 L2 的预取逻辑,可以更灵活地处理各自的预取策略和性能优化。
//==========================================================
//                Generate some compare info
//==========================================================
//------------------generate strideh------------------------
assign pfu_pfb_entry_strideh[`PA_WIDTH-1:0]         = {{`PA_WIDTH-11{pfu_pfb_entry_stride_neg}},
                                                      pfu_pfb_entry_stride[10:7],
                                                      pfu_pfb_entry_strideh_6to0[6:0]};

assign pfu_pfb_entry_l1_dist_strideh[`PA_WIDTH-1:0] = {`PA_WIDTH{lsu_pfu_l1_dist_sel[3]}} & {pfu_pfb_entry_strideh[`PA_WIDTH-4:0],3'b0}
                                                      | {`PA_WIDTH{lsu_pfu_l1_dist_sel[2]}} & {pfu_pfb_entry_strideh[`PA_WIDTH-3:0],2'b0}
                                                      | {`PA_WIDTH{lsu_pfu_l1_dist_sel[1]}} & {pfu_pfb_entry_strideh[`PA_WIDTH-2:0],1'b0}
                                                      | {`PA_WIDTH{lsu_pfu_l1_dist_sel[0]}} & pfu_pfb_entry_strideh[`PA_WIDTH-1:0];
assign pfu_pfb_entry_l2_dist_strideh[`PA_WIDTH-1:0] = {`PA_WIDTH{lsu_pfu_l2_dist_sel[3]}} & {pfu_pfb_entry_strideh[`PA_WIDTH-6:0],5'b0}
                                                      | {`PA_WIDTH{lsu_pfu_l2_dist_sel[2]}} & {pfu_pfb_entry_strideh[`PA_WIDTH-5:0],4'b0}
                                                      | {`PA_WIDTH{lsu_pfu_l2_dist_sel[1]}} & {pfu_pfb_entry_strideh[`PA_WIDTH-4:0],3'b0}
                                                      | {`PA_WIDTH{lsu_pfu_l2_dist_sel[0]}} & {pfu_pfb_entry_strideh[`PA_WIDTH-3:0],2'b0};

//==========================================================
//                    Set confidence
//==========================================================
assign pfu_pfb_entry_inst_new_va_hit_pipe = pipe_ppfu_va[`PA_WIDTH-1:0]
                                            ==  pfu_pfb_entry_inst_new_va[`PA_WIDTH-1:0];

//--------------------confidence set------------------------
assign pfu_pfb_entry_confidence_high      = &pfu_pfb_entry_confidence[2:0];
assign pfu_pfb_entry_confidence_low       = !(|pfu_pfb_entry_confidence[2:0]);

assign pfu_pfb_entry_confidence_set       = pfu_pfb_entry_tsm_is_judge
                                            &&  !(pfu_pfb_entry_confidence_high
                                                &&  pfu_pfb_entry_confidence_add_vld)
                                            &&  !(pfu_pfb_entry_confidence_low
                                                &&  !pfu_pfb_entry_confidence_add_vld)
                                            &&  pfu_pfb_entry_pf_inst_vld;

assign pfu_pfb_entry_confidence_add1[2:0] = pfu_pfb_entry_confidence[2:0] + 3'b1;
assign pfu_pfb_entry_confidence_sub1[2:0] = pfu_pfb_entry_confidence[2:0] - 3'b1;

assign pfu_pfb_entry_confidence_add_vld   = pfu_pfb_entry_inst_new_va_hit_pipe;

assign pfu_pfb_entry_confidence_next[2:0] = pfu_pfb_entry_confidence_add_vld
                                            ? pfu_pfb_entry_confidence_add1[2:0]
                                            : pfu_pfb_entry_confidence_sub1[2:0];

//--------------set confidence thdreshold------------------
assign pfu_pfb_entry_confidence_zero      = pfu_pfb_entry_confidence[2:0]
                                            ==  3'b0;

//==========================================================
//                    Set/clr evict
//==========================================================
assign pfu_pfb_entry_timeout_cnt_full = (pfu_pfb_entry_timeout_cnt[TIMEOUT_BW-1:0]
                                         == pfb_timeout_cnt_val[TIMEOUT_BW-1:0]);

assign pfu_pfb_entry_evict_set  = pfu_pfb_entry_vld
                                  &&  (pfu_pfb_entry_timeout_cnt_full
                                       || pfu_pfb_entry_no_req_cnt_full);

assign pfu_pfb_entry_evict_clr  = !pfu_pfb_entry_timeout_cnt_full
                                  && !pfu_pfb_entry_no_req_cnt_full;

//==========================================================
//                Generate pop signal
//==========================================================
assign pfu_pfb_entry_reinit_vld = pfu_pfb_entry_l1sm_reinit_req
                                  ||  pfu_pfb_entry_l2sm_reinit_req
                                  ||  pfu_pfb_entry_create_vld
                                  ||  pfu_pfb_entry_tsm_is_judge
                                      &&  pfu_pfb_entry_pf_inst_vld
                                      &&  !pfu_pfb_entry_inst_new_va_hit_pipe;

//st pref pop
assign pfu_pop_st_all = pfu_pfb_entry_vld
                        && !pfu_pfb_entry_type_ld 
                        && (!cp0_lsu_l2_st_pref_en || amr_wa_cancel);

assign pfu_pfb_entry_pop_vld    = pfu_pop_all_part_vld
                                  ||  pfu_pop_st_all
                                  ||  pfu_pfb_entry_vld
                                      &&  (pfu_pfb_entry_dcache_hit_pop_req
                                          ||  pfu_pfb_entry_confidence_zero);

步幅处理

  • 生成步幅高位(strideh):
    • pfu_pfb_entry_strideh 是通过组合 pfu_pfb_entry_stridepfu_pfb_entry_stride_neg 生成的,用于表示步幅的高位部分。
    • pfu_pfb_entry_l1_dist_stridehpfu_pfb_entry_l2_dist_strideh 分别是针对 L1 和 L2 缓存预取逻辑的步幅高位调整,依据不同的分布选择信号(lsu_pfu_l1_dist_sellsu_pfu_l2_dist_sel)进行位移操作。

置信度设置

  • 新虚拟地址命中管道(pfu_pfb_entry_inst_new_va_hit_pipe):

    • 当新虚拟地址(pfu_pfb_entry_inst_new_va)与管道中的虚拟地址(pipe_ppfu_va)相匹配时,认为命中。
  • 置信度相关逻辑:

    • pfu_pfb_entry_confidence_set 用于根据当前状态机判断和其他条件来更新置信度。
    • 置信度通过递增(pfu_pfb_entry_confidence_add1)或递减(pfu_pfb_entry_confidence_sub1)操作进行调整,具体取决于新虚拟地址是否命中。

逐出设置

  • 逐出条件:
    • 当超时计数器满(pfu_pfb_entry_timeout_cnt_full)或无请求计数器满(pfu_pfb_entry_no_req_cnt_full)时,将设置逐出标志(pfu_pfb_entry_evict_set)。
    • 当这些条件不满足时,清除逐出标志(pfu_pfb_entry_evict_clr)。

生成弹出信号

  • 重初始化有效性(pfu_pfb_entry_reinit_vld):

    • 当 L1 或 L2 状态机请求重初始化,或者创建新预取缓冲区条目时,设置重初始化有效性。
    • 当状态机判断和其他条件满足时,也可能触发重初始化。
  • 存储预取弹出(pfu_pop_st_all):

    • 当条目有效,且为存储类型,且不启用 L2 存储预取或满足特定取消条件时,设置存储预取弹出标志。
  • 预取缓冲区条目弹出有效性(pfu_pfb_entry_pop_vld):

    • 综合考虑所有部分的弹出请求,包括存储预取弹出、置信度为零时的弹出,以及数据缓存命中请求的弹出。

功能和重要性

  • 这些逻辑提供了对预取缓冲区条目状态的精细控制,包括根据访问模式调整步幅,根据预取效果调整置信度,以及在特定条件下触发逐出和弹出操作。
  • 这样的精细控制有助于优化预取策略,提高缓存的效率和命中率,从而改善处理器的整体性能。
//==========================================================
//                 Generate interface
//==========================================================
//------------------input-----------------------------------
//-----------create signal--------------
assign pfu_pfb_entry_create_vld         = pfu_pfb_entry_create_vld_x;
assign pfu_pfb_entry_create_dp_vld      = pfu_pfb_entry_create_dp_vld_x;
assign pfu_pfb_entry_create_gateclk_en  = pfu_pfb_entry_create_gateclk_en_x;
//---------grnt/done signal-------------
assign pfu_pfb_entry_biu_pe_req_grnt    = pfu_pfb_entry_biu_pe_req_grnt_x;
assign pfu_pfb_entry_mmu_pe_req_grnt    = pfu_pfb_entry_mmu_pe_req_grnt_x;
//-----------reply signal---------------
assign pfu_pfb_entry_from_lfb_dcache_hit  = pfu_pfb_entry_from_lfb_dcache_hit_x;
assign pfu_pfb_entry_from_lfb_dcache_miss = pfu_pfb_entry_from_lfb_dcache_miss_x;
//------------------output----------------------------------
//-----------entry signal---------------
assign pfu_pfb_entry_vld_x                        = pfu_pfb_entry_vld;
assign pfu_pfb_entry_l1_vpn_v[`PA_WIDTH-13:0]     = pfu_pfb_entry_l1_vpn[`PA_WIDTH-13:0];
assign pfu_pfb_entry_l1_pf_addr_v[`PA_WIDTH-1:0]  = pfu_pfb_entry_l1_pf_addr[`PA_WIDTH-1:0];
assign pfu_pfb_entry_l1_page_sec_x                = pfu_pfb_entry_l1_page_sec;
assign pfu_pfb_entry_l1_page_share_x              = pfu_pfb_entry_l1_page_share;
assign pfu_pfb_entry_l2_vpn_v[`PA_WIDTH-13:0]     = pfu_pfb_entry_l2_vpn[`PA_WIDTH-13:0];
assign pfu_pfb_entry_l2_pf_addr_v[`PA_WIDTH-1:0]  = pfu_pfb_entry_l2_pf_addr[`PA_WIDTH-1:0];
assign pfu_pfb_entry_l2_page_sec_x                = pfu_pfb_entry_l2_page_sec;
assign pfu_pfb_entry_l2_page_share_x              = pfu_pfb_entry_l2_page_share;
assign pfu_pfb_entry_biu_pe_req_x                 = pfu_pfb_entry_biu_pe_req;
assign pfu_pfb_entry_biu_pe_req_src_v[1:0]        = pfu_pfb_entry_biu_pe_req_src[1:0];
assign pfu_pfb_entry_mmu_pe_req_x                 = pfu_pfb_entry_mmu_pe_req;
assign pfu_pfb_entry_mmu_pe_req_src_v[1:0]        = pfu_pfb_entry_mmu_pe_req_src[1:0];
assign pfu_pfb_entry_evict_x                      = pfu_pfb_entry_evict;
assign pfu_pfb_entry_priv_mode_v[1:0]             = pfu_pfb_entry_priv_mode[1:0];
//-----------hit signal-----------------
assign pfu_pfb_entry_hit_pc_x                     = pfu_pfb_entry_hit_pc_for_new;

输入信号

  • 创建信号(Create Signals):

    • pfu_pfb_entry_create_vldpfu_pfb_entry_create_dp_vldpfu_pfb_entry_create_gateclk_en 是与预取缓冲区条目创建相关的有效性和门控时钟使能信号。
  • 授权/完成信号(Grant/Done Signals):

    • pfu_pfb_entry_biu_pe_req_grntpfu_pfb_entry_mmu_pe_req_grnt 分别是来自 BIU(总线接口单元)和 MMU(内存管理单元)的预取请求的授权信号。
  • 应答信号(Reply Signals):

    • pfu_pfb_entry_from_lfb_dcache_hitpfu_pfb_entry_from_lfb_dcache_miss 表示来自查找缓冲区(LFB)的数据缓存命中或未命中的应答。

输出信号

  • 条目信号(Entry Signals):

    • 包括预取缓冲区条目的各种状态信息,如有效性(pfu_pfb_entry_vld_x)、L1和L2的虚拟页号(VPN)、物理地址(PF Addr)、页面安全性(Page Sec)和共享性(Page Share)等。
  • BIU 和 MMU 请求信号:

    • pfu_pfb_entry_biu_pe_req_xpfu_pfb_entry_mmu_pe_req_x 是发送给 BIU 和 MMU 的预取请求信号,pfu_pfb_entry_biu_pe_req_src_vpfu_pfb_entry_mmu_pe_req_src_v 指示请求的来源。
  • 逐出和权限模式信号:

    • pfu_pfb_entry_evict_x 表示预取缓冲区条目的逐出标志,pfu_pfb_entry_priv_mode_v 表示权限模式。
  • 命中信号(Hit Signal):

    • pfu_pfb_entry_hit_pc_x 指示预取缓冲区条目是否命中,特别是针对新指令创建的情况。

功能和重要性

  • 这些信号为预取缓冲区条目的创建、管理和操作提供了必要的接口,使预取逻辑可以根据当前的处理器状态和内存访问模式进行调整。
  • 输入信号提供了对预取请求的控制,包括创建、授权和应答,而输出信号则提供了预取缓冲区的状态和行为控制。
  • 这种接口的设计允许灵活地处理预取缓冲区条目,优化缓存预取策略,提高处理器的效率和性能。