传输触发架构

在计算机架构中，传输触发架构（ , TTA ）是一种处理器设计，其中程序直接控制处理器的内部传输总线。计算作为数据传输的副作用发生：将数据写入功能单元的触发端口会触发功能单元开始计算。这与脉动阵列中的情况类似。由于其模块化结构，TTA 是应用特定指令集处理器（ASIP）的理想处理器模板，具有定制的数据路径，但没有固定功能硬件加速器的灵活性和设计成本。
通常，传输触发处理器具有多个传输总线和多个连接到总线的功能单元，这为指令级并行性提供了机会。并行性由程序员静态定义。在这方面（显然由于指令字宽度较大），TTA 架构类似于非常长指令字（VLIW）架构。TTA 指令字由多个槽组成，每个总线一个槽，每个槽确定在相应总线上发生的数据传输。细粒度控制允许一些在传统处理器中无法实现的优化。例如，软件可以在功能单元之间直接传输数据，而无需使用寄存器。
传输触发暴露了一些通常对程序员隐藏的微架构细节。这大大简化了处理器的控制逻辑，因为许多通常在运行时做出的决策在编译时就已固定。然而，这也意味着为一个 TTA 处理器编译的二进制文件如果在两个处理器之间的架构存在微小差异，则无法在另一个处理器上运行，必须重新编译。二进制不兼容问题，加上实现完整上下文切换的复杂性，使得 TTA 更适合嵌入式系统而非通用计算。
在所有单指令集计算机架构中，TTA 架构是为数不多的有基于其构建的处理器的架构之一，也是唯一一个有基于其的处理器进行商业销售的架构。
与 VLIW 架构相比的优势.
TTA 可以被视为“暴露数据路径”的 VLIW 架构。虽然 VLIW 是通过操作进行编程的，但 TTA 将操作执行拆分为多个移动操作。与标准 VLIW 相比，低级编程模型带来了几个好处。例如，TTA 架构可以提供比 VLIW 更简单的寄存器文件和更多的并行性。由于程序员可以控制操作数和结果数据传输的时序，因此寄存器文件（RF）的复杂性（输入和输出端口的数量）不必根据多个并行指令的最坏情况发射/完成场景进行缩放。
由传输编程启用的一种重要独特软件优化称为软件旁路。在软件旁路的情况下，程序员通过将数据直接移动到下一个功能单元的操作数端口来绕过寄存器文件的写回。当这种优化被积极应用时，传输结果到寄存器文件的原始移动可以完全消除，从而减少寄存器文件端口的压力，并为其他临时变量释放一个通用寄存器。减少的寄存器压力，除了简化 RF 硬件所需的复杂性外，还可以带来显著的 CPU 能量节省，这在移动嵌入式系统中尤其是一个重要的好处。  
结构（Structure）.
TTA 处理器由独立的功能单元和寄存器文件构成，这些单元通过传输总线和插座连接。
功能单元（Function unit）.
每个功能单元实现一个或多个操作，这些操作的功能范围从简单的整数加法到复杂的任意用户定义的特定应用计算。操作的操作数通过功能单元端口传输。
每个功能单元可能有一个独立的流水线。如果一个功能单元是完全流水线化的，那么每个时钟周期都可以开始一个需要多个时钟周期才能完成的新操作。另一方面，流水线可以是这样的：在一个旧操作仍在执行时，它并不总是接受新的操作启动请求。
数据内存访问和与处理器外部的通信是通过使用特殊功能单元来处理的。实现内存访问操作并连接到内存模块的功能单元通常称为加载/存储单元。
控制单元（Control unit）.
控制单元是功能单元的一个特殊案例，它控制程序的执行。控制单元可以访问指令存储器，以便获取要执行的指令。为了允许已执行的程序将执行（跳转）转移到已执行程序中的任意位置，控制单元提供控制流操作。控制单元通常具有指令流水线，包含获取、解码和执行程序指令的各个阶段。
寄存器文件（Register files）.
寄存器文件包含通用寄存器，用于在程序中存储变量。与功能单元一样，寄存器文件也具有输入和输出端口。读写端口的数量，即在同一个时钟周期内能够读取和写入多个寄存器的能力，可以在每个寄存器文件中有所不同。
传输总线和套接字（Transport buses and sockets）.
互连架构由传输总线组成，这些总线通过插座连接到功能单元端口。由于连接的成本，通常会减少单元之间的连接数量（功能单元和寄存器文件）。如果每个单元的输出端口到每个单元的输入端口之间都有路径，则称 TTA 为完全连接。
套接字（Sockets）提供了编程 TTA 处理器的手段，通过允许在任何时刻选择插座的哪些总线到端口连接被启用。因此，发生在一个时钟周期内的数据传输可以通过定义每个总线要启用的源和目标插座/端口连接来编程。
条件执行（Conditional execution）.
某些 TTA 实现支持条件执行。
条件执行是通过保护器实现的。每个数据传输都可以通过一个保护器进行条件化，该保护器连接到一个寄存器（通常是一个 1 位条件寄存器）和一个总线。如果被保护寄存器的值评估为假（零），则连接到该保护器的总线上的数据传输将被压制，即不写入其目的地。无条件数据传输不连接到任何保护器，并始终执行。
分支（Branches）.
所有处理器，包括 TTA 处理器，都包含控制流指令，这些指令会改变程序计数器，用于实现子程序、if-then-else、for 循环等。TTA 处理器的汇编语言通常包括控制流指令，如无条件跳转（JUMP）、条件相对跳转（BNZ）、子程序调用（CALL）、条件返回（RETNZ）等，这些指令与其他处理器的相应汇编语言指令看起来相同。
与 TTA 机器上的所有其他操作一样，这些指令作为“移动”指令实现到一个特殊功能单元。
支持条件执行的 TTA 实现，例如 sTTAck 和第一个 MOVE 原型，可以将大多数这些控制流指令实现为对程序计数器的条件移动。  
仅支持无条件数据传输的 TTA 实现，例如 Maxim Integrated MAXQ，  通常具有一个与程序计数器紧密连接的特殊功能单元，该单元响应各种目的地址。每个这样的地址在作为“移动”的目的地时，对程序计数器有不同的影响——每个“相对分支 &lt;条件&gt;”指令对于每个条件都有不同的目的地址；其他目的地址用于 CALL、RETNZ 等。
编程.
在更传统的处理器架构中，处理器通常通过定义执行的操作及其操作数来编程。例如，RISC 架构中的加法指令可能如下所示。
 add r3, r1, r2
