异星工厂吧 关注:57,811贴子:339,984

#作死历程#如何在异星工厂里玩图灵完备?

取消只看楼主收藏回复

《如何在异星工厂中从mos管开始搭建计算机?》
【不定期更新】。因为lz也在一边做一边学,做了三个月书才看了一半()。所以本贴应该更像一个完全外行的玩家对于计算机组成原理的个人笔记。求懂行的大佬轻喷。









IP属地:浙江1楼2024-06-15 08:50回复
    这一切的起源是,lz今年年初时候在研究核电节能电路——lz自然而然翻到了wiki上的电路教学、但这些wiki实例都只有一个结论,而缺少具体运作过程的教学。其中最让我困惑的就是这个奇怪的SR锁存器,为什么要设置S>R?它到底是如何运行的?


    所以lz就开始疯狂寻找可以入门异星工厂里电路的教程,,lz找啊找啊找,,

    ↑↑↑然后在贴吧精品贴里找到了这样一篇电路教学。
    本着来都来了看看也不吃亏的精神,lz在一番寻找后找到了这本书的pdf文件(之后会贴在二楼,欢迎大家一起来看!),结果没想到天雷勾动地火,这本书的有趣程度大大出乎我的意料:




    ↑↑↑真的很有趣!!lz拿到书第一天就看了一百多页。。
    然后终于,在读完第十二章“二进制加法器”之后,lz手痒难忍,决心尝试用异星工场中的电路元件来复现书中出现的所有结构——如此这般,在验证书中方案可行性的同时,我还能学到非常多有趣的数电知识。说不定在以后搭混料系统,或者AAI小车控制自动采矿等更复杂的电路里都能用上这些知识。
    ——那么话不多说,我们直接开干!
    (*在这里偷偷感谢御道风云同学推荐的书籍以及ta的电路教程,让我受益匪浅。在这里邀请所有对电路感兴趣的同学也去看看ta的帖子)
    (**如果你真的打算认真研究一下《编码的奥秘》,lz个人推荐大家再去买一份《图灵完备》过来玩玩。书中所学80%的结构都会在游戏前中期派上大用场。后半本书中艰涩难懂的计算机架构也可以反向通过《图灵完备》来学习,自己上手搭一搭数据总线、指令解码器和ALU模块等,要比书中结尾几章的纯文本描述要直观得多。)


    (***↑↑↑对了公布一下答案。这个是上文提到wiki实例中的SR锁存器具体运作方式。它本质上是一个AND-OR锁存器,S且非R时输出S(wiki中是S>R输出S。两者的真值表是完全一样的,都是只有S=1且R=0时输出1),电路核心的判断器相当于是一个给R输入取反的与门逻辑。实际上你还能再简化掉一个给R转换信号的运算器,直接把非R的条件写进判断器里(*中央判断器条件:当电量A<90%,闭合开关允许S信号通过),这样就只需要两个元件来完成锁存器电路。)

    ↑↑↑(画完才发现少画了个或门,,,还好异星工厂里元件不会短路,不然绝对烧芯片=A=)


    IP属地:浙江2楼2024-06-15 10:02
    收起回复
      《编码的奥秘》pdf就放在二楼了。挂了t我。
      〇第一章,在异星工厂里实现继电器和三级管

      如上图。三极管和mos管的本质,是“由一个输入来控制另一条电路的通断”。其实在功能上,三极管/mos管和继电器是完全同构的:输入高电平,电磁铁被激活,磁力吸引开关的铁片闭合开关。这样就连通了另一条电路,另一条电路的输出也从0(低电平)变成了1(高电平)。
      不同之处是,三极管由电流驱动,而mos管由电压驱动。(*注意这里只讨论它们作为布尔元件时逻辑功能上的相同点,要记住它们在物理原理上是完全不同的。这也是为什么基于mos管的门电路要远比基于三极管的门电路复杂。下一章末尾会作为进阶内容具体讨论。)

      继电器的真值表/逻辑表如上。输入0则输出0,输入1则输出1。
      要注意这并不是一条导线,实际上继电器的输入和输出之间没有任何电流可以构成回路。“输出0信号”是电磁铁关闭开关断开,输出端输出电流为0;而“输出1信号”是电磁铁打开开关闭合,把输出端直接和V端(供电电压,一般+1.8V)连接来输出1的。
      所以我们需要做的,是在异星工厂里搭出来一个和继电器/三极管同构的元件。它的要求是:
      1,你所设置的高电平信号“D”可以直接输入元件的基极(BASE)/栅极(GATE)来作为布尔值(0或1)输入——说得这么高大上,但你要做的其实很简单——那就是要找到一个结构,这个结构可以接收高电平信号D,然后像上图中的继电器一样,由D输入的1/0来直接控制“电磁铁”的开启/关闭
      2,与此同时,你所设置的高电平信号“D”也可以直接作为VDD,来给元件的集电极(COLLECTOR)/漏极(DRAIN)供电——如上,说的很高大上,但你要做的结构其实也很简单——那就是在元件里再做一个小回路,这个小回路的输入为VDD,而它的通断受“电磁铁”控制。
      (这个结构可以用工厂里的信号电路来做,也可以用机械臂来做,甚至可以用传送带来做——只要这个结构和继电器的功能同构就行。和MC或泰拉瑞亚中搭电脑一样,最重要的不是你的元件会不会用到电,而是你一定要找到一个和继电器/三极管/mos管同构的结构——比如你也可以用水流电路/沙子电路来在MC中实现逻辑门,不一定非要用红石电路。是的,这也是“图灵完备”的释义:只要我们能做继电器/三极管,就一定能做出逻辑门;只要我们能做出逻辑门,就一定能一步步做出图灵机甚至冯诺依曼机。其中“逻辑”才是主体,具体实现逻辑的“元件”的选取其实并没有绝对的限制。反正玩游戏嘛大家可以自由选择。)


      (*课外内容tips:“基极B,集电极C,发射极E”为三极管的三个引脚。其实继电器就像图中的水龙头一样:一个名为B的水龙头开关来控制C的水流到E。三极管完全由电流驱动,内部结构基本和继电器/水龙头同构,且三极管的输出可以并联(*继电器可以,但三极管的输出并不完全能并联。所以记得串个电阻再并联)。而“栅极G,漏极D,源极S”为mos管的三个引脚。因为mos管是由电压驱动的所以要特别注意,mos管的输出不可并联。因为一旦两个mos管输出不一致就会造成VDD→VSS短接,烧掉芯片(lz也是查了很多资料才完全理解,为什么游戏《图灵完备》里逻辑门的输出不能并联,而《异星工厂》里却可以==。工厂里的元件更像是已经做好了带电阻接地的三极管,永远不会短路)。所以如果你看过现实世界里芯片/cpu设计图的话,会看到mos管逻辑电路通常比三极管逻辑电路更加复杂。因为我们不希望芯片发生VDD→VSS短接)

      ——经过一番思考,我做出了这样一个结构↑↑↑。这个结构在书中被称为“延迟线(buffer relay)”(*其实逻辑电路中更常用串联非门的形式来搭延迟线)
      首先我把“绿色信号=1”作为“高电平”;自然“绿色信号=0”也就对应“低电平”。
      然后常量箱作为开关,控制输入的值。打开常量箱,则发送一个高电平信号(绿色=1)到元件的基极(BASE);关闭常量箱,则不再发送高电平信号(也可以看作绿色=0),此时元件的基极输入=0。
      这个元件由两部分构成。↑↑↑当它的输入端,也就是基极(BASE)接收到绿色信号>0(电平>0)时,电磁铁被激活,发送一个模拟磁力的信号“√”到小回路的开关。

      ↑↑↑然后当小回路接收到电磁铁发出的磁力信号后,就立即闭合,允许由集电极(COLLECTOR)输入的电平信号从此通过。

      测试一下,成功!模拟三极管的元件正常运转。


      IP属地:浙江4楼2024-06-15 12:51
      回复
        做好了继电器延迟线,非门就简单了。以下是非门的内部结构和真值表:



        ↑↑↑只需要给输入引脚设置电平=0时启用“电磁铁”就行了。这样设置时电平=1反而会让“电磁铁”关闭。要记住这种给单引脚取反的方式,这和后面会讲到的“德·摩根律”息息相关。用这种方式也能搭出更紧凑、延迟更低的定制逻辑门。


        IP属地:浙江5楼2024-06-15 13:12
        回复
          【〇第二章,在异星工厂里实现基础逻辑门】

          还是以《编码的奥秘》中的结构为参考,我们可以串联两个继电器来搭一个“与门”。

          画一下真值表可以知道,“输出=1”的条件是“A=1且B=1”。其实自己试试就能知道,“且”的逻辑与“串联”同构,“或”的逻辑与“并联”同构。所以我们一般做核能的节能电路:“蒸汽低于50%”且“距离上次加燃料已经过去200s”中,判断电路核心的两个判断器是串联的。

          ↑↑↑这里我们串连两个基本三极管,让A的输出连到B的输入。可以看到与门正常运转!

          ↑↑↑稍微优化一下布局,让这个与门更加紧凑。


          ↑↑↑同理,串三个三极管,就是三输入与门了。只有三个输入都为1时才会输出1:

          ↑↑↑↑左边的输入连接的是我之前做的计时器,它会一直重复输出二进制的0000~1111(十进制的0~15)。可以看到,在所有000~111的输入组合中,只有111可以点亮灯泡。

          ↑或门的逻辑和并联同构,所以并联两个三极管的输出就可以搭出一个或门。让我们来试试看:

          ↑↑↑可以看到,正常运转。所有00~11的输入组合里,只有00会输出0,其余组合(10、01、11)都输出1。
          因为并联的关系,任何一路输出为1都可以点亮代表输出的灯泡,此时或门的输出引脚=1。而只有当两个输入引脚都为0时,灯泡才会熄灭,此时或门的输出引脚=0。

          ↑优化一下布线,让它更加紧凑一些。
          总结一下,
          串联n个三极管就可以做出n输入与门,而它的输出相当于给n个三极管的输出求交集(0相当于空集)。所以只要有一个0,n输入与门的输出就是0
          并联n个三极管就可以做出n输入或门,而它的输出相当于给n个三极管的输出求并集。所以只要有一个1,n输入或门的输出就是1。


          IP属地:浙江6楼2024-06-15 16:37
          回复

            ↑如果你手头只有二输入与门,那么你可以通过这种“串联”的方式来得到一个三输入与门。

            ↑↑↑这个时候我们之前搭建的三极管结构时,高电平信号“D”就派上了大用场:因为高电平信号D【既可以是它的输入也可以是它的输出】,这允许我们在处理逻辑条件时,可以直接连接三极管的输入-输出引脚,而不用去管具体的数据类型。
            (*但是不要把高电平信号D和电源总线VDD划等号,虽然它们在数值上是相同的。元件的输入和输出是布尔算数,而VDD只负责供电。它们在功能上完全不同。在你的三极管不作为传输门TG所使用时,所有三极管元件中的“小回路”最好用统一的电源总线VDD去供电。比如在我的设计里,【绿线代表布尔算数,红线代表VDD供电】)

            ↑关于n输入与门/或门的另一个应用。这是一个8输入或门,用于判定给出的8位带符号整数是否等于0。不过因为或门特殊的性质(有1则1),无论串联还是并联都不影响它最终的输出。
            接下来要介绍一个重要的定律,【德·摩根律】:




            ↑如上,分别是《编码的奥秘》、《图灵完备》、《GEB》、《数学基础(修订本)》中对于【德·摩根律】的阐述。其实大家只要知道“德摩根律”是布尔代数和一阶逻辑命题里的一种【永真式】就行了,这里我只讲应用不讲原理(其实自己画画逻辑表也能推出来它为什么永真)。


            ↑拿出一个或门,给它的两个输入引脚取反,江江!我们就得到了一个与非门NAND GATE。
            它只有当两个输入都为1时才输出0,其余输入组合时都输出1。


            IP属地:浙江8楼2024-06-17 14:35
            回复
              【德摩根律-更多解释和证明】

              ↑↑↑如果你画出了或门OR和与非门NAND的逻辑表,不知道你会不会觉得,这两张逻辑表很像呢?它们两张逻辑表之间的差别好像是旋转了180°,或者好像时沿对角线翻转了一次?

              其实如果你试着只给一个引脚取反,比如给与门AND的上引脚取反,你会发现,它的逻辑表【横向翻转】了一次;而如果给与门AND的下引脚取反,你会发现,它的逻辑表【纵向翻转】了一次。
              是的,这就是给单引脚取反以定制逻辑门的方式:你本质上其实是对逻辑表这个2×2矩阵进行了一次翻转操作。
              而如果你给两个引脚同时取反,就相当于把这个矩阵翻转了两次——一次横向翻转,一次纵向翻转。虽然对比翻转两次前的逻辑表,它看起来像是沿对角线翻转了一次。但实际上进行过两次镜像对称操作后,你是把整张逻辑表旋转了180°:


              ↑↑↑以此为基础,我们就可以搭出所有的基础逻辑门:
              缓冲器Buffer(或称为延迟线relay)、非门NOT(或称为反相器inverter)、
              与门AND、或门OR、与非门NAND、或非门NOR。

              (↑不过实际上计算机是以与非门NAND和或非门NOR为基础逻辑门去搭建逻辑电路的。因为NAND和NOR的延迟更低。这也是为什么那个用继电器搭计算机的网页游戏叫NAND GAME↓)

              (*提前剧透一下,以下是所有基于通用逻辑门(NAND/NOR)的基础逻辑门电路↓↓↓↓↓。其中最让我印象深刻的是用与非门NAND搭出的异或门XOR(图里被命名为Exclusive-OR)。后面会单独讲解一下这个XOR的工作方式。这个结构也是图灵完备里“四元件异或门”成就所需要的结构。)
              (**更多的剧透:但是很遗憾,我已经试过了,所有以下结构在异星工厂中都有延迟更低的搭法——我们可以直接并联两个三极管搭OR门,而不用三个NAND门去搭OR门。这很有可能是因为异星工厂中的电路并不需要考虑“接地电压VSS”和“高阻态断路”两种低电平信号的区别。而且我们还能利用异星工厂电路的特性(不会短路,默认带电阻接地)来实现一些延迟非常低的“非法逻辑门结构”。接下来的帖子会细说。)



              IP属地:浙江9楼2024-06-17 15:37
              回复
                【〇第三章,二进制加法器:进位和异或门】


                ↑↑↑如书中所说,为了实现【1位二进制加法】,我们需要两个逻辑门:一个逻辑门负责输出加和位(个位),一个逻辑门负责输出进位位(十位)。进位位输出很好实现,当且仅当两个二进制数都为1时会向下一位进位,而这个逻辑刚好和与门AND GATE的逻辑是同构的。
                但是加和位要如何输出呢?两个二进制数中只有一个为1时加和结果是1(1+0=0+1=1,加和位/个位为1),而两个二进制数都为1时因为发生了进位,加和位会变成0(1+1=10,加和位/个位为0)。
                这里的诀窍有两个:
                ①通过观察发现,其实只有在两个输入相等时,“加和位逻辑门”才会输出0;而当两个输入不相等时,“加和位逻辑”会输出1。——本质上我们搭了一个与“≠”同构的逻辑门。
                ②要意识到,如果我们把两个基础逻辑门的4个输入引脚两两并联,并让两个输入A、B同时抵达两个逻辑门,并让两个逻辑门的输出怼进一个与门AND GATE里,我们实际上是把它俩的逻辑表求了一次交集:两张逻辑表上2×2=4个位置里,同为1的才会被与门输出1,不同为1的则不会输出。
                同理,如果把两个逻辑门的输出怼进一个或门OR GATE里,那么就相当于对两张逻辑表求了一次并集。——我们可以用这种给输出求交集/并集的方法来设计一些非常特殊的电路,比如将来会讲到的3-8译码器。当然也可以用来设计我们现在正需要的这个“加和位逻辑门“——异或门XOR。

                ↑其实看图要直观得多。我们可以给或门OR和与非门NAND的输出取交集来得到需要的异或门XOR输出;或者我们也可以给两个定制的特殊与门求并集来得到我们需要的异或门XOR输出。

                ↑而后一种求并集的方式,就是这种4×NAND=XOR结构的运作原理。根据德摩根律,如果给最右侧这个与非门NAND GATE的两个输入引脚取反,那么它就相当于一个或门OR GATE:

                这样,我们就用三种逻辑上等效的结构完成了异或门的搭建(在真正的计算机中常用第三种——4 NAND=XOR的结构)。
                但是这里我打算选用《编码的奥秘》中所用的第一种结构,即给NAND和OR的输出取交集的结构:

                ↑↑↑可以看到,正常运转。只有两个输出不相等时输出1,其他情况都输出0。
                可以看到当从11跳变到00时,输出闪烁了1tick。这是因为OR和NAND都是由【并联两个三极管】的形式搭成的,所以延迟都是一个通用逻辑门的延迟(游戏内为4tick)。但是求交集的与门因为是【串联两个三极管】搭成的,【它两个引脚的延迟并不一致】:

                ——如果输入引脚离输出引脚更近,则与门AND GATE的延迟也是“一个通用逻辑门的延迟”=4tick。但如果输入引脚离输出引脚更远,则与门AND GATE的延迟为“一个通用逻辑门的延迟”+“半个三极管的延迟”=5tick。就是这1tick的输入不一致,让与门的输出闪烁了一下。
                目前这并不是什么问题。因为我们要搭出的二进制加法器是纯粹的算数机器,它没有存储能力。所以这1tick的闪烁稍纵即逝,很快会被正确的答案所覆盖。而我们只需要等待N个tick后(N=加法器最大延迟),等计算稳定下来了,再去访问结果即可。
                【*我后来才知道,《编码的奥秘》和《图灵完备》都是【完全忽略“门延迟”】的。或者说门延迟造成的各种影响{比如锁存器的“亚稳态”)等内容完全不曾提及。但是异星工厂里时钟频率最快也只有60Hz,这种慢到极致的时钟刷新频率让一切延迟问题都会变成我们不得不面对的严峻考验——我们将来搭出的所有锁存器,都会非常非常非常容易跌入“亚稳态”进而失效。但这些问题都是可以一步步解决的。】


                IP属地:浙江11楼2024-06-17 17:37
                回复
                  希望你还记得我们本章最初要做的东西:

                  ——我们要用基础逻辑门做出这样一个结构:当输入两个1位二进制数A和B后,输出它们相加后的结果X₂X₁。其中X₂是进位位(Carry Bit),X₁是加和位(Sum Bit)。

                  ↑↑↑↑有了上面大费周章做出的异或门,我们就可以做出二进制加法器最基本的部件:半加器(Half Adder)。

                  ↑↑↑A+B=X₂X₁
                  X₂=CO (Carry Output 进位输出);X₁=S (Sum Output)。
                  但是目前它只能运行1位二进制加法。我们该如何实现n位二进制加法呢?别着急,让我们重新回顾一下加法的本质:

                  ↑↑↑试着加一下4位二进制数如何?比如14+15=29,我们把两个4位二进制数相加,最大会得到一个4+1位二进制数的结果(*1111+1111=11110。两个n位数字相加,结果最大不会超过n+1位数字)。
                  可以看到,在处理最低位时,我们首先把A和B的最低位相加,得到一个加和位S和一个进位位CO。这确实可以用半加器做到。
                  但是当我们开始处理下一位数字时,其实是在把“A的右起第二位”、“B的右起第二位”、“来自第一位相加结果的进位位”——这三个1位二进制数字加在一起,然后输出来加和位S和进位位CO。
                  也就是说,为了得到第n位二进制数字的加和结果,我们需要把【A的第n位数输入】、【B的第n位数输入】、【来自n-1位加和结果的进位输出】这三个二进制数加起来,输出【第n位的加和结果S(n)】,并把【第n位的进位输出CO(n)】发送给下一位(n+1位)——让这个【三输入二输出】的进程不断进行下去。

                  ——我们把这种可以处理三输入二输出的二进制加法元件称为“全加器(Full Adder)”。观察逻辑表,全加器的实际作用是“统计三个输入当中1的个数”:
                  如果三个输入中没有1,则输出00;如果三个输入中有一个1,则输出01;如果三个输入中有两个1,则输出10;如果三个输入中有三个1,则输出11。它的输出结果X₂X₁分别代表进位位CO和加和位S。

                  ↓↓↓

                  我们可以通过串联两个半加器HA的方式得到全加器FA,就像本贴8楼开头,串联两个二输入与门得到一个三输入与门一样。你可能会觉得两个半加器的CO输出不用再过一个半加器吗?为什么要过一个或门?万一两个CO都是1会不会丢失数据?
                  但如果你仔细观全加器的逻辑表就会发现,两个半加器的CO永远不可能同时为1。因为如果两个CO同时为1,则意味着我们的三个输入中有4个1——但很显然这种情况根本不可能发生。


                  ↑↑↑要注意,虽然全加器的功能是“统计三个输入中1的个数”,所以三个输入的次序可以互换(大家可以在游戏里试一试),但因为半加器的输出(X₂X₁)是有“前后次序”的,“和X₁进X₂”就是“和X₁进X₂”,不可表示成“和X₂进X₁”
                  ——所以两个半加器的串联次序是不可改变的:必须先用半加器处理A和B、再把来自AB的加和结果S和来自上一位的进位输入CI相加。这样才能保证所有的进位位都能正确输出到全加器外的CO引脚、所有的加和位都能过一遍半加器。

                  ↑↑↑试着搭一下。正常运行。全加器会统计当前三个输入中有多少个1,并以二进制数的形式输出1的个数。


                  IP属地:浙江14楼2024-06-18 19:59
                  回复


                    ↑↑↑这个是一般计组教科书上的全加器,原理更加直观一些。三输入异或门的逻辑也很有趣,只有在三个输入里有一个1或三个输入里有三个1时会输出1,其余时候都输出0,这正巧是我们需要的加和位输出。上面这个三输入异或门全加器和《编码的奥秘》中串联两个半加器的全加器延迟一样,在《图灵完备》里都是12tick。


                    将n个三输入二输出的全加器FA(Full Adder)串联,就得到了【n位行波进位加法器】,它的延迟是n×(全加器的延迟)。其实在输入A和B的时候,我们就已经能同时求出所有的进位输出CO(1)~CO(n)。这样我们就能做出一种延迟非常低的加法器——【并行进位加法器】。不过这部分书本外的内容我也没有完全研究懂,所以暂且不讲,以后弄懂了再来更新。
                    这里给最低位用全加器预留了一个进位输入,是为了给减法使用(*因为减法其实就是给B求补数后的加法,这里需要给B取反后再+1来得到补数。后面会详细讲。)。但如果你只进行加法不进行减法,那么就可以只给最低位一个半加器HA(Half Adder):

                    ↑↑↑这里选用《编码的奥秘》中的结构,但我打算串十个全加器,这样它可以进行0~1024以内的加法,输出0~2048。这样正好可以覆盖(0~999)+(0~999)=(0~1998),即所有的三位十进制加法。

                    这里做一个七段管,制作过程略,,原理很简单,就是给七个灯管编码为A~G(如果有小数点要8段显示,需要编码到H),然后把0~9这十个数字显示时所点亮的灯管分别编码进十个常量箱里——比如输入信号i=4,则判断器打开四号常量箱,输出提前编码好的灯管编号(B=1,C=1,F=1,G=1)。其余数字也是同理。

                    ↑↑↑假设我们要相加的两个三位十进制数字是X和Y,这里就是我们要如何把它们正确显示到七段数码管。
                    (*因为七段显示管、进制转换器等模块和我们本章研究的核心【二进制行波进位加法器】无关,所以这里我就偷个小懒直接用算术运算器做这些模块所需要的乘除法运算器了,,如果要我用三极管和逻辑门来做乘除法模块应该也行,但是恐怕延迟会非常非常高,布线也会非常麻烦,,所以饶了我吧QwQ)

                    ↑↑↑做一个“十进制→二进制”的进制转换模块,把两个三位十进制数X、Y转换成两个十位二进制数A、B。图中“%”是求余数。
                    这样我们直接用两个十进制数作为输入就可以了,不用像书中一样手动控制10个开关来调节A和B的值。

                    ↑↑↑“二进制→十进制”的进制转换模块要简单一些,直接把n个输出引脚分别乘以2^(n)。异星工厂的信号线会自动把同类型的信号按数目加起来,这样这条数据总线上的数,就已经是来自加法器的四位十进制输出了。


                    IP属地:浙江15楼2024-06-19 15:43
                    收起回复

                      ↑↑↑0.25倍速测试一下,正常运行!一轮计算的最大延迟大概是115tick。
                      输出出现闪烁的原因在本帖11楼结尾阐述过,这和基本逻辑门之间的【门延迟差异】有关。不过目前这不是特别严重的问题,因为加法器只是纯计算机械,没有存储功能。我们只需要在115tick后再读取它的输出即可——这可以用锁存器和计时器电路来实现。
                      【门延迟】将会是我们之后做锁存器和计时器时最大的敌人。不过到时候我们会一步步着手解决这些问题。
                      那么第三章《二进制加法器、进位和异或门》完结。


                      IP属地:浙江16楼2024-06-19 15:53
                      回复
                        【☎第三章附录1:减法】

                        ↑↑↑书上的减法部分内容讲的很快很浅,这里是我重新总结的一些笔记。减法和求补数的原理全在上面了。

                        为什么“A-B”实际上等于“A+(B取反)+1”?为什么我们加了一个更大的数,却可以绕数轴一整圈,得到一个更小的数?
                        ↑↑↑原因如上。比如说我们在计算机中定义出一个4 Bit数据,实际上并没有定义出整个二进制正整数轴x∈[0,∞),而是定义出了一个x∈[0000,1111]的【环】。这个环像我们的手表一样——【当手表上的时间走完24点后并不会跳到25点,而是会跳到第二天的00点。】它是一个首尾相接的环。
                        此时时间已经来到了第二天(这个4 Bbit数据也输出了一个进位位),但是我们一般会选用其他内存去接收这个进位位(比如用日历:每当钟表走完两圈24小时,则日期跳变到下一天),而不会把一整本日历做进小小的手表里。
                        ——这在计算机方面也是一样,如果有需要,我们则输出1111+1后的最高进位位(比如用16位内存处理64位加减法时,会单独锁存每16位的最高进位位,然后把这1位最高进位位数据发送到下一个16位数据)。
                        但一般在做减法时,我们只是把一个个n位数据当成一个个圆形的表盘:左半边[1000~1111]为负数,右半边[0000~0111]为正数。即【首位bit为1则为负数,首位bit为0则为正数】。这样我们在“A-B=A+(B取反)+1”时,就可以把时针拨快一整圈,得到正确的减法答案。
                        但还有一些问题,比如你在早上8:00问我,“11小时前是几点?”,我既可以直接8-11得到9点,也可以8+(11的补数1)得到9点——为什么我在求11的补数时候只需要给11取反:“12-11得到1”;而不需要像在计算机中那样,在取反后再给结果加1呢?
                        ——答案比你想象中的要简单:【因为计算机中我们一般定义“0”为“时钟”的起点。而现实世界中我们钟表的起点就是“1”,所以求补数时只需要取反,不需要加1。】

                        ↑↑↑其实知道了原理,减法模块搭起来就很简单了。
                        这是游戏《图灵完备》里给OVERTURE架构搭的算术逻辑单元ALU(*绿色的线是四种按位操作的逻辑,暂时不用关注。玫红色的线才是这里实现加减法的主体结构),我们甚至不需要动8位加法器,只需要一个1-2选择器元件和一个8位按位取非元件就行。两个元件都很容易搭出来。
                        ....逻辑简单但是异星工厂里因为接线有点困难,减法器先咕咕一下,以后会和计算机架构一起做=A=。


                        IP属地:浙江19楼2024-06-21 15:52
                        回复
                          【☎第三章附录2:高阻抗≠VSS??逻辑门短路、现实世界中的MOS管电路】

                          ↑↑↑我在第一次读到《编码的奥秘》中搭建异或门XOR的那一节时,我就很疑惑:为什么不直接把两个与门AND的输出合并起来?这样应该也能正确输出OR的逻辑才对啊?为什么要再连接一个或门?而且按照《异星工厂》中信号电路的逻辑来说,这种做法应该完全合法才对啊?大部分人实现“OR”逻辑应该也是这样做的:直接并联两个算数运算器就好,为什么还要再给输出过一个或门?

                          ↑↑↑↑试一下。
                          ok,在《异星工厂》中,“直接并联逻辑门输出”来替代“或门”是完全可行的。
                          让我们试试在《图灵完备》里,能不能这样做:

                          ???????
                          咦?为什么在《异星工厂》中完全可行的结构,在《图灵完备》里却行不通呢?

                          ↑↑↑好像必须在这里加一个或门才行,否则会一直提示【输出短接】?
                          这个小小疑问在两个月里一直萦绕耳畔,直到我翻找到了或门OR GATE的mos电路图:

                          ↑↑↑图源:《带你认识CPU》BV18M4y137Cr
                          可以先看看右半部分“N非门”:实际上你使用nmos和pmos搭了个【1-2选择器】,给非门输入高电平,则把输出连到VSS(接地,电压=0V);给非门输入低电平,则把输出连到VDD(电源总线,电压= +1.2V)。左半部分“NOR或非门”其实也是类似的原理。仅当“A=B=高电平”时,把NOR的输出连接到VDD,否则NOR的输出一直连到VSS。
                          也就是说,【所有门电路的输出,只能是VSS或者VDD】——VSS连接到GND输出低电平,也就是接地;VDD连接到电源总线输出高电平,一般取+1.2V。
                          这就是为什么你在现实世界里不能把逻辑门的输出直接连在一起:如果你并联两个逻辑门的输出,
                          【一旦两个逻辑门输出不一致,就会造成VDD→VSS短接】,此时大量电流涌入短接的回路,烧掉芯片(听说是这样=A=。没找到具体参考文献。蹲个大佬讲讲到底会怎样)。这也是为什么MOS管逻辑门的结构远远比三极管逻辑门要复杂:因为在mos管电路中我们不希望发生VDD高电平→VSS接地低电平的短接。我们希望所有逻辑门只输出VDD或VSS中的一个。
                          ——所以我也是直到开始写本篇帖子才逐渐意识到,异星工厂里的信号电路永远不存在“短路”,这是因为工厂中算术运算器“信号=0”的状态更像一种二极管或传输门TG(Transmission Gate)的“高阻抗”状态,而非mos管逻辑门的“低电平VSS”状态:



                          虽然惜字如金的《图灵完备》中从未介绍过,但我很确信上图这个“Switch”开关元件就是大家常说的“传输门TG”——而它是唯一一个可以输出“高阻态”的mos管元件。而当你需要把做好的各种模块接入总线时,一定会需要用到它的。
                          ↑↑↑↑在《图灵完备》中,这样的异或门XOR结构就更接近《异星工厂》中信号电路的本质了——
                          【《异星工厂》中的信号=0并不是“低电平VSS”,而是“高阻态”】。也就是说异星工厂的信号电路本质是OC门——Open Collector Gate,集电极开路门(*基于三极管的逻辑门)。它只能输出“高电平”和“高阻态”,默认做好了带电阻接地,所以工厂里的运算器也永远不会过载或短路烧毁......
                          ——我不知道你怎么想,但是在我查到这些资料时有一点小小的失落:如此看来,《编码的奥秘》中所有逻辑门都是基于OC门的,所以其实它们的底层结构和原理远远不如mos管电路复杂(书中搭或门OR GATE只用了两个继电器和一个灯泡(电阻),但现实世界中的IC电路则至少需要6个mos管来搭或门OR GATE来防止VDD→VSS短接)。而我大费周章搭出看似复杂的电路,其实也根本不是mos管电路的真实样貌。
                          ......但这大概也没什么大不了的,毕竟计算机架构首先应该站在【逻辑】和【布尔代数】的基础上,而对于如何实现“逻辑”则没有硬性要求。说实在的只要能实现同构的逻辑,不管我用mos管还是三极管、机械臂还是传送带、红石电路还是水流电路、继电器还是查找表,我想我们都能做出功能一样强大的冯诺依曼机器。(当然请忽略不同结构带来的不同延迟,,请别杠我TAT,,我不是为了效率或者装比才来研究计组的,我只是单纯好奇朝夕相处的电脑到底是如何运行的TAT。。)
                          求知欲和好奇心驱使我前进至此,那么我还会继续前进下去。
                          ——虽然认识到《异星工厂》中的信号电路只能做带电阻接地的三极管电路和OC门逻辑而很难复现mos管电路和三态门。但计组的逻辑电路结构、解决问题的思维一脉相承。接下来我将从上古程序员大佬Charles Petzold手中接过薪火,继续尝试复现《编码的奥秘》中所有的结构——直到有一天我能真正做出一台图灵完备的计算机。


                          IP属地:浙江20楼2024-06-21 19:06
                          回复
                            【☎第三章附录3,如何优化《异星工厂》中的逻辑电路延迟?】
                            说是优化,但其实只是以信号电路特性的角度出发,从我们造出金碧辉煌的依托答辩结构中剔除所有不需要的答辩罢了()。 作为附加内容不会特别深入到算法层面(比如用移位优化乘法,用德摩根律优化按位操作,用查表优化加减法等),主要只涉及如何优化逻辑电路的延迟。
                            总结了一下,我主要以以下几条原则来优化工厂里的逻辑电路延迟:
                            1,如果把三极管的VDD供电端也看作布尔值输入端,那么它本身就相当于一个与门(是的,“与门”其实也常用作“单路开关”)。再加上工厂的信号电路永远不会短路/没有噪音/没有信号丢失/没有衰减,且默认带电阻接地;所以我们上面用两个判断器搭的“三极管”实际上是个“传输门”。在某些情况下完全可以用这个传输门替代与门。
                            2-1,【并联三极管结构】(或门/与非门)的门延迟通常都比【串联三极管结构】(与门/)的门延迟更低。且并联三极管逻辑门的各个引脚延迟都是一致的,都是一个逻辑门的延迟T。而串联三极管结构因为串联次序的不同,不同针脚之间可能会有n tick的延迟差异,总延迟会在T~T+n之间波动(n是你串联三极管的个数)。
                            2-2,所以我们可以用【德摩根律】和【单引脚取反】来大幅简化逻辑门,甚至基本可以把所有逻辑门都简化成并联三极管的结构,以此来降低延迟;或者得到一个更加稳定可控的延迟。
                            *(3,虽然一般是非法操作,但在《异星工厂》中你可以把n个输出引脚直接并联在一起来替代或门OR GATE。【*但要时刻记住,在《图灵完备》和现实世界mos电路里不可以这样做!】)
                            ——但考虑到,lz我希望能在《异星工厂》中做出一个可以在《图灵完备》里正常运行、完全同构的逻辑电路,lz我将主要以前几条原则来优化逻辑电路,括号里的第3条仅作为演示——实际上你不应该在任何地方随意并联逻辑门的输出。
                            因为加法器延迟最高的元件是XOR异或门,延迟是与门的两倍。所以优先考虑优化XOR元件。
                            根据上一章结尾的分析,一个开关(传输门)实际上相当于一个与门,而非门开关则实际上相当于一个定制与门:

                            (*↑↑↑左下角定制与门引脚画反了,,算了不重要==)
                            而因为传输门的输出有三种:0(VSS)、1(VDD)、0(高阻抗),传输门的输出可以直接并联(*但要确保不会在并联后的总线上同时输出VSS和VDD,否则还是会短路)。
                            ↓试一下,在图灵完备中这个结构是可以运行的:

                            然后用开关(TG传输门)替换AND与门,这样就可以并联传输门的输出:


                            ↑↑↑但唯一的缺点是当输出同时为1时输出的是高阻抗而不是VSS。可以再加两个开关,实现“A=1且B=1时,输出VSS”:


                            ↑↑↑可以看到,正常输出!当A=B时,总线上总有引脚可以输出接地电压0=VSS。这个XOR门正常运转,且延迟只有4。
                            试着在异星工厂里应用一下:

                            成功!延迟只有3~4tick,甚至可以和延迟最低的NAND门一战!
                            因为我们在工厂里造出的元件不区分VSS和高阻抗,所以只使用简单结构xor即可,不需要我们上面在图灵完备里优化过的复杂结构xor。但要注意这个xor比较特殊,它【没有直接与电源总线VDD连接】。
                            它是一个纯机械开关,不需要电源总线来驱动。但如果没有布尔输入也永远不会启动。


                            ↑↑↑顺手做一个XNOR同或门。原理同上,传输门输出直接并联来组个小总线,然后把NOR和AND分别拆分成基于传输门的结构,最后补一个传输门用于输出VSS,大功告成!

                            试了一下,如果想要实现低延迟XNOR,很难不借助非门来完成“A=0且B=0时输出1”的逻辑。在XOR的逻辑之上使用非门总会让延迟超过5tick。所以最终延迟最低的XNOR同或门组成方式只能是并联NOR和AND。
                            这么着急弄XNOR是为了以后做超前进位加法器CLA。图灵完备里XNOR延迟比XOR低2tick,依此可以把大量AND串联运算转化为NAND并联运算,大幅降低总延迟。不过异星工厂中因为电路特性,反而是XOR延迟比XNOR低2tick。希望能据此做出延迟更低的加法器。
                            敬请期待。


                            IP属地:浙江22楼2024-07-10 10:58
                            回复
                              【☎第三章附录4,RCA的关键路径延迟到底是多少】
                              这一章恐怕是我准备得最久的,因为这涉及《图灵完备》和《编码》都跳过了的内容——理论上元件延迟的最大值【关键路径】。《异星工厂》的所有元件自带1tick延迟,所以延迟问题变得无法逃避。为了研究清楚RCA的关键路径延迟,lz花了一个月才完全想明白。
                              (*不过希望各位明白这依然属于附录内容。这几个月我在反省写了这么多优质内容没人看,有可能是因为附录包含大量lz尚且没有学透的进阶知识,lz过于繁琐的解释劝退了大部分看客,而主要的章节里我们却还迟迟没有进入基础的存储器设计章节。
                              所以我保证这是最后一章冗长的附录,且尽量做到言简意赅。等本章结束,下一章我们立即进入锁存器原理笔记,教大家如何初步设计出随机存储器Random Access Memory,a.k.a. RAM。)


                              观察上图。图1里我们用《编码的奥秘》中的异或门/与门全加器来构建8位加法器RCA,图2里我们用《图灵完备》里打包好的全加器元件(ADD)来构建8位加法器RCA。图里天蓝色的线是进位线,也是理论上的关键路径(延迟最大的路径),我们至少要途径天蓝色路径上的所有元件才能得到稳定的输出。
                              但问题来了,上图中两个8位加法器RCA的结构完全相同,为什么延迟差了这么多呢?图1我们直接用门电路来做RCA,延迟只有36tick;但图2我们用游戏打包好的全加器Full Adder来做RCA,延迟却有64tick。
                              为什么延迟差了几乎两倍呢?

                              这里首先前情提要一下,四个基础逻辑门(NAND、NOR、AND、OR)的【门延迟】都是2tick,而同或门XOR和异或门XNOR因为使用了3个基础逻辑门,所以XOR和XNOR的【门延迟】是4tick。(同理三输入AND门因为串联了两个AND,所以延迟也是4tick。)

                              所以简单计算一下就能知道,上图全加器的【关键路径延迟】是两个XOR门,全加器想要得到稳定的输出,最小延迟是8tick。那么串联8个全加器,理论上延迟就应该是64tick啊?
                              那么现在我们就可以提出一个更进一步的问题:
                              【串联8个全加器,理论上的最大延迟就应该是64tick。那么本楼第一张图的36tick延迟到底是怎么来的呢?】
                              lz为了找到这个问题的答案花废了一番精力。而最先帮我问出问题的,居然是《异星工厂》。。
                              lz经过了上面的推理,一直认为影响8位加法器RCA延迟的最大因素是异或门XOR的延迟。所以在上个月写完如何优化XOR延迟的帖子后就兴冲冲地去用延迟更低的XOR重新做了个加法器,结果发现,,,

                              算上2进制到10进制的转码器延迟,优化前RCA延迟32tick,优化后RCA延迟30tick。两次的延迟都远不及lz最初计算的大于100tick的延迟。
                              根据《编码的奥秘》在异星工厂中复现出的全加器FA电路,最大延迟有12tick(也就是两个XOR门的延迟)。那么8位加法器RCA完成一轮8位二进制计算至少需要12×8=96tick延迟,再加上10进制-2进制转码和七段管显示,保守估计100tick绝对是有的。但为什么实际上跑出来延迟只有32tick呢?



                              再来仔细看一下这个全加器,仔细计算一下它的延迟。
                              有没有发现,得到加和位SUM的输出,至少要XOR+XOR=8tick的延迟
                              然后得到进位位CAR的输出,至少要XOR+AND+OR=8tick的延迟...对吗?
                              错!虽然全加器FA的A、B输入都要8tick延迟,但是串联全加器用到的关键路径却并不包含XOR门,所以一个全加器实际上只有AND+OR=4tick的延迟!!!:

                              仔细观察上图天蓝色的关键路径,你会发现byd,串联全加器,关键路径上居然一个XOR都没有!!!!

                              是的,计算开始后4tick,所有1位全加器FA的首个XOR都已经完成了计算,接下来整个8位加法器RCA上延迟最高的关键路径上只有8个AND和8个OR。所以RCA的实际【关键路径延迟】应该等于XOR+8×(AND+OR)=36tick!!(见上图中【天蓝色的线】,这条线就是RCA的实际关键路径。)


                              IP属地:浙江25楼2024-08-26 06:09
                              回复