微处理器设计/寄存器文件
寄存器是 CPU 内部用于保存数据和地址的临时存储位置。
寄存器文件是包含微处理器所有通用寄存器的组件。一些 CPU 也将 PC 和状态寄存器等特殊寄存器置于寄存器文件中。其他 CPU 将它们分开。
在设计 CPU 时,有些人区分“架构特征”和“实现细节”。“架构特征”是程序员可见的部分;如果有人制作了一个新系统,其中任何这些部分与旧的 CPU 不同,那么突然之间所有旧的软件将无法在新 CPU 上运行。“实现细节”是那些虽然我们投入了更多时间和精力来使其正常工作,但可以制作一个新系统,该系统有不同的实现方式,并且仍然保持软件兼容性——有些程序可能运行得快一点,其他程序可能运行得慢一点,但它们都产生与早期机器上相同的结果。
程序员可见的寄存器集对软件兼容性的影响比数据路径的任何其他部分都大,也许比整个计算机中的任何其他部分都大。程序员可见的寄存器集的架构特征是寄存器的数量、每个寄存器中的位数以及寄存器的逻辑组织。汇编语言程序员喜欢拥有许多寄存器。早期的微处理器寄存器数量非常少,受芯片面积的限制。如今,许多芯片有空间容纳大量寄存器,因此程序员寄存器的数量受其他限制:更多的程序员可见寄存器需要更大的操作数字段。更多的程序员可见寄存器需要在中断或上下文切换时花费更多时间保存和恢复寄存器。软件兼容性要求保持完全相同的程序员可见寄存器数量、大小和组织。汇编语言程序员喜欢“扁平”的地址空间,其中(虚拟)内存中任何位置的完整地址都适合单个地址寄存器。因此,架构师想要的(虚拟)内存数量为每个地址寄存器设置了最小宽度。 [1]
“通用寄存器”的概念——一组寄存器,其中任何一个寄存器可以在不同的时间充当堆栈指针、索引寄存器、累加器、程序计数器等,是在 1971 年左右发明的。 [2]
虽然寄存器可以用一组触发器寄存器来实现,但基于 SRAM 的全定制寄存器文件使用更少的面积和功耗。 [3][4]
许多单芯片 CPU 的整体性能受寄存器文件读取操作的速度限制。 [3]
一个简单的寄存器文件是一组寄存器和一个译码器。寄存器文件需要一个地址和一个数据输入。
然而,这个简单的寄存器文件在现代处理器设计中并不实用,因为有些情况下我们不想将新值写入寄存器。此外,我们通常希望在一个周期内同时读取两个值并将一个值写回。考虑以下等式
为了执行此操作,我们想要从寄存器文件读取两个值,A 和 B。我们还有一个结果,我们希望在操作完成时将其写回寄存器文件。对于我们不想将任何值写入寄存器文件的情况,我们添加一个称为Read/Write的控制信号。当控制信号为高电平时,数据被写入寄存器,当控制信号为低电平时,没有新值被写入。
在这种情况下,为我们指定第三个地址端口以用于写地址可能是有利的。
许多人选择为其流水线微处理器使用 3 端口寄存器文件,以便它可以每个周期执行这样的 ALU 指令。每个周期 CPU 从寄存器文件中读取两个值以准备根据一条指令对其进行操作,同时 CPU 将来自先前指令的某些结果写入寄存器文件中的其他寄存器。(超标量处理器 和 VLIW 需要具有 6 个或更多端口的寄存器文件)。
(具有操作数转发的微处理器是否会在同一个时钟周期内从一个寄存器读取并写入同一个寄存器?)
全定制寄存器文件通常从 SRAM 设计开始。与 SRAM 芯片一样,基于 SRAM 的寄存器文件为每个端口包含一对差分位线——但与单个 SRAM 读/写端口不同,寄存器文件通常至少有一个专用的写端口和几个专用的读端口。典型的寄存器文件在每个指令周期重复此过程:首先,在预充电阶段,每个读端口的一对差分位线的两条位线彼此短路并充电到 Vdd/2。然后,字线将一个位单元连接到这些线——稍微使这些长位线上的电荷失去平衡。最后,CPU 使感应放大器使轻微的失衡放大到正常的数字逻辑电平。 [5][3][6][4]
考虑机器字非常小的情况,因此寄存器的可用地址空间非常有限。如果我们有一个只能容纳 2 位寄存器地址的机器字,我们只能寻址 4 个寄存器。但是,寄存器文件实现起来很小,所以我们有足够的空间容纳 32 个寄存器。有几个解决方案可以解决这个难题——几种通过使用多个寄存器来提高性能的方法,即使我们没有足够的位数在指令字中直接寻址它们。
其中一些解决方案包括
- 特殊用途寄存器,它们始终用于某些特定指令,因此该指令不需要任何位来指定该寄存器。
- 在几乎所有 CPU 中,程序计数器 PC 和状态寄存器都与其他寄存器不同,有自己的一组特殊指令。
- 将寄存器分成两组,“地址寄存器”和“数据寄存器”,因此使用地址的指令需要足够的位来选择所有地址寄存器中的一个,这比选择所有寄存器中的一个少 1 位。
- 如 SPARC 上的寄存器窗口
[1] 和
- 使用“寄存器组”。
术语“寄存器组”在两种不同的意义上使用。 [7] 一些 CPU 具有多个不同的寄存器组(或“组”),而不是一个单一的寄存器文件。
一种“寄存器组”类似于(主内存) 银行切换。由于这种类型对汇编语言程序员可见,在本节中,我们将称之为“架构寄存器组”。其他类型的“寄存器组”允许 CPU 运行与单组实现完全相同的软件(对汇编语言程序员不可见),因此在本节中,我们将称之为“微架构寄存器组”——这些实现选项与单片寄存器文件实现相比具有各种优点。
考虑这样一种情况,机器字长非常小,因此寄存器可用的地址空间非常有限。如果机器字长只能容纳 2 位寄存器地址,那么我们只能寻址 4 个寄存器。然而,寄存器文件实现起来很小,所以我们有足够的空间存放 32 个寄存器。解决这个难题的方法是使用一个**寄存器组**,它由多个寄存器文件组合在一起。
一个**寄存器组**包含多个寄存器文件或 *页*。同一时间只允许一个页处于活动状态,并且在 ISA 中添加了一些额外的指令来在可用寄存器页之间切换。数据值只能写入和读取当前活动的寄存器页,但是可以存在将数据从一个页移动到另一个页的指令。
如本图所示,灰色方框表示当前页,可以上下移动寄存器组上的页。
如果寄存器组有 *N* 个寄存器,而一个页只能显示 *M* 个寄存器(其中 *N* > *M*),我们可以用两个值分别表示寄存器地址,分别为 *n* 和 *m*。我们可以将这些值定义为
换句话说,*n* 和 *m* 分别是寻址 *N* 和 *M* 个寄存器所需的位数。我们可以将地址分解为一个单独的值,如下所示
其中 *p* 是为指定当前寄存器页保留的位数。从该图中可以看出,当前寄存器地址只是页地址和寄存器地址的串联。
微架构寄存器组
[edit | edit source]有几种技术可以将物理寄存器分成多个物理寄存器文件(“组”),并使用控制逻辑使整个 CPU 在软件上与同一 CPU 架构的其他实现兼容,这些实现只使用一个单一的整体寄存器文件。在现代高性能 CPU 中,这些技术用于构建软件兼容的 CPU,这些 CPU 运行速度更快、功耗更低、面积更小,而不是用单个传统的多分支寄存器文件实现相同的 CPU 架构。[8][9]
像 POWER2、Alpha 21264 和 Alpha 21464 一样,复制整个寄存器文件[8][7] 是微架构寄存器组的最简单类型。这些 CPU 在内部用整个(架构)寄存器文件的 2 个副本实现它们的寄存器文件,并将一半的功能单元连接到每个副本。这需要每个寄存器文件具有与单片寄存器文件相同的写入端口数(因为所有写入都发送到 *两个* 副本以保持同步),但每个寄存器文件只需要单片寄存器文件一半的读取端口数。
参考文献
[edit | edit source]- ↑ a b "计算机体系结构:计算机设计的基础和原理" 作者:Joseph D. Dumas 2006 年,第 111 页。
- ↑ “通用寄存器”是由 C. Gordon Bell 和 Allen Newell 在撰写他们的著作 *计算机结构:阅读和示例*(1971)时发明的。——Frederik Nebeker。文章 “更多珍藏文本”。“IEEE Spectrum” 2003 年 7 月。
- ↑ a b c Larry R. Fenstermaker。 "当前模式感测放大器应用于双端口寄存器文件,作者:Larry R. Fenstermaker"。1998 年。
- ↑ a b Akshay Vijayashekar 和 Hasan Ali。 "优化寄存器文件实现"。引用:“本论文的目的是为 Atmel 32 位微控制器实现一个全定制的、低功耗和面积高效的寄存器文件。... 寄存器文件的大小为 32 个 32 位字,具有两个写入端口和四个读取端口。”
- ↑ Norman P. Jouppi 和 Jeffrey Y. F. Tang "一个持续 20 MIPS 的 32 位 CMOS 微处理器,具有高持续性能与峰值性能比率"。 doi:10.1.1.85.988。1989 年。部分 “4.2。寄存器文件感测放大器”。第 10-12 页。
- ↑ Robert Reese。 "寄存器文件"。1999 年。
- ↑ a b "当应用于寄存器时,银行化是什么意思?"
- ↑ a b Jessica H. Tseng 和 Krste Asanović。 "用于高频超标量微处理器的组化多分支寄存器文件"。2003 年。
- ↑ Il Park、Michael D. Powell 和 T. N. Vijaykumar。 "减少寄存器端口以实现更高的速度和更低的能量"。2002 年。