openc910源码LSU系列之<94>

ct_lsu_pfu_pmb_entry

module ct_lsu_pfu_pmb_entry(
  amr_wa_cancel,
  cp0_lsu_icg_en,
  cp0_lsu_l2_st_pref_en,
  cp0_yy_clk_en,
  cpurst_b,
  ld_da_ldfifo_pc,
  ld_da_pfu_act_dp_vld,
  ld_da_pfu_evict_cnt_vld,
  ld_da_pfu_pf_inst_vld,
  lsu_special_clk,
  pad_yy_icg_scan_en,
  pfu_pmb_entry_create_dp_vld_x,
  pfu_pmb_entry_create_gateclk_en_x,
  pfu_pmb_entry_create_vld_x,
  pfu_pmb_entry_evict_x,
  pfu_pmb_entry_hit_pc_x,
  pfu_pmb_entry_pc_v,
  pfu_pmb_entry_ready_grnt_x,
  pfu_pmb_entry_ready_x,
  pfu_pmb_entry_type_ld_x,
  pfu_pmb_entry_vld_x,
  pfu_pop_all_part_vld,
  pipe_create_pc,
  pmb_timeout_cnt_val,
  st_da_pc,
  st_da_pfu_evict_cnt_vld,
  st_da_pfu_pf_inst_vld
);

ct_lsu_pfu_pmb_entry模块是C910架构中负载存储单元(LSU)的预取单元(PFU)的一部分。

  1. 输入端口:

    • 控制信号: 包括amr_wa_cancelcp0_lsu_icg_encp0_lsu_l2_st_pref_encp0_yy_clk_encpurst_bpad_yy_icg_scan_en。它们可能用于各种控制功能,如时钟门控、复位和扫描测试。
    • 加载和存储数据:ld_da_ldfifo_pcld_da_pfu_act_dp_vldld_da_pfu_evict_cnt_vldld_da_pfu_pf_inst_vldst_da_pcst_da_pfu_evict_cnt_vldst_da_pfu_pf_inst_vld等输入可能与加载和存储操作的数据和控制路径相关,包括预取指令和逐出计数。
    • 预取和PMB管理:pfu_pop_all_part_vldpipe_create_pcpmb_timeout_cnt_val等输入表明该模块参与处理预取请求和管理PMB条目,包括它们的创建、逐出和超时条件。
  2. 输出端口:

    • PMB条目控制: 诸如pfu_pmb_entry_create_dp_vld_xpfu_pmb_entry_create_gateclk_en_xpfu_pmb_entry_create_vld_xpfu_pmb_entry_evict_xpfu_pmb_entry_hit_pc_xpfu_pmb_entry_pc_vpfu_pmb_entry_ready_grnt_xpfu_pmb_entry_ready_xpfu_pmb_entry_type_ld_xpfu_pmb_entry_vld_x等输出负责管理PMB条目。这包括条目的创建、验证、逐出和就绪,以及确定条目是否为加载类型的预取。
  3. 特殊时钟:

    • lsu_special_clk 这可能是LSU或PFU的专用时钟,表明该单元具有特殊的时序要求。
  4. 功能:

    • 该模块似乎管理着预取请求在PMB中的生命周期。这包括确定何时创建新条目,何时条目有效或就绪,以及何时逐出条目。
    • 它还似乎处理特殊条件,如预取请求取消、PMB条目命中,以及管理特定于加载操作的条目。
    • 各种时钟相关控制的存在表明,该模块旨在考虑到功耗效率,可能使用时钟门控等技术。
parameter TIMEOUT_BW  = 8;
parameter PC_LEN      = 15;

//==========================================================
//                 Instance of Gated Cell  
//==========================================================
assign pfu_pmb_entry_clk_en = pfu_pmb_entry_vld
                              ||  pfu_pmb_entry_create_gateclk_en;
