DATA_FC 方法以牺牲逻辑为代价,提供了最精细的分配粒度。就像使用 PACKET_FC 和 RCB_FC 时一样,从 CPLH_PENDING 和 CPLD_PENDING(复位时加载,含零位)这两个寄存器开始。
- 当用户应用需发送非转发请求时,判定可能需要的 CplH 和 CplD 信用值的潜在数值:
- NP_CplH = ceiling[((Start_Address mod RCB) + Request_Size) / RCB]
- NP_CplD = ceiling[((Start_Address mod 16 bytes) + Request_Size) / 16 字节](I/O 写入除外,它会返回零数据)
- 检查以下项:
- CPLH_PENDING + NP_CplH < Total_CplH
- CPLD_PENDING + NP_CplD < Total_CplD
- 如果这两个不等式均成立,则发射非转发请求,将 CPLH_PENDING 增大 NP_CplH,并将 CPLD_PENDING 增大 NP_CplD。
- 每个传入完成包开始时,或者如果该完成包始于或跨某个 RCB 但并未止于此 RCB,则 CPLH_PENDING 减小 1。跨 RCB 数量可按如下方式计算:
- RCB_CROSSED = ceiling[((Lower_Address mod RCB) + Length) / RCB]
“Lower_Address”和“Length”字段均可从完成报头进行解析。或者,也可以在每个传入完成包起始位置加载含 Lower_Address 的寄存器 CUR_ADDR,按相应的 DW 或 QW 递增,然后一旦 CUR_ADDR 发生翻滚,即可对 RCB 进行计数。
- 每个传输完成包开始时,或者如果该完成包始于或跨自然对齐的信用值边界,则 CPLD_PENDING 减小 1。跨信用值边界次数计算方式如下:
- DATA_CROSSED = ceiling[((Lower_Address mod 16 B) + Length) / 16 B]
或者,也可以在每个传入完成包起始位置加载含 Lower_Address 的寄存器 CUR_ADDR,按相应的 DW 或 QW 递增,然后一旦 CUR_ADDR 滚过每个 16 字节地址边界,即可对 RCB 进行计数。此方法的资源浪费最少,但所需用户逻辑最多。如果需要更精细的粒度,可以将 Total_CplD 值按 2 或 4 比例进行缩放,以分别得到完成 QWORD 或 DWORD 数量,并对数据计算方式进行相应调整。