Cortex M4 LDR/STR 时序

Eri*_*Sun 5 performance assembly arm cpu-architecture cortex-m

我正在阅读 Cortex M4 TRM 以了解指令执行周期。但是,那里有一些令人困惑的描述

  1. 处理器指令表中STR需要2 个周期
  2. 稍后在加载/存储时间中,它表明

STR Rx,[Ry,#imm]总是一个周期,这是因为地址生成在初始循环中执行,并且所述数据存储在同一时间作为下一个指令正在执行执行。

如果存储到write buffer,并且write buffer已满或未启用,则下一条指令将延迟,直到存储完成。

如果存储不是到write buffer,例如代码段,并且该事务停止,则只有在完成之前执行另一个加载或存储操作时才会感受到对计时的影响

  1. 仍然在Load/store Timings 中,表示LDR可以通过跟随LDR和进行流水线化STR,但STR不能通过跟随指令进行流水线化。

其他指令在STR使用寄存器偏移后无法流水线化。STR 只能在跟随 LDR 时被流水线化,但在存储之后什么都不能流水线化。由于写缓冲区的原因,即使停止STR通常也只需要两个周期

更具体的让我困惑的是:

一季度。12似乎相互冲突,STR实际需要多少个周期,1 还是 2?(虽然我的实验显示为 1)

Q2。2表示如果存储通过write buffer并且不可用,它仍然会停止流水线,但是如果存储绕过它,流水线可能只在加载/存储指令跟随时停止。闻起来write buffer只会让事情变得更糟。这是有悖常理的。

Q3。3表示STR不能与后续指令流水线化,但是2表示STR在适当条件下始终与后续指令流水线化。如何理解相互矛盾的陈述?(这里它表示STR需要 2 而不是 1 个周期,因为write buffer

第 4 季度。我没有找到有关如何实现的更多信息write buffer。缓冲区有多大?如何STR确定是使用它还是绕过它?

Emb*_*eer 5

STR 的类型 请注意,在“加载/存储计时页面”上,第一条语句引用了 STR,其字面量偏移到基地址寄存器 ( STR Rx,[Ry,#imm])。再往下,它指的是一个 STR,其寄存器偏移到基地址寄存器 ( STR R1,[R3,R2])。这是 STR 指令的两种不同变体。

文字偏移 STR ( STR Rx,[Ry,#imm]) 嗯,我想知道文档在说“始终为 1 个周期”时是否具有误导性,因为随后添加了一个警告,这意味着它可能需要多个周期“......下一条指令被延迟到商店可以完成”

我将尽力解释文档:

STR Rx,[Ry,#imm] 总是一个周期。这是因为地址生成是在初始周期进行的,而数据存储是在执行下一条指令的同时进行的。如果存储到写缓冲区,并且写缓冲区已满或未启用,则下一条指令将延迟,直到存储可以完成。如果存储是写入缓冲区,例如代码段,并且该事务停止,则只有在完成之前执行另一个加载或存储操作时才会感受到对时序的影响。

如果写缓冲区可用,我会假设第一个 STR 需要 1 个周期。如果它不可用,则下一条指令将被暂停,直到缓冲区可用。但是,如果缓冲区未使用,它将延迟下一条指令,直到总线事务完成。

对于非连续 STR(第一个 STR),写缓冲区将是空的,并且指令需要 1 个周期。如果有 2 个连续的 STR 指令,第二个 STR 将在第一个 STR 写入缓冲区时立即开始。但是,如果第一个 STR 的总线事务停止并保留在写缓冲区中,则第二个 STR 将无法写入缓冲区并将阻止进一步的指令。然后当第一个 STR 的总线事务完成时,缓冲区被清空,第二个 STR 写入缓冲区,解锁下一条指令。

停滞的总线事务,其中事务缓冲在写缓冲区中,不会影响非 STR 指令,因为它们不需要访问写缓冲区来完成。因此,总线停止的 STR 指令不会延迟进一步的指令,除非它是另一个 STR。但是,如果未使用写缓冲区,则停止的总线事务将延迟所有指令。

指令集摘要页面将固定的“2”作为 STR 的周期数,这似乎有点偏离,但显然它不像这样可预测。

注册偏移量 STR ( STR R1,[R3,R2]) 我同意你对以下明显相互矛盾的陈述的困惑:

其他指令不能在带有寄存器偏移量的 STR 之后流水线化。STR 只能在跟随 LDR 时被流水线化,但在存储之后什么都不能流水线化。由于写缓冲区的原因,即使是停滞的 STR 通常也只需要两个周期。

因为这与页面上的第一个条款相矛盾。但是,我相信这是因为它指的是 2 种不同的 STR 类型,文字偏移量(第一个)和寄存器偏移量。寄存器偏移 STR 是之后不能允许流水线指令的寄存器。不过语言可能会更清楚。停顿的 STR 是什么意思,它是否指的是默认情况下总是停顿的寄存器偏移量 STR?这个停顿与写缓冲区不可用导致的停顿不同吗?在这里很容易迷路。

我认为基本上一个寄存器偏移量 STR 至少是 2 个周期。如果写缓冲区不可用,或者事务没有缓冲并且总线停顿,它将阻塞并占用更多周期。

写入缓冲区 大小 大小为单个条目,参见https://developer.arm.com/documentation/100166/0001/Programmers-Model/Write-buffer?lang=en

为了防止总线等待周期在数据存储期间停止处理器,DCode 和系统总线的缓冲存储通过单条目写入缓冲区。如果写缓冲区已满,则对总线的后续访问将停止,直到写缓冲区耗尽。

写缓冲区仅在总线等待缓冲存储的数据阶段时使用,否则事务在总线上完成。

写缓冲区的用处 就我的理解而言:如果 CPU 可以立即写入总线,那么它就不需要缓冲区,因为总线将立即空闲以供下一条指令使用。在像 M4 这样的高性能部件上,一些内存总线无法跟上 CPU 时钟速率,这意味着执行事务可能需要多个周期。也可能有使用相同总线的 DMA 单元。为了防止在总线事务完成之前停止 CPU,缓冲区提供了一个立即存储以使用该硬件然后在总线空闲时写入总线。