芯片的设计到底有多难?来看资深工程师是如何做到模拟 CPU 的

2019-05-23 15:01:13 来源:tuicool
标签:

芯片的设计到底有多难?想要回答这个问题最好还是先自己实践一下。最近,来自 BBC 的一名资深软件工程师 Daniel Harper 使用 Go 语言成功模拟出了一个 CPU 的所有功能,并把自己的经历写成了博客,引起了人们的热议。这篇文章也告诉我们:完整地了解计算机的工作原理是多么重要。

 

Daniel 的经历在社交网络上不仅被好奇的群众点赞,也引发了大学芯片相关课程的学生和助教们的共鸣。如果你不知道 L1/L2 缓存的意义,认为自己没有搞清楚英特尔、ARM 芯片上著名的 Meltdown、Spectre 漏洞的意义,现在是时候开始学习了。

 


让我们看看 Daniel 是如何做到模拟 CPU 的:

几个月前,我实在不理解计算机如何在后台工作,也不清楚现代计算机的工作原理。之后,我读了 J. Clark Scott 的书籍《But How Do I Know?》,这本书讲述了一台与非门(NAND gate)8 位计算机,包括寄存器、RAM 以及 CPU、ALU 和 I/O 的位元,于是我想用代码进行模拟。

 

我对电路学知识的兴趣不大,而这本书只是简单概述了一些基础知识,包括接线以及在没有必备电气工程知识的情况下位元如何在计算系统中移动。对我而言,从这本书中获得的知识不多,所以必须亲身实践,并从不可避免的错误中吸取经验教训,这样使我能够有条理地用代码编写电路。

 

相关成果的 GitHub 地址为:https://github.com/djhworld/simple-computer

 

这台简单的计算机可以用来计算。

 


示例程序

这是一个相当整洁的小东西,CPU 代码被实现为一个开闭的门,但它奏效了,我已经进行了测试,以此证明它能够运行。

 

该程序操控键盘输入,并将文本呈现给显示器,其中使用了一套精心制作的字形作为专业字体,我将其命名为「Daniel Code Pro」。唯一作弊的一点是获取键盘输入并显示输出内容,为此我必须通过 GLFW 与外界通信,但剩余部分是模拟电路。

 

我甚至编写了一个简单的汇编程序,这令人大开眼界。这并不是完美的,实际上有点胡扯。但是,我了解到了其他人很多年前已经解决了的问题,并认为自己的这项工作更好。

 

为什么要做这个?

我曾看到一个 13 岁的孩子在 Minecraft 中做这项工作,所以等你用电报继电器制作出一个真正的 CPU 时再来质问我吧!

 

我心中的计算模型还停留在计算机科学初级教科书的层面,并且驱动我在 2013 年所编写的 Gameboy Emulator 的 CPU 与现今计算机运行的 CPU 完全不同。甚至可以说,模拟器只不过是一种状态机(state machine),它没有从逻辑门(logic gate)层面描述 CPU。仅使用 switch 语句即可以实现大多数 CPU 且能够存储寄存器状态。

 

我不知道 L1/L2 缓存(cache)和 pipelining 是什么,也完全不确定自己是否理解 Meltdown 和 Spectre 漏洞论文,所以想要更深入地了解这些东西。一些人告诉我,他们正在优化代码以更好地利用 CPU 缓存,而我却不知道如何验证真假,只能选择相信他们。我真的不确定 x86 指令是什么。我不了解人们如何能够将工作交给 GPU 或 TPU 处理,也不清楚什么是 TPU,更不清楚如何使用这些 SIMD 指令。

 

但所有这一切都需要具有相关的基础知识,所以我只有在阅读相关书籍后才能对此有所了解。这意味着我需要回到基础知识和原理上面,并从一些简单的程序上手。《But How Do I Know?》一本书中的「Scott 计算机」就很简单,也是我选择它的原因。

 

功能强大的 Scott 计算机!可以运行的!

Scott 计算机是一个附有 256 字节 RAM 的 8 位处理器,并通过 8 位系统总线连接。该计算机拥有 4 个通用寄存器,能够执行 17 个机器指令。一些人搭建了一个很酷的视觉模拟器(visual simulator),无法想象需要花费多长时间才能跟踪全部的接线状态!

 


组成 Scott CPU 的所有组件图解。

 

