之前在《[2022]总结与展望,想说的都在这里》中就提到过,我打算单独开个系列,从最基础的逻辑门,甚至是最最基础的晶体管开始实现一台图灵完备的计算机,于是我新开了一个系列,叫《从零开始的手搓CPU》。

前言

因为2022年的下半年学习了一些CPU结构的相关知识,并且在Tuling Complete游戏中实现了一个简单的架构,所以我想基于这些技术和知识,整理成一个系列文章,并且实实在在的使用硬件逻辑门芯片甚至是晶体管来搭建一块(一台)CPU。

在这个系列中,我们会从晶体管开始,了解各逻辑门的实现方法,然后基于这些逻辑门搭建寄存器、控制器、ALU、总线等部模块,然后使用这些模块组成一个可以执行汇编代码的CPU。

虽然现代集成电路和CPU已经发展得特别快了,我们只能实现最简单的CPU功能,但在完成这个系列的学习后,我们也能对现代CPU的最基本的工作原理有个大概的认识。这样对我们开发操作系统也有一定帮助。(所以操作系统开发系列我可能会再停更一大段时间...)

CPU组成

在intel汇编学习系列文章(目前还没发出来)中,我在第一篇文章中介绍了计算机发展历史,讲到了从最早的机械计算机与穿孔纸带到现代计算机的发展。其中随着计算机整体技术的不断提升,CPU中的技术也在不断提升。不过我们如果要纯手工制作,当然没办法做到现在的CPU的这种程度,但是实现一个简单的具有计算功能和指令运行功能的CPU还是没问题的。

最简单的CPU一般由以下几个部分组成:

  1. 寄存器
  2. 控制器
  3. ALU
  4. 总线

下面来对每个部分单独进行介绍:

寄存器

寄存器用于存储数据,不同寄存器的作用有所不同,结构也不同。

在CPU中,一般有以下几种寄存器:

  1. PC(Program Counter, 程序计数)寄存器,该寄存器用于指令地址,CPU在执行代码时,就会按照PC寄存器中保存的地址来读取指令。在我们后面实现汇编跳转指令(JMP等)时,就会修改这个寄存器中的值,从而实现跳转。
  2. SP(Stack Pointer, 栈顶指针)寄存器,该寄存器指向栈顶,我们在实现CALL和RET指令时会用到栈来保存和恢复CPU运行状态,此时就需要用到SP寄存器来记录栈顶。(不过栈和调用的实现比较麻烦,第一版的CPU中不一定会有,到时候按照进度情况来看要不要增加这个功能吧)
  3. 通用数据存储寄存器,该寄存器用于存储输入数据、输出数据、计算过程中的变量或计算结果等数据。
  4. Flags Register(标志寄存器),该寄存器用于存储运算状态,比如运算的进位、溢出或CPU的其他运行状态等。
  5. IR(Instruction Register, 指令寄存器),该寄存器用于保存正在执行的指令。

除了寄存器功能上的区别以外,在物理结构上也分为动态寄存器和静态寄存器,在不同的情况下有可能会使用到不同的寄存器结构。动态寄存器和静态计算器也有一些区别:

  • 从工作原理上来说,动态寄存器每个时钟周期重新读入和写入数据,而静态寄存器只需要在写入数据时电路稍加改变。
  • 从功耗上来说,因为动态寄存器会不断执行写入和读取,所以功耗会比静态寄存器更高。
  • 从速度上来说,动态寄存器的处理速度更快。
  • 从容量上来说,静态寄存器一般会比动态寄存器容量更大。

控制器

控制器用于协调和管理数据及其他部件,主要作用有:解码指令、管理数据流、管理寄存器、协调同步。

下面单独对每个功能进行简单介绍:

  • 解码指令:按照PC寄存器给出的地址从内存中读取指令,并把指令读取到IR寄存器中,以便CPU进行指令执行。
  • 管理数据流:协调和控制数据在CPU中的传递。
  • 管理寄存器:负责读取和写入寄存器数据,以便CPU对指令进行执行。
  • 协调同步:协调不同模块间状态的同步。

具体的控制过程,我们在真正上手制作CPU时就能感受到。

ALU

ALU中文名叫算术逻辑单元,负责进行对数据进行各种计算。

ALU可以完成一系列算术或逻辑运算,比如四则运算(加减乘除)或逻辑运算(与或非),或者比较运算(大于、小于、等于等)。在ALU进行计算时,会从通用数据存储寄存器取到需要计算的数据,并在计算完成后将数据保存到通用数据存储寄存器中,用于后续操作。

一般来说,如果需要计算浮点数(可以理解为小数,如3.14,至于为什么叫浮点数,我们后面在实现ALU时会介绍到)需要依靠一个叫FPU(Floating-Point Unit, 浮点运算单元)的东西,不过FPU并不是ALU中不可缺少的一部分,在对浮点数计算有需求的情况下,会将FPU集成到ALU中,或是单独的单元,供ALU调用运行。

由于FPU实现起来比较复杂,其中还涉及到一些浮点数的处理,所以在第一版中应该不会加入FPU,还是后续看情况再考虑要不要实现这一部分。

总线

负责连接各个模块,用于数据传输,还负责与外部设备、内存、芯片组(所谓的南桥之类的)进行数据通信,如果计算机中有多个CPU(核心),也负责CPU间通信。

总线其实跟其名字一样,就是一堆线,连接到各个模块,确保各个模块之间的数据是联通的。

总结

一个最简单的CPU的结构大概就是上面这样,我们后面会逐步实现每个模块,然后将其组装到一起,最后实现一个图灵完备,可以实际编程使用的CPU。

8086CPU结构图

具体在搭建CPU中会用到哪些芯片和材料,会在下一章中说明。