在x86处理器系统中,存储器指令大体可以分为F(reg, reg)[1],F(reg, mem)和F(mem, reg) 三大类。在这些指令中,第1个Operand为目标操作数也可以为源操作数,第2个Operand只能为源操作数。与LSU部件直接相关的指令为F(reg, mem)和F(mem, reg)。后一类指令的处理相对较为复杂,该类指令需要首先进行存储器读,进行某种运算后,再次进行存储器写,即Read-Modify-Write μop。在Opteron微架构中,浮点和SSE指令的存储器读写依然需要通过Integer指令流水,为简化起见,下文不再讨论浮点和SSE指令的存储器读写指令。

一条存储器指令的执行需要使用AGU,ALU和LSU三大部件。AGU,ALU将和LSU部件协调流水作业,最终完成一次存储器读写操作。L1 Cache的Load-Use Latency参数的计算是从存储器指令进入LSQ开始计算。为了实现指令流水的并发高速运转,在AGU和ALU中也具备多级流水结构。存储器指令在通过ALU,AGU与LSU部件的过程中存在相互依赖关系,如图4‑3所示。

我们分别讨论F(reg,mem)指令和F(mem, reg)指令的执行过程。在RS(Reservation Station)等待的F(reg, mem)指令,当所需的Operands Available后首先Launch到AGU部件,并在地址计算完毕后,将结果发送到LSU部件。但是存储器访问μop是同时进入到AGU和LSU部分中的,只有LSU需要等待AGU的计算结果。

在LSU部件从存储器子系统中获得最终数据之后,将其送给ALU,并最终完成指令的执行。F(mem, reg)指令的执行过程与此相近,只是需要在LSQ中经历两次等待过程,第1次是等待ALU计算的结果,第2次等待Store μop的commit将结果最终写入Cache。F(mem, reg)进行存储器读时的操作与F(reg, mem)一致。

AGU和ALU Pipeline的执行过程较易理解,本篇对此不做进一步的说明。Opteron LSU的设计使用Tag和Data总线分离的方式。Scheduler在监听Result Bus时,发现对应的Tag有效时即可启动LSU和ALU的μop,不必等待Data总线,通常情况下Tag bus上的数据先于Result Bus一个cycle,以Overlap不同的流水阶段。在Opteron微架构中,1个Cycle,可以Launch一个ALU和一个AGU微操作。如图4‑3所示,这两个操作显然没有对应关系。

LSU部件负责与其下的存储器子系统进行数据交互,也是图4‑3所示三大部件中最为复杂的一个部件。在Opteron微架构中,LSU由两个部件组成,分别是LS1和LS2。其中LS1中含有12个Entry,LS2中含有32个Entry,共44个Entry[6]。

LS1和LS2也被分别称为Pre-Cache和Post-Cache Load/Store Unit,绝大多人会认为LS1用于访问L1 Cache,而LS2用于访问L2 Cache。这一说法源自AMD的软件优化手册[73],这似乎是一个权威说法,也在某种程度上善意地误导着读者。这一说法非但并不准确,在某种程度上甚至是错误的。Opteron LSU的结构示意如图4‑4所示。

在Opteron微架构中,一条存储器读写指令在被Dispatch到Integer Scheduler的同时,也会被Dispatch到LS1的相应Entry中等待。LS1通过监听AGU的Tag总线获得必要的信息后,开始真正意义上的执行。这些必要的信息包括,LS1所需要的地址是否能够在下一拍有效,将使用哪一个AGU产生的地址。LS1使用Tag总线的信息虽然不能用于L1 Cache的Probe操作,却可以实现AGU和LSU的流水执行。

Opteron微架构分离Tag和Data总线是利用流水进行加速的技巧,将AGU的执行分解为两个步骤,以最大化AGU与LSU流水部件间的Overlap。除了AGU部件分离的Tag和Data总线,LSU和ALU也进行了这样的总线分离。

在LS1中的指令在下一拍从Data总线中获得地址后执行,由上文所述,Opteron微架构的L1 Cache具有两个端口,当所访问的数据间不发生冲突的前提下,LS1率先处理最先进入队列的两条存储器读写指令,并将其转交给L1 CacheController做进一步处理。

无论是存储器读还是存储器写操作,L1 CacheController都需要首先进行Probe操作。读操作发起的Cache Read Probe操作将带回数据。写操作发起的Cache Probe操作,也被称之为Probe-before-Write。进行这个Probe操作之前,需要准备好待写的Cache Block,Probe操作返回时将会带回数据,而当且仅当存储器写指令获得最终数据而且进行Commit操作之后,才能将数据真正写入。由于写入的数据在多数情况不能占满一个完整的Cache Block,此时需要和Probe操作带回的数据进行Merge后进行写入操作。

