碎碎思 · 2021年07月22日

浅谈PCI Express体系结构(三)

image.png

PCI总线的存储器读写总线事务

总线的基本任务是实现数据传送,将一组数据从一个设备传送到另一个设备,当然总线也可以将一个设备的数据广播到多个设备。在处理器系统中,这些数据传送都要依赖一定的规则,PCI总线并不例外。

PCI总线使用单端并行数据线,采用地址译码方式进行数据传递,而采用ID译码方式进行配置信息的传递。其中地址译码方式使用地址信号,而ID译码方式使用PCI设备的ID号,包括Bus Number、Device Number、Function Number和Register Number。下文将以图1‑1中的处理器系统为例,简要介绍PCI总线支持的总线事务及其传送方式。

如表1‑2所示,PCI总线支持多种总线事务。而本节重点介绍存储器读写总线事务,I/O读写总线事务,并在第2.4节详细介绍配置读写总线事务。值得注意的是,PCI设备只有在系统软件初始化配置空间之后,才能够被其他主设备访问。

当PCI设备的配置空间被初始化之后,该设备在当前的PCI总线树上将拥有一个独立的PCI总线地址空间,即BAR((Base Address Register)寄存器所描述的空间,有关BAR寄存器的详细说明见第2.3.2节。

处理器与PCI设备进行数据交换,或者PCI设备之间进行存储器数据交换时,都将通过PCI总线地址完成。而PCI设备与主存储器进行DMA操作时,使用的也是PCI总线域的地址,而不是存储器域的地址,此时HOST主桥将完成PCI总线地址到存储器域地址的转换,不同的HOST主桥进行地址转换时使用的方法并不相同。

PCI总线的配置读写总线事务与HOST主桥与PCI桥相关,因此读者需要了解HOST主桥和PCI桥的详细实现机制之后,才能深入理解这部分内容。本篇将在第2.4节详细介绍这些内容。在下文中,我们假定所使用的PCI设备的配置空间已经被系统软件初始化。

PCI总线支持以下几类存储器读写总线事务。

(1) HOST处理器对PCI设备的BAR空间进行数据读写,BAR空间可以使用存储器或者I/O译码方式。HOST处理器使用PCI总线的存储器读写总线事务和I/O读写总线事务访问PCI设备的BAR空间。

(2) PCI设备之间的数据传递。在PCI总线上的两个设备可以直接通信,如一个PCI设备可以访问另外一个设备的BAR空间。不过这种数据传递在PC处理器系统中,较少使用。

(3) PCI设备对主存储器进行读写,即DMA读写操作。DMA读写操作在所有处理器系统中都较为常用,也是PCI总线数据传送的重点所在。在多数情况下,DMA读写操作结束后将伴随着中断的产生。PCI设备可以使用INTA#、INTB#、INTC#和INTD#信号提交中断请求,也可以使用MSI机制提交中断请求。

1.3.1 PCI总线事务的时序

PCI总线使用第1.2节所述的信号进行数据和配置信息的传递,一个PCI总线事务的基本访问时序如图1‑3所示,与PCI总线事务相关的控制信号有FRAME#、IRDY#、TRDY#、DEVSEL#等其他信号。
image.png

当一个PCI主设备需要使用PCI总线时,需要首先发送REQ#信号,通过总线仲裁获得总线使用权,即GNT#信号有效后,使用以下步骤完成一个完整PCI总线事务,对目标设备进行存储器或者I/O地址空间的读写访问。

(1) 当PCI主设备获得总线使用权之后,将在CLK1的上升沿置FRAME#信号有效,启动PCI总线事务。当PCI总线事务结束后,FRAME#信号将被置为无效。

(2) PCI总线周期的第一个时钟周期(CLK1的上升沿到CLK2的上升沿之间)为地址周期。在地址周期中,PCI主设备将访问的目的地址和总线命令分别驱动到AD[31:0]和C/BE#信号上。如果当前总线命令是配置读写,那么IDSEL信号线也被置为有效,IDSEL信号与PCI总线的AD[31:11]相连,详见第2.4.4节。

(3) 当IRDY#、TRDY#和DEVSEL#信号都有效后,总线事务将使用数据周期,进行数据传递。当IRDY#和TRDY#信号没有同时有效时,PCI总线不能进行数据传递,PCI总线使用这两个信号进行传送控制。

(4) PCI总线支持突发周期,因此在地址周期之后可以有多个数据周期,可以传送多组数据。而目标设备并不知道突发周期的长度,如果目标设备不能继续接收数据时,可以disconnect当前总线事务。值得注意的是,只有存储器读写总线事务可以使用突发周期。

一个完整的PCI总线事务远比上述过程复杂的多,因为PCI总线还支持许多传送方式,如双地址周期、fast back-to-back(快速背靠背)、插入等待状态、重试和断连、总线上的错误处理等一系列总线事务。本篇不一一介绍这些传送方式。

1.3.2 Posted和Non-Posted传送方式

PCI总线规定了两类数据传送方式,分别是Posted和Non-Posted数据传送方式。其中使用Posted数据传送方式的总线事务也被称为Posted总线事务;而使用Non-Posted数据传送方式的总线事务也被称为Non-Posted总线事务。

其中Posted总线事务指PCI主设备向PCI目标设备进行数据传递时,当数据到达PCI桥后,即由PCI桥接管来自上游总线的总线事务,并将其转发到下游总线。采用这种数据传送方式,在数据还没有到达最终的目的地之前,PCI总线就可以结束当前总线事务,从而在一定程度上解决了PCI总线的拥塞。

而Non-Posted总线事务是指PCI主设备向PCI目标设备进行数据传递时,数据必须到达最终目的地之后,才能结束当前总线事务的一种数据传递方式。

显然采用Posted传送方式,当这个Posted总线事务通过某条PCI总线后,就可以释放PCI总线的资源;而采用Non-Posted传送方式,PCI总线在没有结束当前总线事务时必须等待。这种等待将严重阻塞当前PCI总线上的其他数据传送,因此PCI总线使用Delayed总线事务处理Non-Posted数据请求,使用Delayed总线事务可以相对缓解PCI总线的拥塞。Delayed总线事务的详细介绍见第1.3.5节。

PCI总线规定只有存储器写请求(包括存储器写并无效请求)可以采用Posted总线事务,下文将Posted存储器写请求简称为PMW(Posted Memory Write),而存储器读请求、I/O读写请求、配置读写请求只能采用Non-Posted总线事务。

下文以图1‑1的处理器系统中的PCI设备11向存储器进行DMA写操作为例,说明Posted传送方式的实现过程。PCI设备11进行DMA写操作时使用存储器写总线事务,当PCI设备11获得PCI总线x1的使用权后,将发送存储器写总线事务到PCI总线x1。当PCI桥1发现这个总线事务的地址不在该桥管理的地址范围内将首先接收这个总线事务,并结束PCI总线x1的总线事务。

此时PCI总线x1使用的资源已被释放,PCI设备11和PCI设备12可以使用PCI总线x1进行通信。PCI桥1获得PCI总线x0的使用权后,将转发这个存储器写总线事务到PCI总线x0,之后HOST主桥x将接收这个存储器写总线事务,并最终将数据写入主存储器。

由以上过程可以发现,Posted数据请求在通过PCI总线之后,将逐级释放总线资源,因此PCI总线的利用率较高。而使用Non-Posted方式进行数据传送的处理过程与此不同,Non-Posted数据请求在通过PCI总线时,并不会及时释放总线资源,从而在某种程度上影响PCI总线的使用效率和传送带宽。

1.3.3 HOST处理器访问PCI设备

HOST处理器对PCI设备的数据访问主要包含两方面内容,一方面是处理器向PCI设备发起存储器和I/O读写请求;另一方面是处理器对PCI设备进行配置读写。

在PCI设备的配置空间中,共有6个BAR寄存器。每一个BAR寄存器都与PCI设备使用的一组PCI总线地址空间对应,BAR寄存器记录这组地址空间的基地址。本书将与BAR寄存器对应的PCI总线地址空间称为BAR空间,在BAR空间中可以存放I/O地址空间,也可以存放存储器地址空间。

PCI设备可以根据需要,有选择地使用这些BAR空间。值得注意的是,在BAR寄存器中存放的是PCI设备使用的“PCI总线域”的物理地址,而不是“存储器域”的物理地址,有关BAR寄存器的详细介绍见第2.3.2节。

HOST处理器访问PCI设备I/O地址空间的过程,与访问存储器地址空间略有不同。有些处理器,如x86处理器,具有独立的I/O地址空间。x86处理器可以将PCI设备使用的I/O地址映射到存储器域的I/O地址空间中,之后处理器可以使用IN,OUT等指令对存储器域的I/O地址进行访问,然后通过HOST主桥将存储器域的I/O地址转换为PCI总线域的I/O地址,最后使用PCI总线的I/O总线事务对PCI设备的I/O地址进行读写访问。在x86处理器中,存储器域的I/O地址与PCI总线域的I/O地址相同。

对于有些没有独立I/O地址空间的处理器,如PowerPC处理器,需要在HOST主桥初始化时,将PCI设备使用的I/O地址空间映射为处理器的存储器地址空间。PowerPC处理器对这段“存储器域”的存储器空间进行读写访问时,HOST主桥将存储器域的这段存储器地址转换为PCI总线域的I/O地址,然后通过PCI总线的I/O总线事务对PCI设备的I/O地址进行读写操作。

在PCI总线中,存储器读写事务与I/O读写事务的实现较为类似。首先HOST处理器在初始化时,需要将PCI设备使用的BAR空间映射到“存储器域”的存储器地址空间。之后处理器通过存储器读写指令访问“存储器域”的存储器地址空间,HOST主桥将“存储器域”的读写请求翻译为PCI总线的存储器读写总线事务之后,再发送给目标设备。

值得注意的是,存储器域和PCI总线域的概念,PCI设备能够直接使用的地址为PCI总线域的地址,在PCI总线事务中出现的地址也为PCI总线域的地址;而处理器能够直接使用的地址为存储器域的地址。理解存储器域与PCI总线域的区别对于理解PCI总线至关重要,本篇将在第2.1节专门讨论这两个概念。

以上对PCI总线的存储器与I/O总线事务的介绍并没有考虑PCI桥的存在,如果将PCI桥考虑进来,情况将略微复杂一些。下文将以图1‑1为例说明处理器如何通过HOST主桥和PCI桥1对PCI设备11进行存储器读写操作。当处理器对PCI设备11进行存储器写操作时,这些数据需要通过HOST主桥x和PCI桥x1,最终到达PCI设备11,其访问步骤如下。值得注意的是,以下步骤忽略PCI总线的仲裁过程。

(1) 首先处理器将要传递的数据放入通用寄存器中,之后向PCI设备11映射到的存储器域的地址进行写操作。值得注意的是,处理器并不能直接访问PCI设备11的PCI总线地址空间,因为这些地址空间是属于PCI总线域的,处理器所能直接访问的空间是存储器域的地址空间。处理器必须通过HOST主桥将存储器域的数据访问转换为PCI总线事务才能对PCI总线地址空间进行访问。

(2) HOST主桥x接收来自处理器的存储器写请求,之后处理器结束当前存储器写操作,释放系统总线。HOST主桥x将存储器域的存储器地址转换为PCI总线域的PCI总线地址。并向PCI总线x0发起PCI写请求总线事务。值得注意的是,虽然在许多处理器系统中,存储器地址和PCI总线地址完全相等,但其含义完全不同。

(3) PCI总线x0上的PCI设备01、PCI设备02和PCI桥1将同时监听这个PCI写总线事务。最后PCI桥x1接收这个写总线事务,并结束来自PCI总线x0的PCI总线事务。之后PCI桥x1向PCI总线x1发起新的PCI总线写总线事务。

(4) PCI总线x1上的PCI设备11和PCI设备12同时监听这个PCI写总线事务。最后PCI设备11通过地址译码方式接收这个写总线事务,并结束来自PCI总线x1上的PCI总线事务。

由以上过程可以发现,由于存储器写总线事务使用Posted传送方式,因此数据通过PCI桥后都将结束上一级总线的PCI总线事务,从而上一级PCI总线可以被其他PCI设备使用。如果使用Non-Posted传送方式,直到数据发送到PCI设备11之后,PCI总线x1和x0才能依次释放,从而在某种程度上将造成PCI总线的拥塞。

处理器对PCI设备11进行I/O写操作时只能采用Non-Posted方式进行,与Posted方式相比,使用Non-Posted方式,当数据到达目标设备后,目标设备需要向主设备发出“回应[1] ”,当主设备收到这个“回应”后才能结束整个总线事务。本节不再讲述处理器如何对PCI设备进行I/O写操作,请读者思考这个过程。

处理器对PCI设备11进行存储器读时,这个读请求需要首先通过HOST主桥x和PCI桥x1到达PCI设备,之后PCI设备将读取的数据再次通过PCI桥x1和HOST主桥x传递给HOST处理器,其步骤如下所示。我们首先假设PCI总线没有使用Delayed传送方式处理Non-Posted总线事务,而是使用纯粹的Non-Posted方式。

(1) 首先处理器准备接收数据使用的通用寄存器,之后向PCI设备11映射到的存储器域的地址进行读操作,

(2) HOST主桥x接收来自处理器的存储器读请求。HOST主桥x进行存储器地址到PCI总线地址的转换,之后向PCI总线x0发起存储器读总线事务。

(3) PCI总线x0上的PCI设备01、PCI设备02和PCI桥x1将监听这个存储器读请求,之后PCI桥1接收这个存储器读请求。然后PCI桥x1向PCI总线x1发起新的PCI总线读请求。

(4) PCI总线x1上的PCI设备11和PCI设备12监听这个PCI读请求总线事务。最后PCI设备11接收这个存储器读请求总线事务,并将这个读请求总线事务转换为存储器读完成总线事务之后,将数据传送到PCI桥x1,并结束来自PCI总线x1上的PCI总线事务。

(5) PCI桥x1将接收到的数据通过PCI总线x0,继续上传到HOST主桥x,并结束PCI总线x0上的PCI总线事务。

(6) HOST主桥x将数据传递给处理器,最终结束处理器的存储器读操作。

显然这种方式与Posted传送方式相比,PCI总线的利用率较低。因为只要HOST处理器没有收到来自目标设备的“回应”,那么HOST处理器到目标设备的传送路径上使用的所有PCI总线都将被阻塞。因而PCI总线x0和x1并没有被充分利用。

由以上例子,我们可以发现只有“读完成”依次通过PCI总线x1和x0之后,存储器读总线事务才不继续占用PCI总线x1和x0的资源,显然这种数据传送方式并不合理。因此PCI总线使用Delayed传送方式解决这个总线拥塞问题,有关Delayed传送方式的实现机制见第1.3.5节。

1.3.4 PCI设备读写主存储器

PCI设备与存储器直接进行数据交换的过程也被称为DMA。与其他总线的DMA过程类似,PCI设备进行DMA操作时,需要获得数据传送的目的地址和传送大小。支持DMA传递的PCI设备可以在其BAR空间中设置两个寄存器,分别保存这个目标地址和传送大小。这两个寄存器也是PCI设备DMA控制器的组成部件。

值得注意的是,PCI设备进行DMA操作时,使用的目的地址是PCI总线域的物理地址,而不是存储器域的物理地址,因为PCI设备并不能识别存储器域的物理地址,而仅能识别PCI总线域的物理地址。

HOST主桥负责完成PCI总线地址到存储器域地址的转换。HOST主桥需要进行合理设置,将存储器的地址空间映射到PCI总线之后,PCI设备才能对这段存储器空间进行DMA操作。PCI设备不能直接访问没有经过主桥映射的存储器空间。

许多处理器允许PCI设备访问所有存储器域地址空间,但是有些处理器可以设置PCI设备所能访问的存储器域地址空间,从而对存储器域地址空间进行保护。例如PowerPC处理器的HOST主桥可以使用Inbound寄存器组,设置PCI设备访问的存储器地址范围和属性,只有在Inbound寄存器组映射的存储器空间才能被PCI设备访问,本篇将在第2.2节详细介绍PowerPC处理器的这组寄存器。

由上所述,在一个处理器系统中,并不是所有存储器空间都可以被PCI设备访问,只有在PCI总线域中有映像的存储器空间才能被PCI设备访问。经过HOST主桥映射的存储器,具有两个“地址”,一个是在存储器域的地址,一个是在PCI总线域的PCI总线地址。当处理器访问这段存储器空间时,使用存储器地址;而PCI设备访问这段内存时,使用PCI总线地址。在多数处理器系统中,存储器地址与PCI总线地址相同,但是系统程序员需要正确理解这两个地址的区别。

下文以PCI设备11向主存储器写数据为例,说明PCI设备如何进行DMA写操作。

(1) 首先PCI设备11将存储器写请求发向PCI总线x1,注意这个写请求使用的地址是PCI总线域的地址。

(2) PCI总线x1上的所有设备监听这个请求,因为PCI设备11是向处理器的存储器写数据,所以PCI总线x1上的PCI Agent设备都不会接收这个数据请求。

(3) PCI桥x1发现当前总线事务使用的PCI总线地址不是其下游设备使用的PCI总线地址,则接收这个数据请求,有关PCI桥的Secondary总线接收数据的过程见第3.2.1节。此时PCI桥x1将结束来自PCI设备11的Posted存储器写请求,并将这个数据请求推到上游PCI总线上,即PCI总线x0上。

(4) PCI总线x0上的所有PCI设备包括HOST主桥将监听这个请求。PCI总线x0上的PCI Agent设备也不会接收这个数据请求,此时这个数据请求将由HOST主桥x接收,并结束PCI桥x1的Posted存储器写请求。

(5) HOST主桥x发现这个数据请求发向存储器,则将来自PCI总线x0的PCI总线地址转换为存储器地址,之后通过存储器控制器将数据写入存储器,完成PCI设备的DMA写操作。

PCI设备进行DMA读过程与DMA写过程较为类似。不过PCI总线的存储器读总线事务只能使用Non-Posted总线事务,其过程如下。

(1) 首先PCI设备11将存储器读请求发向PCI总线x1。

(2) PCI总线x1上的所有设备监听这个请求,因为PCI设备11是从存储器中读取数据,所以PCI总线x1上的设备,如PCI设备12,不会接收这个数据请求。PCI桥x1发现下游PCI总线没有设备接收这个数据请求,则接收这个数据请求,并将这个数据请求推到上游PCI总线上,即PCI总线x0上。

(3) PCI总线x0上的设备将监听这个请求。PCI总线x0上的设备也不会接收这个数据请求,最后这个数据请求将由HOST主桥x接收。

(4) HOST主桥x发现这个数据请求是发向主存储器,则将来自PCI总线x0的PCI总线地址转换为存储器地址,之后通过存储器控制器将数据读出,并转发到HOST主桥x。

(5) HOST主桥x将数据经由PCI桥x1传递到PCI设备11,PCI设备11接收到这个数据后结束DMA读。

以上过程仅是PCI设备向存储器读写数据的一个简单流程。如果考虑处理器中的Cache,这些存储器读写过程较为复杂。

PCI总线还允许PCI设备之间进行数据传递,PCI设备间的数据交换较为简单。在实际应用中,PCI设备间的数据交换并不常见。下文以图1‑1为例,简要介绍PCI设备11将数据写入PCI设备01的过程;请读者自行考虑PCI设备11从PCI设备01读取数据的过程。

(1) 首先PCI设备11将PCI写总线事务发向PCI总线x1上。PCI桥x1和PCI设备12同时监听这个写总线事务。

(2) PCI桥x1将接收这个PCI写请求总线事务,并将这个PCI写总线事务上推到PCI总线x0。

(3) PCI总线x0上的所有设备将监听这个PCI写总线事务,最后由PCI设备01接收这个数据请求,并完成PCI写事务。

1.3.5 Delayed传送方式

如上文所述,如果处理器使用Non-Posted总线周期对PCI设备进行读操作,或者PCI设备使用Non-Posted总线事务对存储器进行读操作时,如果数据没有到达目的地,那么在这个读操作路径上的所有PCI总线都不能被释放,这将严重影响PCI总线的使用效率。

为此PCI桥需要对Non-Posted总线事务进行优化处理,并使用Delayed总线事务处理这些Non-Posted总线事务,PCI总线规定只有Non-Posted总线事务可以使用Delayed总线事务。PCI总线的Delay总线事务由Delay读写请求和Delay读写完成总线事务组成,当Delay读写请求到达目的地后,将被转换为Delay读写完成总线事务。基于Delay总线请求的数据交换如图1‑4所示。

image.png

假设处理器通过存储器读、I/O读写或者配置读写访问PCI设备22时,首先经过HOST主桥进行存储器域与PCI总线域的地址转换,并由HOST主桥发起PCI总线事务,然后通过PCI桥1、2,最终到达PCI设备22。其详细步骤如下。

(1) HOST主桥完成存储器域到PCI总线域的转换,然后启动PCI读总线事务。

(2) PCI桥1接收这个读总线事务,并首先使用Retry周期,使HOST主桥择时重新发起相同的总线周期。此时PCI桥1的上游PCI总线将被释放。值得注意的是PCI桥并不会每一次都使用Retry周期,使上游设备择时进行重试操作。在PCI总线中,有一个“16 Clock”原则,即FRAME#信号有效后,必须在16个时钟周期内置为无效,如果PCI桥发现来自上游设备的读总线事务不能在16个时钟周期内结束时,则使用Retry周期终止该总线事务。

(3) PCI桥1使用Delayed总线请求继续访问PCI设备22。

(4) PCI桥2接收这个总线请求,并将这个Delayed总线请求继续传递。此时PCI桥2也将首先使用Retry周期,使PCI桥1择时重新发起相同的总线周期。此时PCI桥2的上游PCI总线被释放。

(5) 这个数据请求最终到达PCI设备22,如果PCI设备22没有将数据准备好时,也可以使用Retry周期,使PCI桥2择时重新发起相同的总线周期;如果数据已经准备好,PCI设备22将接收这个数据请求,并将这个Delayed总线请求转换为Delayed总线完成事务。如果Delayed总线请求是读请求,则Delayed总线完成事务中含有数据,否则只有完成信息,而不包含数据。

(6) Delayed总线完成事务将“数据或者完成信息”传递给PCI桥2,当PCI桥1重新发出Non-Posted总线请求时,PCI桥2将这个“数据或者完成信息”传递给PCI桥1。

(7) HOST主桥重新发出存储器读总线事务时,PCI桥1将“数据或者完成信息”传递给HOST主桥,最终完成整个PCI总线事务。

由以上分析可知,Delayed总线周期由Delayed总线请求和Delayed总线完成两部分组成。下文将Delayed读请求总线事务简称为DRR(Delayed Read Request),Delayed读完成总线事务简称为DRC(Delayed Read Completion);而将Delayed写请求总线事务简称为DWR(Delayed Write Request),Delayed写完成总线事务简称为DWC(Delayed Write Completion)。

PCI总线使用Delayed总线事务,在一定程度上可以提高PCI总线的利用率。因为在进行Non-Posted总线事务时,Non-Posted请求在通过PCI桥之后,可以暂时释放PCI总线,但是采用这种方式,HOST/PCI桥将会择时进行重试操作。在许多情况下,使用Delayed总线事务,并不能取得理想的效果,因为过多的重试周期也将大量消耗PCI总线的带宽。

为了进一步提高Non-Posted总线事务的执行效率,PCI-X总线将PCI总线使用的Delayed总线事务,升级为Split总线事务。采用Split总线事务可以有效解决HOST/PCI桥的这些重试操作。Split总线事务的基本思想是发送端首先将Non-Posted总线请求发送给接收端,然后再由接收端主动地将数据传递给发送端。

除了PCI-X总线可以使用Split总线事务进行数据传送之外,有些处理器,如x86和PowerPC处理器的FSB(Front Side Bus)总线也支持这种Split总线事务,因此这些HOST主桥也可以发起这种Split总线事务。在PCIe总线中,Non-Posted数据传送都使用Split总线事务完成,而不再使用Delayed总线事务。本章将在第1.5.1节简要介绍Split总线事务和PCI-X总线对PCI总线的一些功能上的增强。

原出处:OpenFPGA
作者:碎碎思

相关文章推荐

更多FPGA技术干货请关注FPGA的逻辑技术专栏。
推荐阅读
关注数
10506
内容数
512
FPGA Logic 二三事
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息