我正在阅读通过Cortex M4 TRM来理解指令执行周期。然而,这里有一些令人困惑的描述。
STR Rx,[Ry,#imm]总是一个周期的,这是因为地址生成在初始循环中执行,数据存储在执行下一个指令的同时执行。如果存储到write buffer,且write buffer已满或未启用,则下一条指令将延迟到存储完成。如果存储不属于write buffer,例如代码段,并且该事务停止,则只有在完成之前执行另一个加载或存储操作时,才能感受到对时间的影响
LDR可以通过遵循LDR和STR来流水线,但是STR不能通过遵循指令来流水线。其他指令不能在
STR后使用寄存器偏移量进行流水线。只有在遵循LDR的情况下,STR才能被流水线化,但是存储之后没有任何东西可以被流水线化。即使是停滞的STR通常也只需要两个周期的,因为有写缓冲区。
更具体的是让我感到困惑的是:
Q1。1和2似乎相互冲突,STR实际需要多少周期,1还是2?(不过,我的实验显示1)
Q2。2表示,如果存储通过write buffer,并且它不可用,它仍然会阻塞管道,但是如果存储绕过它,管道可能只有在加载/存储指令遵循时才会停止。闻起来像write buffer只会让事情变得更糟。这与常识背道而驰。
Q3。3意味着STR不能用后续指令进行流水线,而2则意味着STR总是在适当的条件下与后续指令一起流水线。如何理解相互矛盾的陈述?(这里表示STR采用2而不是1周期,因为write buffer)
Q4。关于write buffer是如何实现的,我找不到更多的信息。缓冲区有多大?STR如何确定是使用它还是绕过它?
发布于 2020-09-10 09:57:47
类型的STR注意:在“Load/ statement页面”上,第一个语句指的是带有对基地址寄存器(STR Rx,[Ry,#imm])的文字偏移量的STR。进一步地,它指的是带有寄存器偏移到基本地址寄存器(STR R1,[R3,R2])的STR。这是STR指令的两个不同的变体。
文字偏移量STR(STR Rx,[Ry,#imm])嗯,我想知道当它说“总是一个周期”时,文档是否是错误的,因为它随后添加了一个警告,这意味着它可能需要多个周期“.下一条指令被推迟到商店完成”。
我将尽我所能解释这些文档:
STR,Ry,#imm总是一个周期。这是因为地址生成在初始周期中执行,数据存储在执行下一条指令的同时执行。如果存储到写缓冲区,而写入缓冲区已满或未启用,则下一条指令将延迟到存储完成。如果存储到写缓冲区(例如到代码段),而事务停止,则只有在完成之前执行另一个加载或存储操作时,才能感受到对时间的影响。
如果写缓冲区可用,我将假设第一个STR需要一个周期。如果它不可用,下一条指令将被停止,直到缓冲区可用为止。但是,如果缓冲区未被使用,它将延迟下一条指令,直到总线事务完成。
对于不连续的STR (第一个STR),写缓冲区将为空,指令需要一个周期。如果有两个连续的STR指令,第二个STR将立即开始,因为第一个STR已经写入缓冲区。但是,如果第一STR的总线事务停止并留在写缓冲区中,则第二STR将无法写入缓冲器并将阻止进一步的指令。然后,当第一STR的总线事务完成时,缓冲器被清空,第二STR写入缓冲器,解除阻塞下一条指令。
阻塞的总线事务(在写缓冲区中缓冲事务)不会影响非STR指令,因为它们不需要访问写缓冲区才能完成。因此,除非是另一个STR指令,否则停止总线的STR指令不会延迟进一步的指令。但是,如果未使用写缓冲区,则停止的总线事务将延迟所有指令。
指令集摘要页将一个坚实的"2“作为STR的循环数(当它显然不是这样可预测时),这似乎有点离题。
寄存器抵消STR(STR R1,[R3,R2])我和你站在一起,因为你对以下明显矛盾的声明感到困惑:
其他指令不能流水线后STR与寄存器偏移。只有在遵循LDR的情况下,STR才能被流水线化,但是存储之后没有任何东西可以被流水线化。由于写缓冲区,即使是停滞的STR通常也只需要两个周期。
因为这与页面上的第一句相矛盾。但是,我相信这是因为它引用了两种不同的STR类型,文字偏移量(第一个)和寄存器偏移量。寄存器偏移量STR是以后不允许流水线指令的寄存器。不过,语言可能会更清楚。它是什么意思的停滞STR,它指的是一个寄存器偏移STR总是在默认情况下暂停?此延迟是否与写入缓冲区不可用所造成的延迟不同?在这里很容易迷路。
我认为基本上一个寄存器偏移STR是至少两个周期。如果写缓冲区不可用,或者事务没有缓冲,总线中断,它将阻塞和占用更多的周期。
大小的写缓冲区大小是单个条目,请参阅https://developer.arm.com/documentation/100166/0001/Programmers-Model/Write-buffer?lang=en
为了防止总线等待周期在数据存储期间延迟处理器,缓冲存储到DCode和系统总线通过一个单项写缓冲区。如果写入缓冲区已满,则随后访问总线暂停,直到写入缓冲区耗尽为止。只有当总线等待缓冲存储的数据阶段时,才使用写缓冲区,否则事务在总线上完成。
按我的理解,写缓冲区的有用性是:如果CPU可以立即写入总线,那么它就不需要缓冲区了,因为下一条指令将立即释放总线。在高性能部分,如M4,一些内存总线无法跟上CPU的时钟速率,这意味着执行事务可能需要多个周期。此外,还可以使用同一总线的DMA单元。为了防止CPU在总线事务完成前停止运行,缓冲区提供了一个立即存储区,以便在总线空闲时使用哪个硬件然后写入总线。
发布于 2020-09-11 04:20:47
@EmbeddedSoftwareEngineer,谢谢您的回复。我想把我的实验总结出来
LDR需要2个周期,STR需要1个周期。STR,后面跟着一个LDR,因为程序集没有确保LDR目标内存没有被STR修改,所以总是延迟,即LDR的3个循环LDR总是有一个额外的等待周期,会产生3个周期LDR跟随LDR将占用1个周期,STR跟随LDR将占用0周期。所有这些都是建立在TCM的基础上的,它不增加缓存负载或外部总线失速的周期。
https://stackoverflow.com/questions/63261379
复制相似问题