写操作的实现细节比上文描述的过程复杂得多。即便我们抛离了与Store Ordering相关的诸多和Memory Consistency的概念和各类Cache Write策略,没有考虑在Cache Write Hit时使用的Write-Through,Write-Back和Write-Once策略,没有考虑Cache Write Miss时使用的Write-Allocate,Write-Validate和Write-Around策略。

我们首先考虑在进行Write Probe操作之前,在Cache流水线准备好一个未使用的Cache Block,到从存储器子系统获得数据后真正写入数据的这段延时。我们首先关注这个刚刚准备好的Cache Block在此时使用的状态信息,似乎MOESIF这几个状态都无法准确描述此时的这条Cache Block所处的状态。

MOESIF这些状态位仅是Cache Controller所使用的简单得不能再简单的状态位,仅是一个Stable状态,是Cache Block诸多状态中一个子集。一个Cache Block中还含有其他状态位,更为复杂的处理Race Condition的Transient状态位。在Cache与Cache间的总线中包含着诸多Coherence Message和各类Bus Transaction。如果进一步考虑多级Cache的组成结构后,Cache ControllerFSM使用的状态位和流程迁移的复杂程度令人叹为观止。

其次我们需要考虑存储器写操作在等待最终Commitment时所带来的延时。如上文所述,如果存储器读指令的访问结构在LSQ中命中时,微架构将不会读取L1或者更高层次的Cache,从而充分利用了这个延时。这个延时可以带来的另外一个好处,由于后续的存储器读指令可能需要读取相同的Cache Block,此时也要进行Probe Cache操作。在这个延时中,这两个Probe操作可以合并,从而在一定程度上降低了总线的Traffic。这些优化手段提高了存储器读写指令的效率,也带来了较大的系统复杂度。

在Opteron LS1中的存储器读或者写操作,如果没有及时完成,例如存储器写指令没有及时地进行Commitment,将导致存储器写操作无法在LS1中完成,此外如果存储器读没有在L1 Cache中命中也无法及时完成时,这些在LS1中的指令都将进入LS2,从而为后续的存储器指令预留空间。这些预留可以为更多可能在L1 Cache Hit的存储器操作并发执行。从这个角度分析可以发现LS1主要用于Cache Hit的处理。

在LS2中的所有存储器读写指令,包括Load,Store和Load-Store指令将继续监听Cache Probe的结果,当发生Cache Miss时,需要将存储器读写请求转发给BUI(Bus InterfaceUnit)部件,BUI部件将根据需要从L2 Cache或者主存储器中获得最终数据。即LS2用于处理Cache Miss时,需要较长时间的存储器读写指令。

在Opteron微架构中,采用了Non-Blocking Cache的实现方式,为每一条Miss存储器请求添加了一个MAB Tag(Missed Address BufferTag)之后再发送给BUI部件,同时为这些Miss请求在LS2中设置了Fill Tag。当Probe操作的数据从L2 CacheController返回时,其MAB Tag将与在LS2中的Fill Tag进行比较,进一步确认数据是否有效,并将LS2中的存储器指令的状态从Miss更新为Hit。

Store指令将在LS2中停留更长的时间,直到该指令从流水线中按序退出后,才能将数据写入到存储器子系统中。当发生Misprediction或者Exception,微架构可以丢弃在LS2中的暂存的Store指令。只要Store指令没有离开LSU,都可以丢弃,当然这种丢弃是条件的,并不是随意丢弃。

在Opteron微架构中,L1和L2 CacheController将与LSU共同完成一次存储器读写操作。在L1和L2 Controller中含有各类Buffer,和连接这些Buffer的通路。一次存储器访问指令,在通过指令流水后,将首先到达LSU,并由LSU将其请求转发至L1和L2 CacheController,并由这些Cache Controller完成剩余的工作。

Cache Controller需要在保证Memory Consistency的前提下,将数据重新传递给LSU,完成一次存储器读写的全过程。在一个微架构中,Cache Controller是一个较为复杂的功能,由其管理的Cache流水线是整个微架构的精华。


[1] 许多论文书籍认为F(reg,reg)指令不属于存储器指令。

