芯片的设计到底有多难?来看资深工程师是如何做到模拟 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 )
限量版产业观察、行业动态、技术大餐每日推荐
享受快时代的精品慢阅读
 

 

继续阅读
美光科技:恢复对华为部分芯片发货

据外媒报道,美光科技表示,对华为已经恢复了部分芯片的出货,并预计今年晚些时候,公司的芯片需求会回升。周二晚些时候,镁光科技的股价一度上涨10%。

又一美公司恢复对华为出货,股价一度上涨 10%

据外媒报道,美光科技表示,对华为已经恢复了部分芯片的出货,并预计今年晚些时候,公司的芯片需求会回升。周二晚些时候,镁光科技的股价一度上涨10%。

续航不是笔记本卖点,但 Intel 九代酷睿是如何做到性能升级功耗不变的?
续航不是笔记本卖点,但 Intel 九代酷睿是如何做到性能升级功耗不变的?

提到这个问题,笔记本玩家可能要分裂了,面向商务市场的笔记本显然会把续航作为第二甚至第一选择,至少也要支撑8小时工作时间,还得轻薄、便携,这又进一步压缩了电池空间。

国内半导体芯片市场该如何满足?听听大咖怎么说

近日,由清华大学经管学院举办的“中美摩擦下的中国经济”研讨会在北京举行。清华大学微纳电子学系主任、微电子所所长魏少军在研讨会上介绍,去年中国采购了全球2/3(3120亿美元)的芯片,其中约1700亿美元随着整机出口至国外,中国本土使用了全球34%(1540亿美元)的芯片;

上海出台浦东新区改革政策,集成电路产业或将迎来新突破

上海市政府举行新闻发布会,解读上海最新出台的《关于支持浦东新区新改革开放再出发 实现新时代高质量发展的若干意见》(以下简称《若干意见》)。

更多资讯
方舟编译器 8 月开源,或能实现安卓到鸿蒙的无缝切换
方舟编译器 8 月开源,或能实现安卓到鸿蒙的无缝切换

近日,在上海举行的中国开源峰会2019上,华为战略与产业发展副总裁肖然表示,华为方舟编译器将于今年8月正式开源。

AMD 7nm 将首登舞台,新一轮 X86 体系大战开始了?
AMD 7nm 将首登舞台,新一轮 X86 体系大战开始了?

自2017年的初代锐龙处理器出世以来,AMD就重新在桌面端CPU市场上重新有了自己的一席之地,直到二代锐龙彻底站稳了脚跟,这几年来AMD多核心的战略令人惊艳,但是因为一二代锐龙受制于Zen架构问题,单核性能比价弱势,因为这一点失去了很多游戏用户的关注,直到今年全新Zen2架构的出现,让我们有了更多的期待。

耗时十年的方舟编译器有望今年8月正式开源?服务的不仅仅将是安卓系统?

华为宣称,方舟编译器可让系统操作流畅度提升24%,系统响应速度提升44%,第三方应用重新编译后流畅度可提升60%!

台积电要把最好的 7nm 留给自己?全球芯片公司人心慌慌
台积电要把最好的 7nm 留给自己?全球芯片公司人心慌慌

台积电近期可谓接连遭遇阵痛,三星抢走高通大单,华为减产,存储市场进展失利。

谷歌将支持其他基于 Chromium 的浏览器,新款 Edge 性能会更强
谷歌将支持其他基于 Chromium 的浏览器,新款 Edge 性能会更强

 谷歌近期宣布谷歌地球将最终支持所有其他基于Chromium的浏览器。谷歌在博客文章中宣布了这一消息,解释了在后台进行的更改以使其获得支持。