当前位置: 首页 > 知识库问答 >
问题:

MIPS I如何在不暂停的情况下处理之前ALU指令上的分支?

司徒炎彬
2023-03-14
        addiu   $6,$6,5
        bltz    $6,$L5
        nop
        ...
$L5:

如果不暂停,这怎么安全呢?经典MIPS除了缓存未命中之外,甚至无法做到这一点?(MIPS最初代表的是没有互锁管道级的微处理器,它有一个负载延迟槽,而不是互锁。)

原始MIPS I是一个经典的5级RISCIF ID EX MEM WB设计,它通过在ID阶段尽早检查分支条件来隐藏其所有分支延迟(更正:这是错误的,去阅读这个答案;不要被问题中基于这个错误前提的其余细节所误导)。这就是为什么它仅限于相等/不相等,或符号位检查,如lit或ge零,而不是两个寄存器之间的tl,这需要通过加法器进行进位传播。

这难道不意味着分支需要比ALU指令早一个周期准备好输入吗?bltz进入ID阶段的周期与addu进入EX的周期相同。

MIPS I(又名R2000)使用从EX输出到EX输入的旁路转发,因此普通整数ALU指令(如addu/xor链)具有单周期延迟并且可以在连续周期中运行。

MIPS代表“无联锁管道级的微处理器”,因此它不会检测原始危险;代码必须避免它们。(因此,在第一代MIPS上加载延迟插槽,在这种情况下,MIPS II添加联锁以暂停,使首字母缩略词P无效)。

但是我从来没有看到任何关于提前计算多条指令以避免失速的分支条件的讨论。(addu/bltz示例是由Goldbolt上的MIPS gcc5.4-O3-mar=mips1发出的,它确实尊重加载延迟槽,如果需要,用nop填充。)

它是否使用了某种技巧,比如在时钟下降沿读取输入,在上升沿之前不需要转发寄存器值?(EX在足够早的时间内产生结果,使其发挥作用)

我想,如果时钟速度被限制得足够低,缓存访问可以是单周期的,那么这是有意义的。

MIPS中的失速或冒泡声称加载结果上的lw需要2个失速周期,因为它无法前进。这对于实际的MIPS I来说并不准确(除非gcc有缺陷)。不过,它确实提到了半个时钟周期,允许在相同的整个周期内写入值,然后从寄存器文件读取值。

共有2个答案

颜奇希
2023-03-14

你实际上在问两个问题:

  1. 在MIPS I上安全吗?
  2. 如果是,如何?

在MIPS I上安全吗?

我见过不同的MIPS CPU框图。它们中的大多数在EX甚至在MEM阶段而不是ID阶段执行分支决策。

当然,在执行示例代码时,这些设计的反应会有所不同。

如果没有您真正使用的CPU的CPU手册中的官方声明,您的问题无法得到肯定的回答。

(Paul Clayton关于的回答是,如果我们总是可以填满延迟槽,那么就没有必要进行分支预测?同意一个延迟槽确实完全隐藏了MIPS R2000上的分支延迟,但没有隐藏MIPS R4000上的分支延迟。因此,这很好地证明了真正的商用MIPS CPU是按照问题假设的方式工作的,尽管存在各种可能不完全遵循MIPS ISA的实现。)

如果是,如何?

这是否意味着分支需要比ALU指令早一个周期准备好输入?

不。

关键是旁路转发逻辑。让我们看一下以下示例:

add  $A, $B, $C      ; Currently in MEM stage
or   $D, $E, $F      ; Currently in EX stage
bltz $G, someLabel   ; Currently in ID stage

(虽然A、B、G是GPR编号。)

EX phase(指令)的旁路转发逻辑包含一个多路复用器,其工作方式如下(伪代码):

if E = A
    take ALU input from EX/MEM shift register output
else
    take ALU input from ID/EX shift register output
end-if

正是此多路复用器允许您在以下指令()中使用某些指令(添加)的结果。

当然,也可以使用3路多路复用器对ID相位执行相同操作:

if G = D
    take branch decision input from ALU output
else if G = A
    take branch decision input from EX/MEM shift register output
else
    take branch decision input from register bank output
end-if

这样,信号传播时间将增加到EX阶段所需的时间。这意味着这将限制处理器的时钟频率。

然而,某些指令的结果已经可以在下一条指令的ID级中使用,而不需要额外的时钟周期。

微生昌勋
2023-03-14

TL:DR:Classic MIPS I在EX的前半个周期检查分支条件,因此转发给它们并不特殊。

如果只需要在下半个周期中的地址,那么EX可以转发给它。

这些因素结合在一起,只会产生1个周期的分支延迟(由1个延迟槽隐藏),对于依赖先前ALU指令的分支没有问题。