4.2 存储器读写指令的发射与执行2相关推荐

  1. 【计算机组成原理】实验4:存储器读写实验

    实验内容 一.实验原理 存储器是计算机的存储部件,用于存放程序和数据.存储器是计算机信息存储的核心,是计算机必不可少的部件之一,计算机就是按存放在存储器中的程序自动有序不间断地进行工作. 本系统从提高 ...

  2. ARM:特殊功能寄存器、Load/Store内存读写指令、栈操作指令

    1.特殊功能寄存器读写指令 msr -->>将普通寄存器中的数据写到特殊寄存器中 mrs -->>将特殊寄存器中的数据写到普通寄存器中 注:特殊寄存器 cpsr 的读写访问只能 ...

  3. 寄存器内存读写指令(二) —— 多寄存器读写 LDM / STM

    有的时候,CPU可能会遇到 a++; b++; c++,这个时候为了提升效率,CPU可能会一次将多个寄存器里的变量保存到内存中.这个时候之前介绍的 LDR / STR 指令虽然也能实现,但只能操作一个 ...

  4. Debug的T命令在执行修改寄存器SS 的指令时,下一条指令也紧接着被执行。

    为什么会这样呢?要想彻底说清楚这里面的来龙去脉,在这里还为时过早,因为这涉及我们在以后的课程中要深入研究的内容:中断机制,它是我们后半部分课程中的一个主题.现在我们只要知道这一点就可以了: Debug ...

  5. Java调用linux指令工具类,直接执行cmd,执行grep指令返回结果,执行sed追加指令,hdfs下载指令,获取文件行数

    Java调用linux指令工具类,直接执行cmd,执行grep指令返回结果,执行sed追加指令,hdfs下载指令,获取文件行数 问题背景 LinuxUtils工具类 Lyric:梦想挟带眼泪 问题背景 ...

  6. 软中断指令int $0x80的执行过程

    软中断指令int $0x80的执行过程 它是陷阱类(编程异常)事件,因此它与异常响应过程一样. 将IDTi(i=128)中段选择符(0x60,内核代码就是这个表项)所指GDT中的内核代码段描述符取出, ...

  7. DSP关于存储器读写、IO读写时序图的注意点

    这里的存储器图不涉及插入等待周期. IO设备的图可以自行减去插入等待周期,然后观察. 存储器读读写 存储器写写读 I/O设备读写操作

  8. 【微机原理作业】8086存储器读写实验

    一.作业要求 利用 2764 和 6264 在 8086 最小模式下扩展 16K ROM 和 16K RAM ,对其地址进行读写(注意数据的偶对齐). 将2764某一段数据读出并写入6264,详细展示 ...

  9. 存储器读写c语言程序,单片机IIC接口存储器AT24C04的读写和显示程序(详细注释)...

    //----------------------------------------------------------------- //        名称: I2C接口存储器AT24C04读写与 ...

  10. 计算机组成课程设计之二——微程序控制的存储器读写系统设计

    如果部分电路图显示不清楚可放大页面后查看 设计要求 课程设计平台为设计环境提供了容量为256×8的随机存储器.在此基础上,设计相应的外围电路和时序对随机存储器进行读写操作.结构框图如下图所示,设计完成 ...

最新文章

  1. 杭电1175简单搜索 连连看
  2. 10.PHP加密相关
  3. Java 面试经典题解析:谈谈你对 Java 平台的理解?
  4. 如何写出优雅的API
  5. linux内核态real cred,Linux内核实验报告——实验5.doc
  6. 100~200之间的素数(及其四个优化方案)
  7. 启动linux的rpc服务的命令
  8. Sqlserver2012 根据数据库mdf文件生成log文件,解决无法附加mdf文件
  9. php 提取字段为key,从一个serialize过的array的字符串中取出中取对应KEY的value
  10. C++版本 ORM 访问数据库之ODB 的oracle Demo测试(二)
  11. POJ1742Coins
  12. 一个文章单词分析作业
  13. efi文件错误服务器崩溃,[转自百度]关于系统安装时候弹出提示winload.efi文件损坏...
  14. SVN不同分支代码合并
  15. 武汉大学计算机学院成绩单,2018年武汉大学各学院总评成绩计算公式汇总
  16. (5)树莓派+1个USB有线网卡+1个USB无线网卡做路由器
  17. Go 依赖注入库dig
  18. NAT 穿透是如何工作的
  19. COVID-19 paper
  20. 数据库连接池是什么?

热门文章

  1. 数独基本规则_独数游戏,数独题目大全
  2. POJ 1061 青蛙的约定
  3. Android之sdcard保存数据
  4. 千锋深圳Java培训分享:MySQL详细知识点
  5. 《黑客帝国 THE MATRIX》——当你生活在代码的虚拟世界中
  6. 安卓手机格式化怎么弄_安卓手机格式化教程、安卓手机怎么格式化-百度经验...
  7. sklearn 学习笔记 —— Nearest Neighbors
  8. 机器学习(二)--- KNN(K-Nearest Neighbors)
  9. 三角形周长最短问题_一次函数动点问题:求三角形周长最小值
  10. 苹果CMSv10插件/本地解析播放器-videojs解析 整合苹果cmsV10程序