// &Instance("gated_clk_cell", "x_lsu_pfu_pmb_entry_gated_clk"); @39
gated_clk_cell  x_lsu_pfu_pmb_entry_gated_clk (
  .clk_in               (lsu_special_clk     ),
  .clk_out              (pfu_pmb_entry_clk   ),
  .external_en          (1'b0                ),
  .global_en            (cp0_yy_clk_en       ),
  .local_en             (pfu_pmb_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     ), @40
//          .external_en   (1'b0               ), @41
//          .global_en     (cp0_yy_clk_en      ), @42
//          .module_en     (cp0_lsu_icg_en     ), @43
//          .local_en      (pfu_pmb_entry_clk_en), @44
//          .clk_out       (pfu_pmb_entry_clk  )); @45

assign pfu_pmb_entry_create_clk_en = pfu_pmb_entry_create_gateclk_en;
// &Instance("gated_clk_cell", "x_lsu_pfu_pmb_entry_create_gated_clk"); @48
gated_clk_cell  x_lsu_pfu_pmb_entry_create_gated_clk (
  .clk_in                      (lsu_special_clk            ),
  .clk_out                     (pfu_pmb_entry_create_clk   ),
  .external_en                 (1'b0                       ),
  .global_en                   (cp0_yy_clk_en              ),
  .local_en                    (pfu_pmb_entry_create_clk_en),
  .module_en                   (cp0_lsu_icg_en             ),
  .pad_yy_icg_scan_en          (pad_yy_icg_scan_en         )
);

  1. 参数定义(Parameter Definition):

    • TIMEOUT_BWPC_LEN是定义的参数,分别表示超时带宽和程序计数器长度。
  2. 时钟使能逻辑(Clock Enable Logic):

    • pfu_pmb_entry_clk_en:这是一个用于控制PMB条目时钟门控的使能信号。当pfu_pmb_entry_vld(PMB条目有效)或pfu_pmb_entry_create_gateclk_en(创建PMB条目的时钟门控使能)其中任一为真时,该信号被置为真。
    • pfu_pmb_entry_create_clk_en:这是一个专门用于控制创建PMB条目的时钟门控的使能信号。
  3. 时钟门控单元实例化(Gated Clock Cell Instantiation):

    • 时钟门控单元gated_clk_cell被实例化两次,分别用于PMB条目的一般时钟(x_lsu_pfu_pmb_entry_gated_clk)和创建时钟(x_lsu_pfu_pmb_entry_create_gated_clk)。
    • 对于每个实例,输入时钟(lsu_special_clk)、全局使能(cp0_yy_clk_en)、模块使能(cp0_lsu_icg_en)和扫描使能(pad_yy_icg_scan_en)都被连接。
    • 每个时钟门控单元还有一个本地使能信号(local_en),分别为pfu_pmb_entry_clk_enpfu_pmb_entry_create_clk_en,用于控制对应的时钟输出(clk_out)。
  4. 功能和重要性:

    • 这些时钟门控逻辑有助于降低整个预取单元的功耗,通过仅在需要时使能时钟。
    • 这种时钟门控策略特别适用于性能敏感且功耗受限的设计,如高性能处理器的LSU部分。
//==========================================================
//                 Register
//==========================================================
//+-----------+
//| entry_vld |
//+-----------+
always @(posedge pfu_pmb_entry_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    pfu_pmb_entry_vld  <=  1'b0;
  else if(pfu_pmb_entry_pop_vld)
    pfu_pmb_entry_vld  <=  1'b0;
  else if(pfu_pmb_entry_create_vld)
    pfu_pmb_entry_vld  <=  1'b1;
end

//+----+
//| pc |
//+----+
always @(posedge pfu_pmb_entry_create_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    pfu_pmb_entry_pc[PC_LEN-1:0]  <=  {PC_LEN{1'b0}};
  else if(pfu_pmb_entry_create_dp_vld)
    pfu_pmb_entry_pc[PC_LEN-1:0]  <=  pipe_create_pc[PC_LEN-1:0];
end

//+----+------+
//| pref_type |
//+----+------+
always @(posedge pfu_pmb_entry_create_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    pfu_pmb_entry_type_ld  <=  1'b0;
  else if(pfu_pmb_entry_create_dp_vld)
    pfu_pmb_entry_type_ld  <=  ld_da_pfu_act_dp_vld;
end

//+-----+
//| cnt |
//+-----+
always @(posedge pfu_pmb_entry_all_pf_inst_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    pfu_pmb_entry_cnt       <=  1'b0;
  else if(pfu_pmb_entry_create_dp_vld)
    pfu_pmb_entry_cnt       <=  1'b0;
  else if(!pfu_pmb_entry_cnt  &&  pfu_pmb_entry_hit_pc)
    pfu_pmb_entry_cnt       <=  ~pfu_pmb_entry_cnt;
end

//+-------------+
//| timeout_cnt |
//+-------------+
always @(posedge pfu_pmb_entry_all_pf_inst_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    pfu_pmb_entry_timeout_cnt[TIMEOUT_BW-1:0] <=  {TIMEOUT_BW{1'b0}};
  else if(pfu_pmb_entry_create_dp_vld ||  pfu_pmb_entry_hit_pc)
    pfu_pmb_entry_timeout_cnt[TIMEOUT_BW-1:0] <=  {TIMEOUT_BW{1'b0}};
  else if(pipe_evict_cnt_vld &&  !pfu_pmb_entry_timeout_cnt_full)
    pfu_pmb_entry_timeout_cnt[TIMEOUT_BW-1:0] <=  pfu_pmb_entry_timeout_cnt[TIMEOUT_BW-1:0]
                                                  + {{TIMEOUT_BW-1{1'b0}},1'b1};
end

//+-------+
//| ready |
//+-------+
always @(posedge pfu_pmb_entry_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    pfu_pmb_entry_ready     <=  1'b0;
  else if(pfu_pmb_entry_create_dp_vld ||  pfu_pmb_entry_pop_vld)
    pfu_pmb_entry_ready     <=  1'b0;
  else if(pfu_pmb_entry_cnt &&  pfu_pmb_entry_hit_pc)
    pfu_pmb_entry_ready     <=  1'b1;
end

//+-------+
//| evict |
//+-------+
always @(posedge pfu_pmb_entry_clk or negedge cpurst_b)
begin
  if (!cpurst_b)
    pfu_pmb_entry_evict     <=  1'b0;
  else if(pfu_pmb_entry_create_dp_vld ||  pfu_pmb_entry_pop_vld ||  pfu_sdb_entry_evict_clr)
    pfu_pmb_entry_evict     <=  1'b0;
  else if(pfu_sdb_entry_evict_set)
    pfu_pmb_entry_evict     <=  1'b1;
end

预取单元(PFU)的预取缺失缓冲区(PMB)条目的寄存器定义和逻辑。包含多个始终块(always blocks),用于在不同条件下更新各种寄存器。让

  1. entry_vld(条目有效)寄存器:

    • 这个寄存器表示PMB条目是否有效。它在pfu_pmb_entry_clk的正边沿或cpurst_b的负边沿上更新。
    • 如果系统重置(cpurst_b为0),则将其清零。
    • 如果条目被弹出(pfu_pmb_entry_pop_vld为真),则将其清零。
    • 如果创建了新条目(pfu_pmb_entry_create_vld为真),则将其置为1。
  2. pc(程序计数器)寄存器:

    • 这个寄存器存储与PMB条目相关的程序计数器值。它在pfu_pmb_entry_create_clk的正边沿或cpurst_b的负边沿上更新。
    • 系统重置时,该寄存器被清零。
    • 如果有新的数据有效(pfu_pmb_entry_create_dp_vld为真),则更新为pipe_create_pc的值。
  3. pref_type(预取类型)寄存器:

    • 这个寄存器表明PMB条目的类型是否为加载(load)。它在pfu_pmb_entry_create_clk的正边沿或cpurst_b的负边沿上更新。
    • 系统重置时,该寄存器被清零。
    • 如果有新的数据有效,根据ld_da_pfu_act_dp_vld的值进行更新。
  4. cnt(计数)寄存器:

    • 这个寄存器用于跟踪某些事件的发生次数。它在pfu_pmb_entry_all_pf_inst_clk的正边沿或cpurst_b的负边沿上更新。
    • 在重置或新数据有效时清零。
    • 如果pfu_pmb_entry_hit_pc为真且cnt为假,则取反cnt的值。
  5. timeout_cnt(超时计数)寄存器:

    • 用于跟踪PMB条目的超时状态。它在pfu_pmb_entry_all_pf_inst_clk的正边沿或cpurst_b的负边沿上更新。
    • 在重置、新数据有效或命中时清零。
    • 如果pipe_evict_cnt_vld为真且pfu_pmb_entry_timeout_cnt_full为假,则增加计数器。
  6. ready(就绪)寄存器:

    • 表示PMB条目是否准备好进行某些操作。它在pfu_pmb_entry_clk的正边沿或cpurst_b的负边沿上更新。
    • 在重置、新数据有效或条目被弹出时清零。
    • 如果cntpfu_pmb_entry_hit_pc都为真,则将其置为1。
  7. evict(逐出)寄存器:

    • 表示PMB条目是否应该被逐出。它在pfu_pmb_entry_clk的正边沿或cpurst_b的负边沿上更新。
    • 在重置、新数据有效、条目被弹出或逐出清除时清零。
    • 如果设置逐出标志,则将其置为1。
//==========================================================
//                 pipe info select
//==========================================================
assign pipe_cmp_inst_vld = pfu_pmb_entry_type_ld
                           ? ld_da_pfu_pf_inst_vld
                           : st_da_pfu_pf_inst_vld;

assign pipe_cmp_pc[PC_LEN-1:0] = pfu_pmb_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;
//==========================================================
//                 Caucalate hit pc signal
//==========================================================
assign entry_hit_pc = pfu_pmb_entry_vld
                      && (pipe_cmp_pc[PC_LEN-1:0]
                         ==  pfu_pmb_entry_pc[PC_LEN-1:0]);

//for maintance
assign pfu_pmb_entry_hit_pc = entry_hit_pc
                              &&  pipe_cmp_inst_vld;

//for new inst create
assign pfu_pmb_entry_hit_pc_for_new = entry_hit_pc
                                      && !(pfu_pmb_entry_type_ld ^ ld_da_pfu_act_dp_vld);
//==========================================================
//                    Set/clr evict
//==========================================================
assign pfu_pmb_entry_timeout_cnt_full = (pfu_pmb_entry_timeout_cnt[TIMEOUT_BW-1:0]
                                         == pmb_timeout_cnt_val[TIMEOUT_BW-1:0]);

//if 
assign pfu_sdb_entry_evict_set  = pfu_pmb_entry_vld
                                  &&  !pfu_pmb_entry_ready
                                  &&  pipe_cmp_inst_vld
                                  &&  pfu_pmb_entry_timeout_cnt_full
                                  &&  !pfu_pmb_entry_hit_pc;

assign pfu_sdb_entry_evict_clr  = pfu_pmb_entry_hit_pc;

//==========================================================
//                Generate pop signal
//==========================================================
//st pref pop
assign pfu_pop_st_all = pfu_pmb_entry_vld
                        && !pfu_pmb_entry_type_ld 
                        && (!cp0_lsu_l2_st_pref_en || amr_wa_cancel);

//for timing
//when create_vld != create_dp,and the entry is at evict state
//pop entry preventing data path from being changed incorrectly
assign pfu_pmb_entry_evict_pop  = pfu_pmb_entry_vld
                                  && pfu_pmb_entry_evict
                                  && pfu_pmb_entry_create_dp_vld
                                  && !pfu_pmb_entry_create_vld; 

assign pfu_pmb_entry_pop_vld    = pfu_pmb_entry_ready_grnt
                                  ||  pfu_pmb_entry_evict_pop
                                  ||  pfu_pop_st_all
                                  ||  pfu_pop_all_part_vld;

预取缺失缓冲区(PMB)条目的逻辑,主要用于处理与预取相关的不同信号。

  1. 管线信息选择(Pipe Info Select):

    • pipe_cmp_inst_vld(管线比较指令有效):根据pfu_pmb_entry_type_ld(PMB条目类型)来选择是加载指令有效还是存储指令有效。
    • pipe_cmp_pc(管线比较程序计数器):同样根据PMB条目类型选择相应的程序计数器值,用于加载或存储。
  2. 计算命中程序计数器信号(Calculate Hit PC Signal):

    • entry_hit_pc:如果PMB条目有效且管线比较的程序计数器与PMB条目的程序计数器相等,则此信号为真。
    • pfu_pmb_entry_hit_pc:在entry_hit_pc的基础上,还需要管线比较指令有效。
    • pfu_pmb_entry_hit_pc_for_new:用于新指令创建时的命中检测。
  3. 设置/清除逐出(Set/Clear Evict):

    • pfu_pmb_entry_timeout_cnt_full:当PMB条目的超时计数器满时,此信号为真。
    • pfu_sdb_entry_evict_set:如果PMB条目有效、未准备好、管线指令有效、超时计数器满,且未命中程序计数器,则设置逐出。
    • pfu_sdb_entry_evict_clr:如果命中程序计数器,则清除逐出。
  4. 生成弹出信号(Generate Pop Signal):

    • pfu_pop_st_all:用于存储预取弹出。
    • pfu_pmb_entry_evict_pop:当存在时序问题时(如创建有效不等于创建数据路径有效,且条目处于逐出状态),弹出条目以防止数据路径被错误改变。
    • pfu_pmb_entry_pop_vld:结合多个条件生成最终的PMB条目弹出有效信号。
//==========================================================
//                 Generate interface
//==========================================================
//------------------input-----------------------------------
//-----------create signal--------------
assign pfu_pmb_entry_create_vld         = pfu_pmb_entry_create_vld_x;
assign pfu_pmb_entry_create_dp_vld      = pfu_pmb_entry_create_dp_vld_x;
assign pfu_pmb_entry_create_gateclk_en  = pfu_pmb_entry_create_gateclk_en_x;
//---------grnt/done signal-------------
assign pfu_pmb_entry_ready_grnt         = pfu_pmb_entry_ready_grnt_x;
//------------------output----------------------------------
//-----------entry signal---------------
assign pfu_pmb_entry_vld_x              = pfu_pmb_entry_vld;
assign pfu_pmb_entry_pc_v[PC_LEN-1:0]   = pfu_pmb_entry_pc[PC_LEN-1:0];
assign pfu_pmb_entry_ready_x            = pfu_pmb_entry_ready;
assign pfu_pmb_entry_evict_x            = pfu_pmb_entry_evict;
assign pfu_pmb_entry_type_ld_x          = pfu_pmb_entry_type_ld;
//-----------hit signal-----------------
assign pfu_pmb_entry_hit_pc_x           = pfu_pmb_entry_hit_pc_for_new;

预取缺失缓冲区(PMB)条目管理模块的接口生成部分。它主要负责将模块内部信号与外部或其他模块间的信号进行连接。代码分为两个主要部分:输入(input)和输出(output)。

  1. 输入信号(Input Signals):

    • pfu_pmb_entry_create_vld:表示创建PMB条目的有效性信号。
    • pfu_pmb_entry_create_dp_vld:表示创建PMB条目的数据路径有效性信号。
    • pfu_pmb_entry_create_gateclk_en:表示创建PMB条目时的时钟门控使能信号。
  2. 输出信号(Output Signals):

    • pfu_pmb_entry_vld_x:向外部表示PMB条目的有效性。
    • pfu_pmb_entry_pc_v:向外部提供PMB条目关联的程序计数器值。
    • pfu_pmb_entry_ready_x:向外部表示PMB条目是否准备就绪。
    • pfu_pmb_entry_evict_x:向外部表示PMB条目是否应被逐出。
    • pfu_pmb_entry_type_ld_x:向外部表示PMB条目的类型(是否为加载类型)。
    • pfu_pmb_entry_hit_pc_x:向外部表示新指令是否命中PMB条目的程序计数器。
  3. 功能和重要性:

    • 这部分代码是模块与外部环境交互的桥梁,确保内部状态和逻辑可以被外部模块正确读取和控制。
    • 通过这些接口,可以灵活地将ct_lsu_pfu_pmb_entry模块集成到更大的系统中,如C910的整个预取单元或更广泛的处理器架构。
    • 输入信号主要用于从外部接收控制和数据,而输出信号则用于向外部报告内部状态和决策。