《But How Do I Know?》这本书将带你从一个不起眼的与非门开始,然后是内存和寄存器,最后继续对这些组件分层,直到你得出与上述类似的结果。这本书对相关内容做了非常好的概述,所以我极力推荐大家阅读,即使你已经熟悉了相关概念。我不建议大家在 Kindle 上阅读,因为书中的一些图有时很难在屏幕上放大和辨认,这是 Kindle 的一大弊端。唯一不同的一点是我将计算机升级到了 16 位,因为仅存储 ASCII 表的字形就令书中所描述的大多数 8 位机器无法做到,因此留给有用代码的空间就不多了。

 

我的开发之旅

开发过程实际上只是阅读文本、查找图表、然后尝试使用通用编程语言代码(而不是使用为集成电路开发而设计的代码)来翻译。

 

之所以用 Go 语言来写,是因为我对 Go 了解一点。杠精们可能会说,我不信你没有将时间花在学 VHDL、Verilog 或 LogSim 上,但我那时已经编写好了我的位元、字节和 NAND,我陷得太深了。也许我接下来会学那些东西。

 

从全局来看,大多数计算机只是传递一堆布尔值,所以任何对布尔值友好的语言都可以完成这项工作。

 

将模式应用于这些布尔值能够帮助程序员获得其含义,任何人都要做的最大决策是确定系统将使用哪种字节顺序(endianness),并确保所有组件都以正确的顺序在总线之间传递信息。

 

这绝对是实现中隐藏的痛点之一。从偏移量上看,我选择了较小的字节顺序。但在测试 ALU 时,我就遇到麻烦了。我试图找出为什么出来的数字是错误的。很多很多打印语句都发生在这个上面。

 

开发的确花了一些时间,大约是一两个月的业余时间。但一旦成功搭建出 CPU 并用它执行 2 + 2 = 5,我还是感到很欣慰。

 

书中讨论了 I/O 特性,设计了一个简单的键盘和显示界面,这样你就可以把东西放进机器或拿出来。我给自己设定了一个目标,那就是能够在键盘上输入一些东西,并在显示器上显示这些字母。

 

外设

在这里,外设使用的是适配模式,充当 CPU 和外部世界之间的硬件接口。这里并不难猜,肯定是软件设计模式获取灵感的地方。

 


I/O 适配器是如何连接到 GLFW 窗口的。

 

通过分离关注点,使用 GLFW 将键盘输入的内容输出到屏幕是非常简单的过程。事实上我只是从模拟器中提取了大部分代码并整形了一下,使用 go 通道作为进出机器的信号。

 

让它跑起来

 

 

这可能是最难的一部分,至少也是最麻烦的。用如此有限的指令集编写程序集真的很糟糕。使用我编写的粗糙的汇编程序编写程序集更糟糕,因为你怪不得别人。

 

最大的问题在于同时处理这 4 个寄存器并跟踪它们,将它们作为临时存储存储到内存中。在这个过程中,我记得 Gameboy CPU 有一个堆栈指针寄存器,这样你就可以推送和弹出状态。不幸的是,这台电脑没有这么奢侈,所以我主要是在定制的基础上对内存里的东西进行移进移出操作。

 

我唯一花时间实现的伪指令是 CALL,以帮助调用函数。这可以让你运行一个函数,然后在函数被调用后返回到该点。由于没有堆栈,你只能调用一层的深度。

 

由于机器不支持中断,为获取键盘状态等函数,你必须实现糟糕的轮询代码。书中的确提到了实现中断的步骤,但那需要写更多代码。

 

无论如何,我最终编写出了四个程序,其中多数程序使用一些共享代码来绘制字体、获取键盘输入等。虽然与操作系统还有一定的距离,但它确实让我意识到一个简单的操作系统也可能提供一些服务。

 

但这其实并不容易,文本编写程序最棘手的部分是计算出何时转到新行,或当你按回车键时发生了什么。

 

<code>main-getInput:</code>
<code>    CALL ROUTINE-io-pollKeyboard</code><code>    </code>
<code><code>    </code>CALL ROUTINE-io-drawFontCharacter</code><code>    </code>
<code><code>    </code>JMP main-getInput</code>


上述文本编写程序的主要循环。

 

我也没有抽出时间来实现退格键或其他任何修改键。这让我意识到制作文本编辑器需要做多少工作,这项工作可能是多么乏味。

 

反思

