当 uops 到达分配器时,在 PRF + Retirement RAT 方案(从 SnB 开始)中,分配器会在必要时咨询前端 RAT (F-RAT) 以重命名 ROB 条目(即,当写入架构寄存器时(例如rax
) 被执行)它在 ROB 的尾指针处分配给每个 uop。RAT 在 PRF 中保留一个空闲和正在使用的物理目标寄存器 (pdsts) 的列表。RAT 返回要使用的空闲物理寄存器编号,然后 ROB 将它们放在相应的条目中(在 RRF 方案中,分配器向 RAT 提供要使用的 pdsts;RAT 无法选择,因为 pdsts要使用的对象本来就位于 ROB 的尾部指针处)。RAT 还使用分配给它的寄存器更新每个体系结构寄存器指针,即它现在指向包含程序顺序中最新写入数据的寄存器。同时,ROB 在预留站 (RS) 中分配一个条目。在存储的情况下,它将在 RS 中放置一个存储地址 uop 和一个存储数据 uop。
一旦在 RS 中分配了这些微指令,RS 就读取其源操作数的物理寄存器并将它们存储在数据字段中,同时检查 EU 回写总线以查找与源 PR(物理寄存器)相关的 ROB 条目和回写数据,因为它们被写回 ROB。然后,RS 安排这些微指令在它们拥有所有已完成的源数据时分派到存储地址和存储数据端口。
然后发送 uop——存储地址 uop 进入 AGU,AGU 生成地址,将其转换为线性地址,然后将结果写入 SAB。我认为在 PRF+R-RAT 方案中商店根本不需要 PR(这意味着在此阶段不需要对 ROB 进行回写),但在 RRF 方案中,ROB 条目被迫使用它们的嵌入式 PR 和所有内容(ROB / RS / MOB 条目)均由其 PR 编号标识。PRF+R-RAT 方案的好处之一是 ROB 和飞行中微指令的最大数量可以扩展,而无需增加 PR 的数量(因为会有不需要任何指令的指令),并且所有内容都由 ROB 条目号解决,以防条目没有识别 PR。
存储数据直接通过存储转换器 (STC) 到达 SDB。一旦它们被调度,它们就可以被释放以供其他微指令重用。这可以防止更大的 ROB 受到 RS 大小的限制。
然后地址被发送到 dTLB,然后它将从 dTLB 输出的物理标签存储在 L1d 缓存的 PAB 中。
分配器已经为该 ROB 条目分配了 SBID 和 SAB / SDB 中的相应条目(STA+STD 微指令被微融合到一个条目中),它们缓冲来自 RS 的 AGU / TLB 中分派执行的结果。商店位于 SAB / SDB 中,对应的条目具有相同的条目号。(SBID),它将它们链接在一起,直到 MOB 被退休单元通知哪些存储已准备好退休,即它们不再是推测性的,并且在指向 ROB 索引的 ROB 条目重试指针的 CAM 匹配时通知它/ID 包含在 SAB / SDB 条目中(在每个周期可以引退 3 uop 的 uarch 中,有 3 个引退指针指向 ROB 中的 3 个最旧的未引退指令,并且只有 ROB 就绪位模式 0,0 ,1 0,1,1 和 1,1, 1 允许退出指针 CAM 匹配继续)。在这个阶段,他们可以在ROB中退休(称为'retire / complete local')并成为高级存储并用高级位(STA的Ae位,STD的De位)标记,并慢慢调度到L1d缓存,只要 SAB/SDB/PAB 中的数据有效。
L1d 缓存使用 SAB 中的线性索引对 tags 数组中的一个集合进行解码,该集合将包含使用线性索引的数据,并在下一个循环中使用与 SBID 具有相同索引值的相应 PAB 条目来比较物理带有集合中的标签的标签。PAB 的全部目的是允许对存储进行早期 TLB 查找以隐藏 dTLB 未命中的开销,而它们在等待成为高级时什么都不做,并允许在存储实际上仍处于推测状态时进行推测性页面遍历。如果存储是立即高级的,那么这个早期的 TLB 查找可能不会发生,它只是被分派,这就是 L1d 缓存将解码标记数组集并并行查找 dTLB 并绕过 PAB 的时候。记住虽然它可以 t 在执行 TLB 转换之前退出 ROB,因为可能存在 PMH 异常代码(页面错误,或在执行页面遍历时需要设置读取的访问/脏位),或者当 TLB 需要时出现异常代码通过它在 TLB 条目中设置的访问/脏位写入。完全有可能对存储的 TLB 查找始终发生在此阶段,并且不会与设置的解码并行执行(与加载不同)。当 PAB 中的 PA 变为有效(在 SAB 中设置了有效位)并且它在 ROB 中准备好退休时,存储变为高级。完全有可能对存储的 TLB 查找始终发生在此阶段,并且不会与设置的解码并行执行(与加载不同)。当 PAB 中的 PA 变为有效(在 SAB 中设置了有效位)并且它在 ROB 中准备好退休时,存储变为高级。完全有可能对存储的 TLB 查找始终发生在此阶段,并且不会与设置的解码并行执行(与加载不同)。当 PAB 中的 PA 变为有效(在 SAB 中设置了有效位)并且它在 ROB 中准备好退休时,存储变为高级。
然后它检查线路的状态。如果它是共享线路,则物理地址被发送到 RFO 中的一致性域(对于写入始终为 RFO),当它拥有线路所有权时,它将数据写入缓存。如果该行不存在,则为该缓存行分配一个 LFB,并将存储数据存储在其中,并向 L2 发送请求,然后 L2 将检查 L2 中行的状态并启动读取或 RFO环 IDI 接口。
当 RFO 完成并且 LFB 中的一个位表示它有权写入该行时,该存储变得全局可见,这意味着 LFB 将在下一次探听无效或驱逐时连贯地写回(或者在命中的情况下,当数据写入该行)。在发生未命中的情况下,在获取行之前将其写入 LFB 时,它不被视为全局可见(与在命中时退出的高级负载或 L1d 缓存分配 LFB 时的高级负载不同),因为可能存在由其他内核发起的其他 RFO,这些 RFO 可能在当前内核的请求之前到达 LLC 切片控制器,如果一个SFENCE
当前内核已基于此版本的“全局可见”退休而退休-至少这为处理器间中断提供了同步保证。全局可见的是,如果负载发生在另一个核心上,存储的数据将被另一个核心读取的那一刻,而不是在一小段时间之后,在此之前旧值仍将被其他核心读取的那一刻。存储由 L1d 高速缓存在分配 LFB 时完成(或在发生命中时将它们写入行)并从 SAB / SDB 退出。当所有先前的存储都从 SAB / SDB 中退出时,这就是store_address_fence
(not store_address_mfence
) 及其相关联store_data_fence
的可以分派到 L1d 的时间。序列化 ROB 指令流也更实用LFENCE
,而SFENCE
/MFENCE
不要因为它可能会导致 ROB 中的全局可见性延迟很长并且没有必要,这与立即退休的高级负载不同,所以为什么LFENCE
选择栅栏同时序列化指令流是有道理的。SFENCE/MFENCE
在所有分配的 LFB 成为全局可见之前,不要退休。
行填充缓冲区可以处于 3 种模式中的一种:读、写或写组合。我认为写行填充缓冲区的目的是将多个存储组合到同一行的数据到 LFB 中,然后当行到达时,用从 L2 获取的数据填充无效位。可能在这个阶段,它被认为已完成,因此写入在批量和一个周期之前得到满足,而不是等待它们被写入行中。只要它现在保证被写回缓存以响应另一个内核的 RFO。LFB 可能会一直保持分配状态,直到它需要被释放,从而可以稍微更快地满足对同一行的后续读取和写入。读取行缓冲区可以更快地服务读取未命中几个周期,因为它在行填充缓冲区中立即可用,但将其写入缓存行然后从中读取需要更长的时间。当内存是一个写组合缓冲区时分配USWC
类型并允许立即满足写入并立即将其全部刷新到 MMIO 设备,而不是具有多个 core->PCIe 事务并具有多个 PCIe 事务。WC 缓冲区还允许从缓冲区进行推测性读取。通常,在 UC 内存上不允许进行推测性读取,因为读取可能会改变 MMIO 设备的状态,而且读/写需要很长时间,以至于当它完成时,它将不再是推测性的,因此可能不值得额外交通?LFB 可能是 VIPT(VIPT/PIPT 在 intel 上是相同的,而 V 是 intel 上的线性地址);我想它可能有物理和虚拟标签来消除进一步的 TLB 查找,但是当物理页面迁移到新的物理地址时必须协商一些东西。