![计算机系统解密:从理解计算机到编写高效代码](https://wfqqreader-1252317822.image.myqcloud.com/cover/723/40796723/b_40796723.jpg)
4.5 最终设计
我们把到目前为止的所有片段组合到一台实际的计算机中。我们需要在几处使用“胶水”才能让一切正常。
4.5.1 指令寄存器
你可能会误以为计算机在执行计算斐波那契数序列的程序时,一次只执行一条指令。但后台其实处理了更多事情。执行一条指令需要什么?图4-20所示的状态机将执行以下两个步骤。
![](https://epubservercos.yuewen.com/F7AA52/21191463001766706/epubprivate/OEBPS/Images/118-01.jpg?sign=1739240484-aOlqnPL3wNC2BlDCWUhV8kv8N3nswkox-0-6dcd5a5ee75d3fe125cd8f9cb0c12c80)
图4-20 获取–执行循环
要做的第一件事是从内存中取得指令。获得指令后,就可以考虑该如何执行该指令。
执行指令通常涉及访问内存。这意味着在使用内存执行其他任务时,需要有一个地方来保存指令。因此,我们向CPU添加一个指令寄存器来保存当前指令,如图4-21所示。
![](https://epubservercos.yuewen.com/F7AA52/21191463001766706/epubprivate/OEBPS/Images/118-02.jpg?sign=1739240484-BFDgTMtb4f7yOIYdGfblX8VjB3TnktE6-0-ca7f37dcd47636dc9836e31635075db6)
图4-21 增加一个指令寄存器
4.5.2 数据通路和控制信号
复杂的部分来了。我们需要将程序计数器的内容输入内存地址总线的方法,以及将内存数据输入指令寄存器的方法。可以做一个类似的练习来确定实现指令集中所有内容(见表4-4)所需的不同连接,最后得到了图4-22。图4-22可能看起来很混乱,但它实际上只是些我们之前见过的东西:寄存器、选择器、ALU和三态缓冲器。
![](https://epubservercos.yuewen.com/F7AA52/21191463001766706/epubprivate/OEBPS/Images/119-01.jpg?sign=1739240484-r82wwdlSSqx6Slt4sMouzLuugDftu8HM-0-ac66b9874e05f927988753662dbb36be)
图4-22 数据通路和控制信号
虽然它看起来很复杂,但它就像一张路线图,比真正的城市地图简单多了。地址选择器只是一个三路交叉口,而数据选择器是一个四路交叉口。对于将在第6章中讨论的I/O设备,存在挂载到地址总线和数据总线的连接。
图4-22中唯一的新内容是间接地址寄存器。之所以需要它是因为我们需要在某个地方保存从内存中获取的间接地址,就像需要指令寄存器保存从内存中获取的指令一样。
为了简单起见,图4-22省略了所有寄存器和内存中的系统时钟。在简单寄存的情况下,假设寄存器被加载到下一个时钟(如果启用)。同样,程序计数器和内存在每个时钟上按其控制信号的指示执行程序。所有其他组件(比如选择器)都只是纯粹地进行了组合,不使用时钟。
4.5.3 流量控制
既然已经熟悉了所有的输入和输出,现在是时候构建流量控制单元了。我们来看几个关于它需要如何运行的例子。
获取指令、获取数对所有指令都是通用的,涉及以下信号:
- 地址源必须设置为选择程序计数器。
- 必须启用内存,读写信号
必须设置为读取(1)。
- 指令寄存器必须启用。
比如,把累加器的内容存储在指令中地址所指向的内存地址(间接寻址),仍然可以像上面那样获取地址。
从内存获取间接地址:
- 地址源必须设置为选择指令寄存器,它可以获取指令的地址部分。
- 启用内存,
设置为读取(1)。
- 启用间接地址寄存器。
将累加器存储在该地址中:
- 地址源必须设置为选择间接地址寄存器。
- 必须设置数据总线启用。
- 启用内存,
设置为写入(0)。
- 程序计数器递增。
因为获取和执行指令涉及多个步骤,所以需要一个计数器来跟踪它们。计数器内容加上指令的操作码和方式部分就可以生成所有的控制信号。我们需要2位计数器,因为执行最复杂的指令需要三种状态,如图4-23所示。
![](https://epubservercos.yuewen.com/F7AA52/21191463001766706/epubprivate/OEBPS/Images/120-01.jpg?sign=1739240484-s8iut5XktGumyic809LBZbz8RinBep1d-0-7ac6a40a8105bdc5fef5b27a0d9cc4d5)
图4-23 随机逻辑流量控制
图4-23所示的是一个装满随机逻辑的大盒子。到目前为止,我们看到的所有逻辑图都遵循某种规律。功能块(如选择器和寄存器)以一种清晰的方式由简单的块组装而成。有时,例如当实现流量控制单元时,必须有一组输入被映射到一组输出以完成一个没有规律的任务。这张示意图看起来就像一个老鼠窝一样的连接,因此表示出了“随机”。
还有另一种可以实现流量控制单元的方法。该方法用大量的内存来代替随机逻辑。地址将由计数器输出加上指令的操作码和方式部分组成,如图4-24所示。图4-25展示了每一个19位的内存字。
![](https://epubservercos.yuewen.com/F7AA52/21191463001766706/epubprivate/OEBPS/Images/121-01.jpg?sign=1739240484-w780gL95vlIvo7ppIcKDFFE011NMMSgK-0-50e98595ce636793c24f97f69cf5691a)
图4-24 基于内存的流量控制
![](https://epubservercos.yuewen.com/F7AA52/21191463001766706/epubprivate/OEBPS/Images/121-02.jpg?sign=1739240484-4CEGqmMYkWRSXn2JwbjBA87E80NTZNjd-0-33c4700cb7fba68fd2788e6f90c5a1d6)
图4-25 微码字布局
图4-25可能会让你觉得有些奇怪。一方面,它只是另一个使用内存而不是随机逻辑实现的状态机。另一方面,它看起来确实像一台简单的计算机。以上两种解释都正确。之所以说它是状态机是因为计算机就是状态机。但它也是一台计算机,因为它是可编程的。
这种类型的实现称为微编码,内存的内容称为微码。通常一台小型计算机可以作为大型计算机实现的一部分。
我们来看微指令的一部分,如图4-26所示,它实现了我们讨论过的例子。
![](https://epubservercos.yuewen.com/F7AA52/21191463001766706/epubprivate/OEBPS/Images/121-03.jpg?sign=1739240484-bIh0UyWcTpHmK2YpDq8EDunRtxWE3w2y-0-6ed4643f74098a1303b1ab48c2cc94ba)
图4-26 微码示例
正如你所料,一个好主意很难不被滥用。有些机器有一个纳米编码块,它实现了可以实现指令集的微编码块。
使用ROM作为微码存储器是有一定意义的,否则我们就需要在其他地方保存一份微码的副本,并且需要额外的硬件来加载微码。然而,在某些情况下,RAM或者ROM和RAM的混合体也是合理的。有些Intel CPU有可写微码,可以通过修补来修复bug。有些机器,如HP-2100系列,有一个可写的控制存储器,它是可以用来扩展基本指令集的微码RAM。
当今拥有可写微码的设备很少允许用户修改,原因有以下几个。制造商不希望用户依赖用户自己为应用程序编写的微码,因为一旦用户开始依赖它,制造商就很难打破这点。此外,有缺陷的微码也会损坏设备,例如它可以同时打开CPU中的内存使能和数据总线使能以可能烧坏晶体管的方式连接图腾柱输出。