[英]Cortex M4 LDR/STR timing
我正在阅读 Cortex M4 TRM 以了解指令执行周期。 但是,那里有一些令人困惑的描述
STR
需要2 个周期。
STR Rx,[Ry,#imm]
总是一个周期,这是因为地址生成是在初始周期进行的,数据存储是在下一条指令执行的同时进行的。
如果存储到
write buffer
,并且write buffer
已满或未启用,则下一条指令会延迟,直到存储可以完成。
如果存储不是
write buffer
,例如代码段,并且该事务停止,则只有在完成之前执行另一个加载或存储操作时才会感受到对时序的影响
LDR
可以按照LDR
和STR
进行流水线化,但STR
不能按照以下指令进行流水线化。其他指令不能在带有寄存器偏移的
STR
之后进行流水线处理。 STR 只能在 LDR 之后进行流水线化,但在存储之后不能进行流水线化。 由于写入缓冲区,即使是停滞的STR
通常也只需要两个周期
更具体地说明让我感到困惑的地方:
Q1。 1和2似乎相互冲突, STR
实际需要多少个周期,1 还是 2? (虽然我的实验显示 1)
Q2。 2表示如果通过write buffer
存储go并且它不可用,它仍然会停止流水线,但是如果存储绕过它,流水线可能只会在加载/存储指令之后停止。 闻起来像write buffer
只会让事情变得更糟。 这是有悖常理的。
Q3。 3表示STR
不能与后续指令一起流水线化,但2表示STR
在适当条件下始终与后续指令一起流水线化。 如何理解相互矛盾的陈述? (这里它表示STR
由于write buffer
而需要 2 而不是 1 个周期)
Q4。 我没有找到有关如何实现write buffer
的更多信息。 缓冲区有多大? STR
如何确定是使用它还是绕过它?
STR 的类型请注意,在“加载/存储时序页面”上,第一条语句指的是带有相对于基地址寄存器 ( STR Rx,[Ry,#imm]
) 的字面偏移量的 STR。 再往下,它指的是一个 STR,其寄存器偏移量相对于基地址寄存器( STR R1,[R3,R2]
)。 这是 STR 指令的两种不同变体。
Literal Offset STR ( STR Rx,[Ry,#imm]
) 嗯,我想知道当它说“总是 1 个周期”时文档是否具有误导性,因为它随后添加了一个警告,这意味着它可能需要多个周期“ ...下一条指令延迟到商店可以完成”
我将尽我所能解释文档:
STR Rx,[Ry,#imm] 总是一个周期。 这是因为地址生成是在初始周期中进行的,而数据存储是在执行下一条指令的同时进行的。 如果存储到写缓冲区,并且写缓冲区已满或未启用,则下一条指令会延迟,直到存储可以完成。 如果存储到写入缓冲区,例如到代码段,并且该事务停止,则只有在完成之前执行另一个加载或存储操作时才会感受到对时间的影响。
如果写缓冲区可用,我会假设第一个 STR 需要 1 个周期。 如果它不可用,则下一条指令将暂停,直到缓冲区可用。 但是,如果缓冲区没有被使用,它将延迟下一条指令,直到总线事务完成。
对于不连续的 STR(第一个 STR),写缓冲区将为空,并且指令需要 1 个周期。 如果有 2 个连续的 STR 指令,则第 2 个 STR 将在第 1 个 STR 写入缓冲区时立即开始。 但是,如果第 1 个 STR 的总线事务停止并保留在写缓冲区中,则第 2 个 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 和系统总线 go。 如果写缓冲区已满,则对总线的后续访问会停止,直到写缓冲区耗尽。
仅当总线等待缓冲存储的数据阶段时才使用写缓冲区,否则事务在总线上完成。
写缓冲区的用处就我的理解而言:如果 CPU 可以立即写入总线,那么它就不需要缓冲区,因为总线将立即空闲以用于下一条指令。 在像 M4 这样的高性能部件上,一些 memory 总线无法跟上 CPU 时钟速率,这意味着执行事务可能需要多个周期。 也可能有使用同一总线的 DMA 单元。 为了防止 CPU 在总线事务完成之前停止,缓冲区提供了一个立即存储,以供使用该硬件在空闲时写入总线。
@EmbeddedSoftwareEngineer,感谢您的回复。 我想发布我从实验中总结的内容
LDR
需要 2 个周期, STR
需要 1 个周期STR
后跟一个LDR
,因为组件不确保LDR
目标 memory 没有被STR
修改,它总是得到延迟,即LDR
3 个周期sub SP, SP, #20 ldr r1, [SP, #4] ;OR ldr r3, [SP, #8] ldr r4, [r3]
第二个LDR
总是会得到一个额外的等待周期,产生 3 个周期LDR
之后的LDR
将占用1个周期, LDR
之后的STR
将占用0个周期所有这些都基于 TCM,它不会从缓存加载或外部总线停顿中引入额外的周期。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.