ct_lsu_pfu_gsdb
module ct_lsu_pfu_gsdb( cp0_lsu_icg_en, cp0_yy_clk_en, cp0_yy_dcache_pref_en, cpurst_b, forever_cpuclk, ld_da_iid, ld_da_pfu_act_vld, ld_da_pfu_pf_inst_vld, ld_da_pfu_va, pad_yy_icg_scan_en, pfu_gpfb_vld, pfu_gsdb_gpfb_create_vld, pfu_gsdb_gpfb_pop_req, pfu_gsdb_stride, pfu_gsdb_stride_neg, pfu_gsdb_strideh_6to0, pfu_pop_all_vld, rtu_yy_xx_commit0, rtu_yy_xx_commit0_iid, rtu_yy_xx_commit1, rtu_yy_xx_commit1_iid, rtu_yy_xx_commit2, rtu_yy_xx_commit2_iid, rtu_yy_xx_flush );
接口分析
-
控制和配置输入:
cp0_lsu_icg_en 、cp0_yy_clk_en 、cp0_yy_dcache_pref_en :这些控制信号可能来自控制/状态寄存器,指示是否启用了某些功能(如时钟门控或数据缓存预取)。cpurst_b :复位信号,用于初始化或重置模块的状态。
-
时钟和扫描输入:
forever_cpuclk 、pad_yy_icg_scan_en :这些信号提供时钟输入和测试目的的扫描控制。
-
加载数据输入:
ld_da_iid 、ld_da_pfu_act_vld 、ld_da_pfu_pf_inst_vld 、ld_da_pfu_va :这些信号可能与加载操作相关,表示指令 ID、预取动作的有效性、预取指令的有效性和加载操作的虚拟地址。
-
预取和全局预取缓冲区(GPFB)信号:
pfu_gpfb_vld 、pfu_gsdb_gpfb_create_vld 、pfu_gsdb_gpfb_pop_req :这些信号看起来与全局预取缓冲区的管理有关,指示预取条目的有效性、创建和弹出请求。
-
步幅检测输入:
pfu_gsdb_stride 、pfu_gsdb_stride_neg 、pfu_gsdb_strideh_6to0 :这些输入可能用于计算或确定预取操作的步幅。包含负步幅信号表明步幅检测逻辑考虑了正负步幅。
-
弹出和刷新信号:
pfu_pop_all_vld 、rtu_yy_xx_flush :这些输入可能用于在某些条件下(如流水线刷新)控制预取请求或条目的刷新或清除。
-
返回/提交输入:
rtu_yy_xx_commit0 、rtu_yy_xx_commit0_iid 、rtu_yy_xx_commit1 、rtu_yy_xx_commit1_iid 、rtu_yy_xx_commit2 、rtu_yy_xx_commit2_iid :这些信号可能与指令的提交阶段相关,可能用于根据某些指令的完成情况更新 GSDB 的状态。
功能概述
parameter IDLE = 4'b0000, GET_STRIDE = 4'b1001, CHECK_STRIDE = 4'b1010, MONITOR_STRIDE = 4'b1100; //========================================================== // Instance of Gated Cell //========================================================== assign pfu_gsdb_clk_en = pfu_gsdb_vld || pfu_gsdb_create_gateclk_en; // &Instance("gated_clk_cell", "x_lsu_pfu_gsdb_gated_clk"); @43 gated_clk_cell x_lsu_pfu_gsdb_gated_clk ( .clk_in (forever_cpuclk ), .clk_out (pfu_gsdb_clk ), .external_en (1'b0 ), .global_en (cp0_yy_clk_en ), .local_en (pfu_gsdb_clk_en ), .module_en (cp0_lsu_icg_en ), .pad_yy_icg_scan_en (pad_yy_icg_scan_en) ); // &Connect(.clk_in (forever_cpuclk ), @44 // .external_en (1'b0 ), @45 // .global_en (cp0_yy_clk_en ), @46 // .module_en (cp0_lsu_icg_en ), @47 // .local_en (pfu_gsdb_clk_en ), @48 // .clk_out (pfu_gsdb_clk )); @49 assign pfu_gsdb_pf_inst_vld_clk_en = pfu_gsdb_pf_inst_vld; // &Instance("gated_clk_cell", "x_lsu_pfu_gsdb_pf_inst_vld_gated_clk"); @52 gated_clk_cell x_lsu_pfu_gsdb_pf_inst_vld_gated_clk ( .clk_in (forever_cpuclk ), .clk_out (pfu_gsdb_pf_inst_vld_clk ), .external_en (1'b0 ), .global_en (cp0_yy_clk_en ), .local_en (pfu_gsdb_pf_inst_vld_clk_en), .module_en (cp0_lsu_icg_en ), .pad_yy_icg_scan_en (pad_yy_icg_scan_en ) );
全局步幅检测缓冲区(Global Stride Detection Buffer,简称GSDB)的时钟门控逻辑。它使用
时钟门控单元(Gated Clock Cell)
-
基本结构:
gated_clk_cell 是一个标准的时钟门控单元,用于根据不同的使能信号开启或关闭时钟信号。这对于动态电源管理非常重要,因为它允许在不需要时关闭模块的时钟,从而节省能源。
-
时钟使能信号(Clock Enable Signals):
pfu_gsdb_clk_en :这是GSDB的主要时钟使能信号,由pfu_gsdb_vld (GSDB有效性)或pfu_gsdb_create_gateclk_en (GSDB创建的额外门控时钟使能)控制。pfu_gsdb_pf_inst_vld_clk_en :专用于控制预取指令有效性的时钟使能信号。
-
时钟门控单元的连接:
- 每个时钟门控单元实例都连接了相同的输入和输出信号,但是使用了不同的本地使能(
local_en )信号。这些实例包括:x_lsu_pfu_gsdb_gated_clk 和x_lsu_pfu_gsdb_pf_inst_vld_gated_clk 。 - 共同的输入包括
forever_cpuclk (持续的CPU时钟),cp0_yy_clk_en (全局使能),cp0_lsu_icg_en (模块使能),和pad_yy_icg_scan_en (扫描使能,用于测试模式)。
- 每个时钟门控单元实例都连接了相同的输入和输出信号,但是使用了不同的本地使能(
功能和重要性
- 动态电源管理: 通过在不同的操作阶段启用或禁用时钟,这种方法可以显著减少处理器的功耗。
- 性能优化: 时钟门控还可以减少不必要的计算和内存访问,从而提高整体性能。
- 模块化设计: 使用标准的
gated_clk_cell 模块说明了代码的模块化设计,易于维护和更新。
//========================================================== // Register //========================================================== //+-------+ //| state | //+-------+ always @(posedge pfu_gsdb_clk or negedge cpurst_b) begin if (!cpurst_b) pfu_gsdb_state[3:0] <= IDLE; else if(pfu_pop_all_vld) pfu_gsdb_state[3:0] <= IDLE; else pfu_gsdb_state[3:0] <= pfu_gsdb_next_state[3:0]; end assign pfu_gsdb_vld = pfu_gsdb_state[3]; //+----------------+ //| newest_pf_inst | //+----------------+ always @(posedge pfu_gsdb_clk or negedge cpurst_b) begin if (!cpurst_b) pfu_gsdb_newest_pf_inst_vld <= 1'b0; else if(pfu_gsdb_create_dp_vld || pfu_gsdb_newest_pf_inst_flush_uncmit) pfu_gsdb_newest_pf_inst_vld <= 1'b0; else if(pfu_gsdb_vld && pfu_gsdb_pf_inst_vld) pfu_gsdb_newest_pf_inst_vld <= 1'b1; end always @(posedge pfu_gsdb_pf_inst_vld_clk or negedge cpurst_b) begin if (!cpurst_b) pfu_gsdb_newest_pf_inst_iid[6:0] <= 7'b0; else if(pfu_gsdb_newest_pf_inst_set) pfu_gsdb_newest_pf_inst_iid[6:0] <= ld_da_iid[6:0]; end always @(posedge pfu_gsdb_clk or negedge cpurst_b) begin if (!cpurst_b) pfu_gsdb_newest_pf_inst_cmit <= 1'b0; else if(pfu_gsdb_newest_pf_inst_set) pfu_gsdb_newest_pf_inst_cmit <= 1'b0; else if(pfu_gsdb_newest_pf_inst_cmit_set) pfu_gsdb_newest_pf_inst_cmit <= 1'b1; end //+-----------------------------+ //| gsdb to gpfb pop confidence | //+-----------------------------+ always @(posedge pfu_gsdb_clk or negedge cpurst_b) begin if (!cpurst_b) pfu_gsdb_pop_confidence[1:0] <= 2'b0; else if(confidence_reset) pfu_gsdb_pop_confidence[1:0] <= 2'b10; else if(confidence_sub_vld) pfu_gsdb_pop_confidence[1:0] <= pfu_gsdb_pop_confidence[1:0] - 2'b01; else if(confidence_add_vld) pfu_gsdb_pop_confidence[1:0] <= pfu_gsdb_pop_confidence[1:0] + 2'b01; end
寄存器定义和更新逻辑
-
状态寄存器(State Register):
- 在
pfu_gsdb_clk 的正边沿或cpurst_b 的负边沿更新。 - 在复位时设置为
IDLE 状态。 - 根据
pfu_pop_all_vld 信号或计算出的下一个状态pfu_gsdb_next_state 来更新状态。 pfu_gsdb_vld 标志由状态寄存器的最高位确定。
- 在
-
最新预取指令有效性(Newest Prefetch Instruction Validity):
- 在相同的时钟边沿更新。
- 在复位时清零。
- 在创建信号
pfu_gsdb_create_dp_vld 有效或刷新未提交时重置为零。 - 在 GSDB 有效且有预取指令时设置为一。
-
最新预取指令的指令ID(Instruction ID):
- 使用专用的
pfu_gsdb_pf_inst_vld_clk 时钟更新。 - 在复位时清零。
- 当设置信号
pfu_gsdb_newest_pf_inst_set 有效时,从ld_da_iid 获取指令ID。
- 使用专用的
-
最新预取指令提交标志(Newest Prefetch Instruction Commit Flag):
- 在
pfu_gsdb_clk 的正边沿更新。 - 在复位时清零。
- 当设置信号
pfu_gsdb_newest_pf_inst_cmit_set 有效时设置为一。
- 在
-
弹出置信度(Pop Confidence):
- 用于管理 GSDB 到 GPFB(全局预取缓冲区)弹出的置信度。
- 在复位时清零。
- 根据置信度重置、减少或增加信号来调整置信度。
功能和重要性
- 这些寄存器为 GSDB 提供了关键的状态信息,如当前状态、最新预取指令的有效性和ID、以及预取弹出的置信度。
- 通过精确地管理这些状态,可以更有效地处理预取逻辑,例如根据检测到的步幅模式调整预取策略。
- 这种状态管理对于优化预取策略、提高缓存效率和处理器性能至关重要。
//========================================================== // Instance addr cmp //========================================================== // &ConnRule(s/^entry_/pfu_gsdb_/); @125 // &Instance("ct_lsu_pfu_sdb_cmp","x_ct_lsu_pfu_gsdb_cmp"); @126 ct_lsu_pfu_sdb_cmp x_ct_lsu_pfu_gsdb_cmp ( .cp0_lsu_icg_en (cp0_lsu_icg_en ), .cp0_yy_clk_en (cp0_yy_clk_en ), .cpurst_b (cpurst_b ), .entry_addr0_act (pfu_gsdb_addr0_act ), .entry_addr_cmp_info_vld (pfu_gsdb_addr_cmp_info_vld ), .entry_check_stride_success (pfu_gsdb_check_stride_success), .entry_clk (pfu_gsdb_clk ), .entry_create_dp_vld (pfu_gsdb_create_dp_vld ), .entry_create_gateclk_en (pfu_gsdb_create_gateclk_en ), .entry_normal_stride (pfu_gsdb_normal_stride ), .entry_pf_inst_vld (pfu_gsdb_pf_inst_vld ), .entry_stride (pfu_gsdb_stride ), .entry_stride_keep (monitor_with_confidence ), .entry_stride_neg (pfu_gsdb_stride_neg ), .entry_strideh_6to0 (pfu_gsdb_strideh_6to0 ), .entry_vld (pfu_gsdb_vld ), .forever_cpuclk (forever_cpuclk ), .ld_da_iid (ld_da_iid ), .pad_yy_icg_scan_en (pad_yy_icg_scan_en ), .pipe_va (ld_da_pfu_va ), .rtu_yy_xx_commit0 (rtu_yy_xx_commit0 ), .rtu_yy_xx_commit0_iid (rtu_yy_xx_commit0_iid ), .rtu_yy_xx_commit1 (rtu_yy_xx_commit1 ), .rtu_yy_xx_commit1_iid (rtu_yy_xx_commit1_iid ), .rtu_yy_xx_commit2 (rtu_yy_xx_commit2 ), .rtu_yy_xx_commit2_iid (rtu_yy_xx_commit2_iid ), .rtu_yy_xx_flush (rtu_yy_xx_flush ) );
地址比较单元实例化
-
基本功能:
ct_lsu_pfu_sdb_cmp 单元可能用于比较存储在 GSDB 中的地址与当前处理的地址,以确定是否存在符合预取条件的步幅模式。
-
输入信号:
- 包括控制信号(如
cp0_lsu_icg_en ,cp0_yy_clk_en ),复位信号(cpurst_b ),以及 GSDB 特有的状态和配置信号(如pfu_gsdb_addr0_act ,pfu_gsdb_stride )。 - 还包括与处理器管道相关的信号(如
ld_da_iid ,ld_da_pfu_va ),以及与提交指令相关的信号(rtu_yy_xx_commit0 ,rtu_yy_xx_commit0_iid 等)。
- 包括控制信号(如
-
功能信号:
entry_stride_keep (传入的monitor_with_confidence )可能用于在确定步幅有效时保持当前步幅状态。entry_check_stride_success 可能表示步幅检测成功的情况。
-
时钟和时钟门控:
- 使用
forever_cpuclk 作为持续的时钟源,pad_yy_icg_scan_en 用于扫描测试。 - 时钟门控信号(如
entry_create_gateclk_en )控制模块的时钟流动,以优化能耗。
- 使用
功能和重要性
- 地址比较单元在步幅预取逻辑中非常关键,用于确定是否存在一致的访问模式,从而触发有效的预取操作。
- 它能够根据实时的访问模式和指令提交情况调整预取策略,优化预取效果。
- 此单元的实例化反映了处理器在预取策略实现中的复杂性和动态性。
//========================================================== // Generate state machine //========================================================== // &CombBeg; @134 always @( confidence_min or pfu_gsdb_normal_stride or pfu_gsdb_create_vld or pfu_gsdb_addr_cmp_info_vld or pfu_gpfb_vld or pfu_gsdb_state[3:0] or pfu_gsdb_check_stride_success) begin pfu_gsdb_next_state[3:0] = IDLE; case(pfu_gsdb_state[3:0]) IDLE: if(pfu_gsdb_create_vld) pfu_gsdb_next_state[3:0] = GET_STRIDE; else pfu_gsdb_next_state[3:0] = IDLE; GET_STRIDE: if(pfu_gsdb_addr_cmp_info_vld && pfu_gsdb_normal_stride) pfu_gsdb_next_state[3:0] = CHECK_STRIDE; else pfu_gsdb_next_state[3:0] = GET_STRIDE; CHECK_STRIDE: if(pfu_gsdb_addr_cmp_info_vld && pfu_gsdb_check_stride_success) pfu_gsdb_next_state[3:0] = MONITOR_STRIDE; else if(pfu_gsdb_addr_cmp_info_vld && !pfu_gsdb_check_stride_success) pfu_gsdb_next_state[3:0] = GET_STRIDE; else pfu_gsdb_next_state[3:0] = CHECK_STRIDE; MONITOR_STRIDE: if(pfu_gsdb_addr_cmp_info_vld && (!pfu_gsdb_check_stride_success && confidence_min || !pfu_gpfb_vld)) pfu_gsdb_next_state[3:0] = GET_STRIDE; else pfu_gsdb_next_state[3:0] = MONITOR_STRIDE; default: pfu_gsdb_next_state[3:0] = IDLE; endcase // &CombEnd; @165 end assign pfu_gsdb_state_is_get_stride = pfu_gsdb_state[0]; assign pfu_gsdb_state_is_check_stride = pfu_gsdb_state[1]; assign pfu_gsdb_state_is_monitor_stride = pfu_gsdb_state[2]; //========================================================== // Set ld inst //========================================================== assign pfu_gsdb_pf_inst_vld = pfu_gsdb_vld && ld_da_pfu_pf_inst_vld; assign pfu_gsdb_addr0_act = pfu_gsdb_newest_pf_inst_older_than_ld_da && (!pfu_gsdb_state_is_get_stride || ld_da_pfu_act_vld); //========================================================== // Generate create gsdb signal //========================================================== assign pfu_gsdb_create_vld = !pfu_gsdb_vld && cp0_yy_dcache_pref_en; assign pfu_gsdb_create_dp_vld = pfu_gsdb_create_vld; assign pfu_gsdb_create_gateclk_en = pfu_gsdb_create_vld; //========================================================== // pop confidence ctrl //========================================================== assign confidence_max = (pfu_gsdb_pop_confidence[1:0] == 2'b11); assign confidence_min = (pfu_gsdb_pop_confidence[1:0] == 2'b00); assign confidence_reset = pfu_gsdb_state_is_check_stride && pfu_gsdb_addr_cmp_info_vld && pfu_gsdb_check_stride_success; assign confidence_sub_vld = pfu_gsdb_state_is_monitor_stride && pfu_gsdb_addr_cmp_info_vld && !pfu_gsdb_check_stride_success && !confidence_min; assign confidence_add_vld = pfu_gsdb_state_is_monitor_stride && pfu_gsdb_addr_cmp_info_vld && pfu_gsdb_check_stride_success && !confidence_max; assign monitor_with_confidence = pfu_gsdb_state_is_monitor_stride && pfu_gpfb_vld && !confidence_min;
状态机生成逻辑
-
状态定义:
IDLE ,GET_STRIDE ,CHECK_STRIDE ,MONITOR_STRIDE 分别代表不同的状态,用于步幅检测和预取操作。
-
状态转换:
- 在
IDLE 状态下,如果收到创建信号pfu_gsdb_create_vld ,则转移到GET_STRIDE 状态。 - 在
GET_STRIDE 状态下,如果地址比较信息有效且为正常步幅,则转移到CHECK_STRIDE 状态。 - 在
CHECK_STRIDE 状态下,根据地址比较结果和步幅检测成功与否决定下一状态。 - 在
MONITOR_STRIDE 状态下,根据地址比较信息、步幅检测成功与否和置信度最小值决定是否回到GET_STRIDE 状态。
- 在
-
状态信号:
pfu_gsdb_state_is_get_stride ,pfu_gsdb_state_is_check_stride ,pfu_gsdb_state_is_monitor_stride 分别表示当前状态。
加载指令设置
pfu_gsdb_pf_inst_vld 和pfu_gsdb_addr0_act 根据当前状态和加载指令的相关信号设置。
创建 GSDB 信号
pfu_gsdb_create_vld ,pfu_gsdb_create_dp_vld ,pfu_gsdb_create_gateclk_en 控制 GSDB 的创建和时钟门控。
置信度控制
confidence_max ,confidence_min 分别表示置信度的最大和最小值。confidence_reset ,confidence_sub_vld ,confidence_add_vld 控制置信度的重置、减少和增加。monitor_with_confidence 表示在MONITOR_STRIDE 状态下并根据置信度最小值进行监控。
功能和重要性
- 状态机逻辑允许 GSDB 动态地响应内存访问模式的变化,优化预取策略。
- 置信度控制逻辑帮助 GSDB 判断预取操作的有效性,减少无效的预取操作。
- 创建和时钟门控逻辑确保 GSDB 在适当的时候被激活和维护,优化能耗。
//========================================================== // Maintain newest iid //========================================================== //-------------------------older---------------------------- // &Instance("ct_rtu_compare_iid","x_lsu_gsdb_newest_inst_cmp"); @212 ct_rtu_compare_iid x_lsu_gsdb_newest_inst_cmp ( .x_iid0 (pfu_gsdb_newest_pf_inst_iid[6:0] ), .x_iid0_older (pfu_gsdb_newest_pf_inst_iid_older_than_ld_da), .x_iid1 (ld_da_iid[6:0] ) ); // &Connect( .x_iid0 (pfu_gsdb_newest_pf_inst_iid[6:0]), @213 // .x_iid1 (ld_da_iid[6:0] ), @214 // .x_iid0_older (pfu_gsdb_newest_pf_inst_iid_older_than_ld_da)); @215 assign pfu_gsdb_newest_pf_inst_cmit_hit0 = {rtu_yy_xx_commit0,rtu_yy_xx_commit0_iid[6:0]} == {1'b1,pfu_gsdb_newest_pf_inst_iid[6:0]}; assign pfu_gsdb_newest_pf_inst_cmit_hit1 = {rtu_yy_xx_commit1,rtu_yy_xx_commit1_iid[6:0]} == {1'b1,pfu_gsdb_newest_pf_inst_iid[6:0]}; assign pfu_gsdb_newest_pf_inst_cmit_hit2 = {rtu_yy_xx_commit2,rtu_yy_xx_commit2_iid[6:0]} == {1'b1,pfu_gsdb_newest_pf_inst_iid[6:0]}; assign pfu_gsdb_newest_pf_inst_cmit_set = (pfu_gsdb_newest_pf_inst_cmit_hit0 || pfu_gsdb_newest_pf_inst_cmit_hit1 || pfu_gsdb_newest_pf_inst_cmit_hit2) && pfu_gsdb_newest_pf_inst_vld; assign pfu_gsdb_newest_pf_inst_older_than_ld_da = pfu_gsdb_newest_pf_inst_vld && (pfu_gsdb_newest_pf_inst_iid_older_than_ld_da || pfu_gsdb_newest_pf_inst_cmit); //-------------------newest_pf_inst_set--------------------- assign pfu_gsdb_newest_pf_inst_set = pfu_gsdb_vld && pfu_gsdb_pf_inst_vld && (!pfu_gsdb_newest_pf_inst_vld || pfu_gsdb_newest_pf_inst_older_than_ld_da); assign pfu_gsdb_newest_pf_inst_flush_uncmit = rtu_yy_xx_flush && !pfu_gsdb_newest_pf_inst_cmit; //========================================================== // Generate gpfb signal //========================================================== assign pfu_gsdb_gpfb_create_vld = pfu_gsdb_state_is_check_stride && pfu_gsdb_addr_cmp_info_vld && pfu_gsdb_check_stride_success; assign pfu_gsdb_gpfb_pop_req = pfu_gsdb_state_is_monitor_stride && pfu_gsdb_addr_cmp_info_vld && confidence_min && !pfu_gsdb_check_stride_success;
全局步幅检测缓冲区(GSDB)中维护最新指令ID(IID)的逻辑,以及如何生成与全局预取缓冲区(GPFB)相关的信号。
维护最新IID逻辑
-
IID比较:
- 使用
ct_rtu_compare_iid 实例比较当前最新的预取指令ID(pfu_gsdb_newest_pf_inst_iid )和加载指令的ID(ld_da_iid ),以确定哪个是较旧的。
- 使用
-
提交命中标志:
pfu_gsdb_newest_pf_inst_cmit_hit0 ,pfu_gsdb_newest_pf_inst_cmit_hit1 ,pfu_gsdb_newest_pf_inst_cmit_hit2 分别用于检测最新的预取指令ID是否与提交的指令ID匹配。
-
设置最新的预取指令提交标志:
pfu_gsdb_newest_pf_inst_cmit_set 在最新的预取指令ID与任一提交的指令ID匹配时设置。
-
最新预取指令ID是否早于加载指令:
pfu_gsdb_newest_pf_inst_older_than_ld_da 表示最新的预取指令ID是否早于加载指令的ID。
-
更新最新预取指令ID:
pfu_gsdb_newest_pf_inst_set 在当前状态有效且有新的预取指令ID时设置。
-
未提交的指令刷新:
pfu_gsdb_newest_pf_inst_flush_uncmit 在流水线刷新且最新的预取指令未提交时设置。
生成GPFB信号
-
创建GPFB条目:
pfu_gsdb_gpfb_create_vld 在CHECK_STRIDE 状态且地址比较信息有效并且步幅检测成功时设置。
-
GPFB弹出请求:
pfu_gsdb_gpfb_pop_req 在MONITOR_STRIDE 状态且地址比较信息有效、置信度最小且步幅检测不成功时设置。
功能和重要性
- 维护最新的预取指令ID对于确保GSDB准确地跟踪程序的内存访问模式至关重要。
- 提交命中和未提交刷新逻辑有助于及时更新GSDB的状态,确保预取策略与程序执行同步。
- 生成GPFB信号的逻辑确保在适当的时机创建和弹出GPFB条目,优化预取操作的效率和有效性。