这个示例操作将通用寄存器 r1 和 r2 的值相加，并将结果存储在寄存器 r3 中。粗略地说，处理器中指令的执行可能会导致将指令转换为控制信号，这些控制信号控制互连网络连接和功能单元。互连网络用于将寄存器 r1 和 r2 的当前值传输到能够执行加法操作的功能单元，通常称为 ALU，即算术逻辑单元。最后，一个控制信号选择并触发 ALU 中的加法操作，其结果被传回寄存器 r3。
TTA 程序不定义操作，仅定义写入和读取操作数值所需的数据传输。操作本身是通过向操作的触发操作数写入数据来触发的。因此，操作是作为触发数据传输的副作用执行的。因此，在 TTA 中执行加法操作需要三个数据传输定义，也称为移动。移动定义了在传输总线中进行的数据传输的端点。例如，移动可以声明从功能单元 F，端口 1，到寄存器文件 R，寄存器索引 2 的数据传输应在总线 B1 中进行。如果目标处理器中有多个总线，则可以在同一个时钟周期内并行利用每个总线。因此，通过在同一条指令中调度多个数据传输，可以利用数据传输级别的并行性。
在 TTA 处理器中，可以执行加法操作，如下所示：
 r1 -&gt; ALU.operand1
 r2 -&gt; ALU.add.trigger
 ALU.result -&gt; r3
第二个操作，即对称为 ALU 的功能单元的第二个操作数进行写入，触发了加法操作。这使得加法的结果在'add'的执行延迟后可在输出端口'result'中获得。
与 ALU 相关的端口可以充当累加器，允许创建抽象底层 TTA 的宏指令：
 lda r1 "; "load ALU": move value to ALU operand 1"
 add r2 "; add: move value to add trigger"
 sta r3 "; "store ALU": move value from ALU result"
程序员可见的操作延迟.
TTAs 的主要理念是将复杂性从硬件转移到软件。因此，程序员面临着几个额外的风险。其中之一是延迟槽，即功能单元的可见操作延迟。时序完全由程序员负责。程序员必须安排指令，以确保结果既不会过早读取，也不会过晚读取。如果结果过早读取，硬件不会检测到并锁定处理器。例如，考虑一个具有延迟为 1 的加法操作和延迟为 3 的乘法操作的架构。当触发加法操作时，可以在下一条指令（下一个时钟周期）中读取结果，但在乘法操作的情况下，必须等待两条指令才能读取结果。结果在触发指令后的第 3 条指令时准备就绪。
过早读取结果会导致读取到先前触发的操作的结果，或者在函数单元中没有先前触发的操作时，读取的值是未定义的。另一方面，结果必须足够早地读取，以确保下一个操作的结果不会覆盖输出端口中尚未读取的结果。
由于程序员可见的处理器上下文丰富，实际上除了寄存器文件内容外，还包括功能单元管道寄存器内容和/或功能单元输入输出端口，因此在 TTA 处理器中，外部中断支持所需的上下文保存可能变得复杂且实现成本高。因此，TTA 处理器通常不支持中断，而是将其任务委托给外部硬件（例如，I/O 处理器），或者通过使用轮询等替代同步/通信机制来避免其需求。