这个项目对我来说非常有趣,也很有收获。在用汇编语言编程的过程中,我基本上放弃了底层的 NAND、AND 和 OR 门。我上升到了上面的抽象层。虽然我做的这个 CPU 很简单,距离电脑里的 CPU 还很远,但通过这个项目我学到了很多,如:

位元如何在使用总线的所有组件之间移动

一个简单的 ALU 是如何工作的

一个简单的 Fetch-Decode-Execute 循环是什么样的

没有堆栈指针寄存器的机器+堆栈的概念很糟糕

没有中断的机器很糟糕

汇编程序是什么、如何工作

外围设备如何与一个简单的 CPU 通信

简单字体的工作原理和在显示器上显示它们的方法

一个简单的操作系统会是什么样子

 

相关课程

如果你对于芯片的工作原理非常有兴趣,先上一些在线课程也是一个好方法。这一 Udacity 免费课程《高性能计算架构》源自佐治亚理工:

https://cn.udacity.com/course/high-performance-computer-architecture--ud007

原文地址:https://djhworld.github.io/post/2019/05/21/i-dont-know-how-cpus-work-so-i-simulated-one-in-code/

 
关注与非网微信 ( ee-focus )
限量版产业观察、行业动态、技术大餐每日推荐
享受快时代的精品慢阅读
 

 

继续阅读
半导体产业未来的复苏还要看中国!

与非网9月20日讯,俄罗斯卫星通讯社网站发表文章称,据国际半导体设备与材料组织(SEMI)报告得出的结论,中国大陆和台湾地区将成为2020年芯片和半导体生产增长的主要驱动力。

笔记本选机有门道,为您精选CPU与GPU的黄金组合

打开电商网站的数码频道页面,“迎面扑来”的上百种型号产品,会不会诱发你的选择困难症?的确,在笔记本电脑的选购过程中,产品外观、品牌效应、性能、价格以及细节之处等很多特点,都可能是消费者考量的因素。

DRAM 要求不断提高,长鑫存储谈 10nm 愿景

与非网9月20日讯,9月19日在深圳举办的中国闪存技术峰会上,长鑫存储副总裁、未来技术评估实验室负责人平尔萱博士进行了《DRAM技术趋势与行业应用》的演讲。

联发科 5G 芯片终于有动静了,明年 1 月量产

与非网9月20日讯,据报道,联发科首席财务官顾大为今日上午表示,联发科5G手机芯片已送样,进度顺利,并预计将从明年1月起量产,在第1季度客户终端产品就会上市。

“鲲鹏+昇腾”双引擎部署,华为开放驶入计算产业大蓝海

与非网9月20日讯,在全联接大会期间,华为基于“鲲鹏+昇腾”双引擎正式全面启航计算战略,宣布开源服务器操作系统、GaussDB OLTP单机版数据库,开放鲲鹏主板,拥抱多样性计算时代。华为通过硬件开放、软件开源、使能合作伙伴,共同开拓万亿级的计算产业大蓝海。

更多资讯
嵌入式系统基本核心不能忘,ARM 是如何构架的?
嵌入式系统基本核心不能忘,ARM 是如何构架的?

目前在嵌入式开发的过程中,开发者往往把大量精力投入到嵌入式微处理器MPU(Micro Processing Unit)与众多外设的连接方式以及应用代码的开发之中,而忽视了对嵌入式系统最基本、最核心部分的研究。

南京集中签约 59 个集成电路项目,总投资额达 2425.5 亿

与非网9月20日讯,9月18日南京市委市政府在南京金陵饭店昆仑厅,举办2019中国·南京金秋经贸洽谈会重大项目集中签约仪式。本次签约仪式上,共有59个有代表性的重大项目,分为七个批次集中签约,总投资额高达2425.5亿。其中有超多项目,都和集成电路有关。

一纸华为禁令使它元气大伤?这家公司一季便损失5300万美元

与非网9月20日讯,美国公司美满Marvell在5G设备上布局多时,却被华为禁令打的翻不了身。

紫光旗下立联信项目正式落户天津

与非网9月20日讯,近日,紫光旗下立联信中国工厂项目暨紫光天津芯云产业基地正式落户天津。

8 英寸晶圆重新归来?年底将开建 15 座新厂

与非网9月20日讯,据SEMI最新报告,2019年底,将有15个新Fab厂开工建设,总投资金额达380亿美元。 全球将由 15 个 Fab 厂开建