The Core Front-End: Instruction Fetch
处理器核心前端:指令拾取
处理器在执行指令之前,必须先装载指令。指令会先保存在L1缓存的I-cache(Instruction-cache)指令缓存当中,Nehalem的指令拾取单元使用128bit带宽的通道从I-cache中读取指令。这个I-cache的大小为32KB,采用了4路集合关联,在后面的存取单元介绍中我们可以得知这种比Core更少的集合关联数量是为了降低延迟。
为了适应超线程技术,RIP(Relative Instruction Point,相对指令指针)的数量也从一个增加到了两个,每个线程单独使用一个。
The Core Front-End: Instruction Fetch
指令拾取单元包含了分支预测器(Branch Predictor),分支预测是在Pentium Pro处理器开始加入的功能,预测如if then这样的语句的将来走向,提前读取相关的指令并执行的技术,可以明显地提升性能。指令拾取单元也包含了Hardware Prefetcher,根据历史操作预先加载以后会用到的指令来提高性能,这会在后面得到详细的介绍。
当分支预测器决定了走向一个分支之后,它使用BTB(Branch Target Buffer,分支目标缓冲区)来保存预测指令的地址。Nehalem从以前的一级BTB升级到了两个级别,这是为了适应很大体积的程序(数据库以及ERP等应用,跳转分支将会跨过很大的区域并具有很多的分支)。Intel并没有提及BTB详细的结构。与BTB相对的RSB(Return Stack Buffer,返回堆栈缓冲区)也得到了提升,RSB用来保存一个函数或功能调用结束之后的返回地址,通过重命名的RSB来避免多次推测路径导致的入口/出口破坏。RSB每个线程都有一个,一个核心就拥有两个,以适应超线程技术的存在。
指令拾取单元使用预测指令的地址来拾取指令,它通过访问L1 ITLB里的索引来继续访问L1I Cache,128条目的小页面L1 ITLB按照两个线程静态分区,每个线程可以获得64个条目,这个数目比Core 2的少。当关闭超线程时,单独的线程将可以获得全部的TLB资源。除了小页面TLB之外,Nehalem还每个线程拥有7个条目的全关联(Full Associativity)大页面ITLB,这些TLB用于访问2M/4M的大容量页面,每个线程独立,因此关闭超线程不会让你得到14个大页面ITLB条目。
指令拾取单元通过128bit的总线将指令从L1I Cache拾取到一个16Bytes(刚好就是128bit)的预解码拾取缓冲区。128位的带宽让人有些迷惑不解,Opteron一早就已经使用了256bit的指令拾取带宽。最重要的是,L1D和L1I都是通过256bit的带宽连接到L2 Cache的。
由于一般的CISC x86指令都小于4Bytes(32位x86指令;x86指令的特点就是不等长),因此一次可以拾取4条以上的指令,而预解码拾取缓冲区的输出带宽是6指令每时钟周期,因此可以看出指令拾取带宽确实有些不协调,特别是考虑到64位应用下指令会长一些的情况下(解码器的输入输出能力是4指令每时钟周期,因此32位下问题不大)。
75%的x86指令小于4Bytes。
指令拾取结束后会送到18个条目的指令队列,在Core架构,送到的是LSD循环流缓冲区,在后面可以看到,Nehalem通过将LSD移动后更靠后的位置来提高性能。