AVR 微架构怎么可能仅在 1 个时钟周期内从 GP 寄存器获取 2 个操作数到 ALU?

How is it possible that the AVR microarchitecture can fetch 2 operands from the GP-Register to the ALU in only 1 clock cycle?

根据AVR Microcontroller的Datasheets,以及AVR架构的Instruction Set的Datasheet,某些指令,例如ADD,可以在只1 到 ALU 的时钟转换。 ADD 指令的指令字包含 2 个 GP 寄存器地址;每个 5 位宽,一个用于 destination/source,一个用于源。但是,这是如何在硬件级别上实现的呢? 2 寄存器的 5 位在尝试通过相同的直接寻址总线访问 GP 寄存器时不会相互干扰吗?

多端口寄存器文件广泛用于CPU设计As wikipedia says:

Modern integrated circuit-based register files are usually implemented by way of fast static RAMs with multiple ports.

快速 google 搜索发现 some slides,其中包含有关多端口 SRAM 单元的一些门/晶体管级详细信息,以及如何从中构建寄存器文件的框图。

这并不是 AVR 所独有的。流水线 RISC CPUs 通常是围绕在没有任何停顿的情况下每个时钟执行(至少)1 条指令而设计的,寄存器文件每个周期处理 2 次读取 + 1 次写入。例如MIPS 和其他 classic 5-stage RISC pipelines。 AVR 只是这些想法的 8 位版本。


多端口寄存器文件不是唯一的实施策略。考虑到 AVR 的时钟速度较慢,寄存器文件可以是单端口的并且时钟更快。


现代超标量 CPU 具有更宽的寄存器文件。

例如,(https://www.agner.org/optimize/blog/read.php?i=857) Intel Skylake 可以维持每个时钟周期至少读取 7 个 GP 整数寄存器的吞吐量,并同时在同一时钟周期内写入 3 个寄存器。 (并写入 FLAGS 3 次,这要归功于寄存器重命名打破了 WAW(写后写入)危险。尽管这实际上不算是分开的;产生寄存器和 FLAGS 输出的 uops 可以使用相同的物理寄存器条目来两者都持有。RAT 会跟踪从哪里来的东西。)

(在现代 Intel 上,不同的循环可以很容易地在每个时钟周期写入 4 个寄存器;我链接的实验主要是测试我每个时钟可以获得多少寄存器读取,以及未融合域 uop 吞吐量。)