漫谈指令集与CPU(二)

371 阅读4分钟

这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战


大家好,我是程栩,一个即将入职鹅厂的校招新人。本系列文章将会以一个演进的视角介绍计算机组成原理,并以一个采取Mips指令集的CPU作为范例。


软硬件接口

面对着计算机的疑惑,聪明的你选择了告诉他按照00-01-10-01的方式进行解读数据。计算机恍然大悟,想要去按照这样的方式解读时却发现,自己并不能按照这样的方式读取数据。这又是为什么呢?

原来当芯片被制造的时候,线路都已经被确定了,它可能只能按照000-110-01的方式解读数据,但是你给他的数据并不符合这样的要求。换句话说,硬件决定了对数据的结构方式和读取方式,这都是事先决定的,而不是可以随意更改的,硬件的硬也体现在这里:不可变更性。一个只能按照000-110-01方式解读的机器,可以接受00-01-10-01的数据,但是它的解读方式并不会按照00-01-10-01的方式进行解读。所以如果我们想要一个可以接受00-01-10-01方式的机器,我们就需要在物理上改变它,这是很难的,所以解决方式也许是换一台机器。

Verilog下的描述

Verilog是一种硬件描述语言,可以帮助我们做芯片设计。在这里我们屏蔽掉数电一层,从电路的角度来看,我们给出如下的一个简单加法器实现:

module add(
                             output     [1:0]   s, //输出
                             input      [1:0]   a, //输入
                             input      [1:0]   b, //输入
                             input      [1:0]   ci //输入
                             );


assign s = a + b
endmodule

从代码上来,其实并不是很难理解,这个模块有三个输入,a、b以及ci,而只有一个输出s。a和b就是两个加数,而s就是结果,所以自然而然的就有s=a+b的方式出现,那么这个模块的含义就很明显了:根据输入a和b来计算结果作为s输出。而这里的ci,则是告诉这个add做什么运算,是无符号加还是有符号加?(在这里省略掉了具体的处理,只以s=a+b来粗略的表示加)

在这里重要的一点在于,[1:0]的含义。在Verilog中,[1:0]表示的是位宽,也即四位的数据长度。比如a可以接受01这个数据,但是当遇到001的时候就会出现问题。

从这个角度来看,这个加法器只能接受六位的输入,而且是按照两位两位两位进行划分,那么自然而然的就不能接受其他方式的输入(可以接受输入,但是运算结果并不会按照我们的想法进行)。如下图所示:

image.png

如果再从数电的角度来看,就变成了:

image.png

这里的每一根线都是一个实际上的物理的电线,譬如面包板上用到的铜线,其能传递的只有高电平(1)和低电平(0)。

而这样的线路是不会更改的,所以一旦线路确定了,那么它的输入输出就确定了,所以这个加法器并不能够按照011-100的方式来正确的运算数据。

所以硬件和ISA其实是相辅相成的,两者只有配套在一起才能正常的运行。软硬件接口是ISA的意义也就在这里。

软硬件接口设计

聪明的你理解了软硬件接口的含义,准备一展宏图,自己设计一个指令集以及相应的硬件。就和Web前后端开发一样,你打算先设计好接口-ISA。

参考加法器的例子,你觉得一条指令应该有如下的因素:

  • 命令(op)
  • 数据

命令告诉硬件要做什么,而数据则告诉硬件做事情的时候使用哪些数据。比如我们小学时候学到的算式:1+1、2-1等,都是采取命令加数据的方式来进行表达。

那么,我们该如何设计指令呢?

从加法器出发,如果我们想要有多种运算,那么op就需要有多种。这计算机总得能支持加减乘除吧?那这个op至少得有两位([1:0]),比如用00表示加,01表示减等等。随着op的变多,这个位数自然而然的就变多了。那我们的数据呢?我们知道加减乘除都是两个运算数的,那如果来了个取反呢?取反不需要两个运算数,这又该如何设计呢?

你又一次的陷入了沉思……


个人水平有限,如果错误的地方,欢迎大家指出。也欢迎大家点赞收藏和评论~

明天再见!