502-数据通路的建立
# 502-数据通路的建立
现在一方面我们已经有了指令系统的总体需求, 另一方面,我们也准备好了几个关键的组件, 那现在我们就来一起看一看能否根据这些需求,将这些关键的组件拼合起来, 构造出一个完整的数据通路。
要建立一个 数据通路,基本原则是分析指令系统当中每一条指令的需求,并根据 指令的需求连接我们已经选好的组件。那么指令的需求 又分为两大类,有一些需求是所有指令所共同需要的; 另外,不同的指令也有一些各自特殊的需求。
首先,我们来看所有指令的共同需求,我们要执行指令, 首先就需要取指令,我们知道,指令是放在指令存储器当中的, 而我们要访问指令存储器取得指令,就得有一个地址,这个地址则存放在 PC 寄存器当中。 我们已经有了一个 32 位的 PC 寄存器,那我们把 PC 寄存器 的输出就作为指令的地址,连接到指令存储器, 而指令存储器则会根据地址的输入选中对应的存储单元,并将其内容输出, 这样我们就得到了我们所需的那条指令的二进制编码。
那除了取得当前的指令之外,我们还得为取下一条 指令做好准备,这就需要更新 PC 寄存器, 这又分成了两种情况,大多数时候,指令是顺序执行的, 在这种情况下,PC 只需要加上当前这条指令的长度,就可以得到下一条指令的地址了。 在 MIPS 指令系统当中,每一条指令都是 4 个字节的,所以只需要 简单地进行 PC 加 4 的运算,那在我们刚才的这个结构上面, 我们需要增加一个简单的加法器,其中一个输入是 PC 寄存器的输出, 另一个输入是一个常数 4,然后我们将这个加法器的输出连接到 PC 寄存器的输入, 这样,当前 PC 寄存器的内容既会送到指令存储器,以获得指令的编码, 也会送到加法器的输入,从而计算出一个 PC+4 的值, 那在下一个时钟上升沿到来的时候, PC 寄存器就会将 PC+4 的值存入其中, 然后再将这个更新后的内容,同时送到指令存储器和加法器,
如此周而复始,就完成了每个时钟上升沿时,更新 PC 寄存器 的内容,然后指令存储器就会送出新一条指令的二进制编码。 当然我们这说的是顺序执行时的情况,
而如果遇到分支指令, 那下一条指令的地址就不是简单的 PC+4,而是用分支指令进行指定。 因此我们还需要继续修改这个结构,我们需要增加一个二选一的多选器, 在顺序执行时,我们选择这个多选器的 0 号输入端,也就是 PC+4 的内容, 而在发生分支时,我们就选择这个多选器的 1 号输入端,以至于由分支指定的目标地址。 那在下一个时钟上升沿到来的时候,PC 寄存器就会采样这个多选器的输出, 并将其保存起来,那这样一个结构,就完成了不断取回指令的功能。 我们把它称为取址部件,也简称为 IFU, IFU 作为一个整体,从外界只有一个时钟信号的输入, 和一个多选器选择信号的输入,并且提供一个指令编码的输出, 我们只用在系统启动时,给 PC 寄存器一个合适的初始值, 并在指令存储器中存放好我们需要运行的指令, 然后在运行的过程中,给出合适的多选器的选择信号,这个 IFU 就可以在时钟信号的驱动下自动的连续工作起来了,这些就是所有指令的共同需求。
然后我们再根据指令的不同类别,来分析他们的各自需求。 首先我们来看加法和减法指令, 这两条指令都是 R 型指令,它的主体操作是先用 rs 和 rt,这两个 5 位信号,访问寄存器堆获得两个寄存器的内容, 并对他们执行相应的运算,这个运算目前我们提供了加法和减法两种, 然后将运算的结果放到另一个 5 位信号 rd 所指定的寄存器当中。 因此,我们就需要用到寄存器堆这个组件, 这是一个两读一写的寄存器堆, 两个需要读出的寄存器的编号,是由指令编码当中 rs 和 rt 这两位域指定。 而要写入的寄存器的编号,则由 rd 这个位域指定的。 所以我们只需要把这三个位域的信号的值,连接到对应的输入上,这样在寄存器堆的输出端, busA 就会输出 rs 所指定的寄存器的内容, busB 则会输出 rt 所指定的寄存器的内容。 然后我们将 busA 和 busB 连到 ALU 的输入端, 并且我们根据指令编码当中的操作码和功能位域,就可以知道当前是加法还是减法指令, 我们要通过一个控制信号,来选择当前 ALU 提供的运算的类型。
然后我们还要将 ALU 的输出连接到寄存器堆的输入端,也就是 busW 信号, 那在下一个时钟上升沿到来的时候,如果寄存器堆的写使能信号是有效的, 在这里,就用这个 RegWr 信号等于 1 的时候, 寄存器堆就会采样 busW 信号上的内容,并将其存入到 Rb 这个信号所指定的寄存器当中去。 这样就在一个时钟周期完成了一条加法或者减法的指令,
我们要注意的是,这里用 红色表明的这两个信号,都成为控制信号。
然后我们来看逻辑运算指令的需求, 在我们的简化版本当中,提供了逻辑运算,就是这个对立即数进行或操作的指令, 这条指令是一条 I 型指令,那我们刚才已经建立的这个数据通路,是否能满足逻辑运算指令的需求呢? 经过分析,我们可以发现几个问题:第一,逻辑运算指令,它的目的寄存器是 rt,而不是 rd,而我们现在在寄存器堆的 Rw 输入端连接的是 rd 这个位域, 这样就没法满足这条逻辑运算指令,要把运算结果写入到 rt 所指向的寄存器当中这样一个目的; 第二,这条指令其中一个操作数是一个立即数, 而我们现在 ALU 的两个输入都是来自寄存器堆, 对这一点也无法支持;第三,我们在指令当中,只提供了一个 16 位的立即数, 而 ALU 的输入都是 32 位的,所以还需要对这个 16 位的立即数进行零扩展。
针对这个三个问题,我们就需要对现在的数据通路进行改造, 我们来注意这个数据通路的图,看我们需要增加哪些部件。
针对问题 1,我们增加了一个二选一的多选器,当执行之前的加法或者减法指令时, 我们让多选器的选择信号为 1,这时就会和刚才一样,将 rd 信号的内容传递到寄存器堆的 Rw 信号端, 而在执行现在这条逻辑运算指令时,我们就可以选择这个多选器的零号输入端, 将 rt 这个信号的值传递到寄存器堆的 Rw 信号端, 这就为写入 rt 所指定的寄存器提供了支持。
针对第二个问题,我们在 ALU 的输入端增加了一个多选器, 对于之前的功能,我们通过这个多选器的零号输入端, 将寄存器堆的 busB 信号和 ALU 的输入端相连, 而对于这条逻辑运算指令提出了新的需求,我们可以通过这个多选器的一号输入端, 将立即数与 ALU 相连,当然,这个 16 位的立即数还需要通过 一个零扩展部件,扩展成 32 位,再接到这个多选器的输入上。 这样我们就通过增加了两个多选器和一个零扩展部件,来满足了逻辑运算指令提出的新需求。 我们需要注意的是,我们在满足新需求的时候,一定要保证原有的需求同样是得到满足的。 所以在这里,我们就需要增加多选器,而不是直接修改各个部件的输入。
那在现在这条数据通路的基础上,我们再来看访存指令的需求。 访存指令也是 I 型指令,我们先来看其中的 Load 指令, Load 指令是要对数据存储器进行访问, 而访存的地址是由 rs 所指定的寄存器的内容加上立即数进行符号扩展后的值, 而且访存得到的数据也要保存在 rt 所指向的寄存器当中。 那现在的数据通路,已经支持了写入 rt 所指向的寄存器了。 而访存地址的运算, 是一个寄存器加上一个立即数, 那我们现在的数据通路,也大体支持这样的一个功能, 但仍然还是有问题的。
首先,我们还不支持符号扩展, 其次,这个 ALU 运算的结果,应该是作为地址去访问存储器,从而获得数据,而不是直接连到寄存器堆的写入端, 因此我们还需要对这个数据通路进行改造。
针对符号扩展的需求,我们将原先的零扩展的这个功能部件,改造为一个多功能的扩展部件, 通过控制信号,我们可以选择进行零扩展或者进行符号扩展, 对于这条 load 指令,我们可以选择将 16 位的立即数符号扩展为 32 位的数,并通过这个多选器连接到 ALU 的一个输入端, 而 ALU 的另一个输入端,则是 rs 所指定的寄存器的内容, 然后执行加法运算之后,获得了存储器的地址, 我们在这里就需要新增一个数据存储器, 这个存储器根据地址就可以得到对应的存储单元中的数据,因为我们最终是要将这个数据写入到寄存器堆,所以还需要增加这样一个多选器,将数据存储器当中输出的内容传送到寄存器堆的输入数据端。那这就是 load 指令所提出的需求,我们的解决方案是将原有的零扩展部件增加符号扩展的功能,并增加 一个数据存储器,当然,还包括相应的多选器。
那我们还有另一条访存指令,那就是 Store 指令, Store 指令的地址运算方式和 Load 指令是一样的, 所不同的是,Store 指令是将 rt 所指定的寄存器当中的内容存放到数据存储器当中去。 那我们来看现在的这个数据通路,我们首先需要 rt 所指定的寄存器的内容, 在现在的这个数据通路中,rt 所指定的寄存器的内容会从 busB 信号上出来, 那我们就需要将这个信号连接到数据存储器的数据输入端, 但是对于除了 Store 之外的其他指令,我们都不希望将 busB 上的信号写入到数据存储器当中, 所以我们还需要给数据存储器连接一个控制信号, 只有在这控制信号有效的时候,才会进行写入的操作, 这样我们就满足了 Store 指令的需求。
现在,除了比较特殊的分支指令之外,我们分析了其他指令的需求, 并将各个组件连接起来,再加上之前已经构造的 IFU 部件, 我们就初步完成了数据通路的建立工作。
现在,在处理器的设计步骤的这五步当中,我们已经完成了第三步。
现在,我们已经基本完成了一个数据通路,看起来也并不复杂嘛。不过,这个数据通路是否已经完整了呢? 而它又是否能够正确地工作呢? 这些都要通过一条一条指令来进行更细致的检查和确认。