在MIPS I(R2000)上运行sltu绝对安全。这被列为bgeu伪指令的扩展,例如,在真实的MIPS手册和书籍中,没有关于它在MIPS R2000或任何其他MIPS上不安全的警告。

GCC在实践中使用类似的序列,即使在考虑到加载延迟槽和实际MIPS R2000的其他特性的情况下,也会使用类似的序列。

MIPS的IF在时钟周期的第二个半周期之前不需要地址,允许EX足够快地生成地址。

参见Dominic Sweetman运行的MIPS(涵盖MIPS I至MIPS IV),第1.5.1章说明约束

我们稍后将看到,有效的条件分支意味着关于是否分支的决定只需压缩到半个管道阶段;该体系结构通过保持分支决策测试非常简单来提供帮助。因此,条件分支(在MIPS中)测试单个寄存器的符号/零或一对寄存器的相等性。

他们的图1.3:管道和分支延迟显示了在EX的前半部分计算的分支条件,并在IF的后半部分使用,总分支延迟仅为1个周期/管道阶段(ID)/指令。直到时钟周期的下半部分才真正开始。(并继续到ID。ID的实际解码/寄存器提取只需要时钟周期的最后一部分。)

这与我在问题中建议的结果相同(在ID末尾检查分支条件),只是它只需要-

也许我记错了或误解了我以前读过的关于半周期分支决策的东西。这个半周期的东西很可能正是我记得看到的。

进一步引用参见MIPS Run 1.5.5程序员-可见管道效果

延迟分支:[第一段解释了分支延迟槽]

如果硬件没有执行任何特殊操作,那么在ALU pipestage结束时,会出现是否分支的决定以及分支目标地址,以便及时获取分支目标指令,而不是下一条指令,而是两条指令。但是分支非常重要,足以证明需要进行特殊处理,从图1.3(如上所述)可以看出,通过ALU提供了一条特殊路径,以使分支地址提前半个时钟周期可用。再加上指令提取阶段的奇数半时钟周期偏移,这意味着可以及时提取分支目标,使其成为下一个,因此硬件运行分支指令,然后是分支延迟槽指令,然后是分支目标-没有其他延迟。

... [不要浪费分支延迟槽]

... [如果安全的话,许多MIPS汇编程序会为您重新排序指令,以隐藏分支延迟]

参见MIPS Run,MIPS Technologies等的创始人John L. Hennessy写了前言...这并不能证明他在书中签署的所有内容都是准确的,但这很好地证明了这本书对MIPS如何管理这个技巧的描述是准确的。

这很容易理解,而且100%可信;我们已经知道数据高速缓存具有单周期读取延迟(在EX阶段生成地址之后)。

 类似资料:
  • 问题内容: 我想知道如何将文件上传到具有“暂停和恢复”支持的Amazon S3?(通过网络浏览器)。 是否有可用的示例Web应用程序?任何编程语言/框架都可以。 提前致谢。 解 我实现了以下应用程序。Github链接。 它基于Condominios的示例应用程序和gem 。 所有的功劳都归功于https://github.com/cotag/,这是一个伟大的宝石和作品。 特征: 问题答案: 我实现

  • 我有一个Flink流应用程序,需要能够“暂停”和“取消暂停”对特定键控流的处理。“处理”意味着只是在流上执行一些简单的异常检测。 我们正在考虑的flow是这样工作的: 命令流,可以是ProcessCommand、PauseCommand或ResumeCommand,每个命令都有一个用于按键的id。 处理命令将检查按键在处理前是否暂停,如果没有暂停,则检查缓冲区。 暂停命令(PauseCommand

  • 我正在用laravel建立一个网站,我想调试我的程序,但很难使用dd(),因为它会立即停止程序,我想让它显示每执行一行,任何想法?任何帮助将不胜感激,谢谢。

  • //类B扩展类并添加一个附加变量 //这是主类 在不使用铸造的情况下如何设计解决上述问题?很抱歉问了这个低级的问题(我是java新手)。

  • 问题内容: 我有以下代码: 在发生某些事件之后,我应该停止在的方法中声明的操作,该方法实现。 我怎样才能做到这一点?我无法关闭执行器,只能撤消我的定期任务。我可以用吗?如果可以的话,请告诉我它将如何工作。 问题答案: 使用。该是你的任务的处理。您需要取消此任务,它将不再执行。 实际上,是签名,并将其与参数一起使用将导致当前正在运行的执行线程被调用中断。如果线程在阻塞的可中断调用(例如)中等待,则会

  • 假设我有一个旋转90度的正方形(我发现这是为我的计算机准备的)和一个旋转75度的第二个正方形。第一个正方形的左上角和第二个正方形的左下角相连。 我的目标是使用三角学来编辑第二个正方形的位置,以便它的右下角和第一个正方形的右上角(两个高亮的角)连接起来。 在一张不太硬的纸上。我会用sin和cos来求x和y的偏移量。在本例中,代码类似于: