<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>MIT Course on MT&#39;s blog</title>
    <link>https://rmtt.github.io/zh/tags/mit-course/</link>
    <description>Recent content in MIT Course on MT&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh</language>
    <lastBuildDate>Wed, 09 Mar 2022 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://rmtt.github.io/zh/tags/mit-course/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>MIT 6.s081(Operating System)</title>
      <link>https://rmtt.github.io/zh/posts/mit-os/</link>
      <pubDate>Wed, 09 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/mit-os/</guid>
      <description>&lt;h1 id=&#34;mit-os&#34;&gt;MIT OS&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址: &lt;a href=&#34;https://pdos.csail.mit.edu/6.S081/2020/schedule.html&#34;&gt;https://pdos.csail.mit.edu/6.S081/2020/schedule.html&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;在拖沓了许久之后, 终于OS给看完了. 总体来说质量很不错, 设计的lab都很好, 理清了不少底层的概念.&lt;/p&gt;
&lt;h2 id=&#34;体验&#34;&gt;体验&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;个人觉得OS课程的lab至关重要, 这也是MIT 6.s081做得非常好的点之一, 他们的lab确实做到了由浅入深.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;理论知识是围绕xv6来讲解, 同时后期开始讲解OS的一些经典paper, 这些可以让自己对OS的学术领域有一个基本的了解.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;然后lab大部分都是修改xv6, 因为xv6的代码非常简洁, 所以修改一般都比较轻松. 难的是OS里面一个很小的细节可能要debug很久.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;加深了对所谓并发的理解, 多线程的lab是设计一个用户空间的&amp;quot;线程调度器&amp;quot;, 写完之后感觉对多线程/多进程的概念更清晰了, 虽然我觉得这里的多线程更像是协程.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;学习了一些经典的技术: copy-on-write, mmap, Read-Copy-Update&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;看到meltdown的时候有点激动, 原作者是怎么想到这个做法的 (&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;看了MIT 6.004之后惊叹数字电路上那么多精妙的设计, 现在看来OS里面也有很多精妙设计, 或者说是体系架构里面. 虽然MIT 6.004学习了页表, 但在OS里面可以看到页表的各种用法, 不得不佩服页表这个发明.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;知道了微内核和宏内核的区别&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;之前觉得一个CPU就是一个通用图灵机, 它的输入也是各种图灵机, 而其中之一就是OS, 而OS本身应该也是一个通用图灵机, 所以本质上OS是通过套娃提高了抽象层次, 简化了操作.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;现代OS的几个关键点应该是并发和安全. 对于并发, 常见的说法是多进程和多线程, 但实际上都是一回事, 只不过多线程是共享一个address space. 对于安全, 用页表来实现address space的隔离是个绝妙的idea, 虽然meltdown的出现吓到了不少人, 但这实际上也跟intel自己的micro-architecture实现有关, 好在现在已经可以在硬件层面修复了(不然还是得把用户空间和内核空间分开, 会拉低大概5%的性能).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;锁可以解决数据冲突, 但会降低并行性, 过度的使用等于没有并行.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Parallel Processing</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-21/</link>
      <pubDate>Thu, 16 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-21/</guid>
      <description>&lt;h1 id=&#34;parallel-processing&#34;&gt;Parallel Processing&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址: &lt;a href=&#34;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c21/c21s1/&#34;&gt;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c21/c21s1/&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章讲的是各种并行方案.&lt;/p&gt;
&lt;h2 id=&#34;并行&#34;&gt;并行&lt;/h2&gt;
&lt;p&gt;并行大体上有如下3种:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;指令级并行(ILP)&lt;/li&gt;
&lt;li&gt;数据级并行(DLP)&lt;/li&gt;
&lt;li&gt;线程级并行(TLP)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;指令级并行&#34;&gt;指令级并行&lt;/h3&gt;
&lt;p&gt;指令级并行是让流行线的每个阶段尽可能同时执行多条指令.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-21/superscalar-processor.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;数据级并行&#34;&gt;数据级并行&lt;/h3&gt;
&lt;p&gt;数据级并行主要是指像向量加法这种计算, 天生就能拆开运算的! 只需要提供多个ALU就行了, 目前主要是由GPU来做.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-21/data-level-parallelism.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;线程级并行&#34;&gt;线程级并行&lt;/h3&gt;
&lt;p&gt;首先介绍一下阿姆达尔定律:&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-21/amdahl-law.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;一个线程就是在一个core上执行的计算任务.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Using multiple independent cores to execute a parallel task is called thread-level parallelism (TLP), where each core executes a separate computation “thread”.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-21/thread-level-parallelism.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;不同的Core之间是通过同一个main memory来交换数据(还有更高效的MPI), 而且每个core都有自己的cache.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-21/multi-core-caches.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;为了保证数据的一致性, 在cache和内存之间也有一条bus来监测cache的变化和同步.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;例如MESI protocal: &lt;a href=&#34;https://en.wikipedia.org/wiki/MESI_protocol&#34;&gt;https://en.wikipedia.org/wiki/MESI_protocol&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>System-level Communication</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-20/</link>
      <pubDate>Thu, 16 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-20/</guid>
      <description>&lt;h1 id=&#34;system-level-communication&#34;&gt;System-level Communication&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址: &lt;a href=&#34;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c20/c20s1/&#34;&gt;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c20/c20s1/&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章主要讲的是系统间通信, 按现在来讲就是总线(BUS).&lt;/p&gt;
&lt;p&gt;前面讲了很多硬核的物理知识, 证明了单一总线因为传输线反射的问题, 无法做到高频.&lt;/p&gt;
&lt;p&gt;后面介绍了PCIe, 原来PCIe是受Network的启发, 也搞了一套点对点的通信协议, 跟网络一样分了几层, 数据也是包装成packet发出去.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-20/pcie.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;跟网络一样, PCIe也可以有多种top, 比如环形, 树形等等.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Concurrency and Synchronization</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-19/</link>
      <pubDate>Wed, 15 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-19/</guid>
      <description>&lt;h1 id=&#34;concurrency-and-synchronization&#34;&gt;Concurrency and Synchronization&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址: &lt;a href=&#34;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c19/c19s1/&#34;&gt;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c19/c19s1/&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章主要是讲进程间通信(IPC), 不过是从硬件的角度来看.&lt;/p&gt;
&lt;p&gt;IPC里面常用的信号量, 其实也只是在共享内存中存入了一个数字, 而所谓的lock, 也只是数量为1的semaphore.&lt;/p&gt;
&lt;p&gt;但是如果不同core上的进程同时对同一个内存地址进行写操作的话, 会产生冲突吗? 这个貌似是内存或者总线去解决的, 目前还没找到具体实现, 先mark一下.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-19/hardware-support-semaphore.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;IPC的一个重要问题是deadlock, 比如进程A和进程B:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 进程A
wait(x)
wait(y)
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 进程B
wait(y)
wait(x)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;当进程A执行完&lt;code&gt;wait(x)&lt;/code&gt;后, 进程B被调度, 而且执行了&lt;code&gt;wait(y)&lt;/code&gt;, 显然这两个进程永远都无法结束.&lt;/p&gt;
&lt;p&gt;一个比较直观而且简单的方案是对IPC中需要用到的信号量进行排序, 在进程&lt;code&gt;wait&lt;/code&gt;时, 总是先&lt;code&gt;wait&lt;/code&gt;顺序在前的信号量.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Devices and Interrupts</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-18/</link>
      <pubDate>Tue, 14 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-18/</guid>
      <description>&lt;h1 id=&#34;devices-and-interrupts&#34;&gt;Devices and Interrupts&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址: &lt;a href=&#34;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c18/c18s1/&#34;&gt;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c18/c18s1/&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章引入外设, 讲解了round-robin调度算法的优缺点.&lt;/p&gt;
&lt;p&gt;首先, &amp;ldquo;IO阻塞&amp;quot;的本质是什么?&lt;/p&gt;
&lt;p&gt;当IO请求没有收到回复时, OS在调度到该进程时还是会继续执行等待IO的指令.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-18/readkey-svc-3.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;虽然每次调度到正在等待IO的进程也花不了多少条指令, 但还是要切换上下文啥的, 为了提高轮询的效率, 我们可以想办法让这些等待IO的进程不会被调度.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-18/readkey-svc-4.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;我们可以将进程分为不同的状态, 只有状态为0的进程可以被正常调度.&lt;/p&gt;
&lt;p&gt;当进程开始等待IO时, 便用 &lt;code&gt;sleep(id)&lt;/code&gt; 来改变进程的状态, 其中 &lt;code&gt;id&lt;/code&gt; 相当于这个IO资源的标识符, 比如可以有多个进程都在等待键盘的输入. 当相应的IO时间响应后, 再根据这个&lt;code&gt;id&lt;/code&gt;去恢复进程的状态.&lt;/p&gt;
&lt;p&gt;加了状态的轮询调度感觉也挺合理的!&lt;/p&gt;
&lt;p&gt;那么, 轮询能满足所有的任务吗? 当然是不能!&lt;/p&gt;
&lt;p&gt;某些特殊的系统, 例如车载系统, 会有一些特别紧急的中断必须要优先执行, 比如紧急制动啥的. 按我们之前的设计, 中断都是在内核态中执行, 而内核态会禁用中断, 所以当需要紧急制动时, 巧好有一个耗时较长的中断在执行, 可能就会引发悲剧!&lt;/p&gt;
&lt;p&gt;像这种每个中断都要及时响应或者在一定时间内执行完成的, 一般称为实时调度.&lt;/p&gt;
&lt;p&gt;本章介绍了弱优先级抢占和强优先级抢占两种调度算法. 区别就是当前的中断是否能被高优先级的中断中断 (&lt;/p&gt;</description>
    </item>
    <item>
      <title>Virtualizing the Processor</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-17/</link>
      <pubDate>Mon, 13 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-17/</guid>
      <description>&lt;h1 id=&#34;virtualizing-the-processor&#34;&gt;Virtualizing the Processor&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址: &lt;a href=&#34;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c17/c17s1/&#34;&gt;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c17/c17s1/&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章讲了CPU的&amp;quot;虚拟化&amp;quot;, 不过这里的&amp;quot;虚拟化&amp;quot;是指在同一个CPU上执行多个程序, 并且互不干扰, 重点当然就是虚拟内存和MMU啦.&lt;/p&gt;
&lt;p&gt;现代CPU都在硬件上实现了内核态和用户态, 所以无法单纯靠软件来实现内核态和用户态的切换, 而是要靠CPU的中断来实现.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-17/timer-interrupts.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;当Timer发起一个中断时, 我们调用OS的schedule程序来切换用户程序的上下文, 那么具体需要切换哪些内容呢? 常见的就是所有寄存器的内容, MMU的Context和Page Directory/Page Map的base pointer, 还有其他各种外设的状态等等, 比如该用户程序的输入应该在哪个tty.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-17/simple-timesharing-scheduler.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;这种代码+上下文+所有相关资源的集合便是一个进程(Process).&lt;/p&gt;
&lt;p&gt;众所周知, OS提供的底层接口都是在内核态运行, 因为内核态不会受中断的干扰, 所以能够保持调度器一直能正常运行. 但是CPU是禁止程序从用户态直接转移到内核态的, 唯一的办法便是通过中断或者异常.&lt;/p&gt;
&lt;p&gt;现代的CPU都运行设置部分中断和异常的Handler, 当用户态程序有中断或异常产生时, 便会跳转到相应的Handler去执行, 而且会无视用户态/内核态的区别. 所以, OS可以指定自己的异常处理Handler, 对于每一个系统调用, 都分配一个illegal-opcode就可以啦!&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-17/illop-handler.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Virtual Memory</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-16/</link>
      <pubDate>Sun, 12 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-16/</guid>
      <description>&lt;h1 id=&#34;virtual-memory&#34;&gt;Virtual Memory&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址: &lt;a href=&#34;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c16/c16s1/&#34;&gt;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c16/c16s1/&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章主要讲了从硬盘加载数据到主存的策略, 从而引出了虚拟内存和页表.&lt;/p&gt;
&lt;h2 id=&#34;extending-the-memory-hierarchy&#34;&gt;Extending the memory hierarchy&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/extending-the-memory-hierarchy.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/impact-of-enormous-miss-penalty.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;virtual-memory-1&#34;&gt;Virtual Memory&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/virtual-memory.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/paging.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/demand-paging.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;page-map&#34;&gt;Page Map&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/simple-page-map-design.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/example-vtop.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/page-fault.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/example-page-fault.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;translation-look-aside-buffer-tlb&#34;&gt;Translation look-aside buffer (TLB)&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/tlb.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/mmu-address-translation.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/mmu-with-tlb.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;context&#34;&gt;Context&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/contexts.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/memory-management-and-protection.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/multi-level-maps.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/rapid-context.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/best-of-both-worlds.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-16/virtual-memory-summary.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Pipelining the Beta</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-15/</link>
      <pubDate>Fri, 10 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-15/</guid>
      <description>&lt;h1 id=&#34;pipelining-the-beta&#34;&gt;Pipelining the Beta&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址: &lt;a href=&#34;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c15/c15s1/&#34;&gt;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c15/c15s1/&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章主要是讲如何讲前面做的Beta cpu流水线化, 以及如何解决流水线中会遇到的数据冲突/控制逻辑冲突等等.&lt;/p&gt;
&lt;p&gt;PS: 这章内容是真多 (&lt;/p&gt;
&lt;h2 id=&#34;流水线化&#34;&gt;流水线化&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/pipelined-implementation.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/too-long-course.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;冲突&#34;&gt;冲突&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/pipeline-hazards.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;常见的冲突有两种,即数据冲突和控制逻辑冲突. 数据冲突是指当前指令需要的数据暂时还没有写回寄存器或者内存, 控制逻辑冲突是指当要跳转的指令的地址还没计算出来时, 下一个指令的地址应该是多少.&lt;/p&gt;
&lt;h3 id=&#34;数据冲突&#34;&gt;数据冲突&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/data-hazards.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/resolving-data-hazards.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;strategy-1---stall&#34;&gt;Strategy 1 - Stall&lt;/h4&gt;
&lt;p&gt;Stall就是当指令运行到流水线的某一个阶段时, 如果检测到需要的数据还没有写回寄存器或者内存, 就在这个阶段阻塞住, 而且前面阶段的指令也要同时阻塞住,  阻塞的同时给下一阶段的IR寄存器输出NOP.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/resolving-data-hazard-1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/stall-logic.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/resolving-data-hazard-2.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;strategy-2---bypass&#34;&gt;Strategy 2 - Bypass&lt;/h4&gt;
&lt;p&gt;虽然每个指令只有在最后的Write Back阶段才会把数据写回寄存器或者内存, 但相关的值在前面的阶段就已经计算出来了, 所以可以直接把这些值bypass到可能需要的地方.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/bypass-logic.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/fully-bypassed-pipeline.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;控制逻辑冲突&#34;&gt;控制逻辑冲突&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/control-hazard-1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/control-hazard-2.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/resolving-control-hazards.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Stratege 1和2跟前面数据冲突的处理一样, 这里只记录一下第三个做法, 也就是分支预测.&lt;/p&gt;
&lt;h4 id=&#34;分支预测&#34;&gt;分支预测&lt;/h4&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/resolving-hazards-with-speculation.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/branch-prediction.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;exception-and-interruption&#34;&gt;Exception and Interruption&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-15/exception-and-interrupt-logic.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Caches and the Memory Hierarchy</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-14/</link>
      <pubDate>Tue, 07 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-14/</guid>
      <description>&lt;h1 id=&#34;caches-and-the-memory-hierarchy&#34;&gt;Caches and the Memory Hierarchy&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址：https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c14/c14s1/&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章主要讲了&lt;em&gt;SRAM&lt;/em&gt;、&lt;em&gt;DRAM&lt;/em&gt;、Flash、HDD的原理和现代CPU的缓存架构。&lt;/p&gt;
&lt;h2 id=&#34;存储设备&#34;&gt;存储设备&lt;/h2&gt;
&lt;p&gt;PS: 片上的存储设备一般都有bitline和wordline, wordline用来激活指定的存储单元，bitline用来读/写数据。&lt;/p&gt;
&lt;h3 id=&#34;sram&#34;&gt;SRAM&lt;/h3&gt;
&lt;p&gt;SRAM跟寄存器比较像，都是用正反馈是保持电压。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/static-ram.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/sram-cell.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/sram-read.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;sram-write&#34; loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/sram-write.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;dram&#34;&gt;DRAM&lt;/h3&gt;
&lt;p&gt;DRAM是使用电容来保持电压，体积更小，所以容量更大，但访问速度比SRAM慢，而且需要定时刷新存储的数据。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/dram-cell.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/dram-write-and-read.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;flash&#34;&gt;Flash&lt;/h3&gt;
&lt;p&gt;Flash是使用MOSFET来存储数据，在栅极下加了一层绝缘体，讲电子导入绝缘体，然后根据绝缘体的带电大小来决定数据。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/flash.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;hard-disk&#34;&gt;Hard Disk&lt;/h3&gt;
&lt;p&gt;硬盘（这里指机械硬盘）是用磁化来存储数据。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/hard-disk.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;内存系统&#34;&gt;内存系统&lt;/h2&gt;
&lt;p&gt;在现代CPU的架构中，主存一般是速度相对较慢但是体积更小的DRAM组成。不过CPU不会直接跟主存交换数据，在中间可能会有其他几层SRAM来充当缓存，以降低内存的平均访问时间。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/the-memory-hierarchy.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;但从编程的角度看，有这样两种选择。一是完全隐藏缓存的细节，这样写程序时便可以把内存当成一个单独的设备使用；二是公开缓存细节，由programmer去决定哪些数据放在缓存，哪些放在主存。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/memory-hierarchy-interface.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;现在除了超算，基本都是选择隐藏缓存的细节。&lt;/p&gt;
&lt;h2 id=&#34;cache策略&#34;&gt;Cache策略&lt;/h2&gt;
&lt;p&gt;既然要隐藏缓存的细节，那么需要用硬件或者软件来自动控制哪些数据应该放在缓存，当缓存命中时，直接返回给CPU，未命中时，缓存应当自主去主存读数据然后缓存起来并返回给CPU. 下面来讨论一下具体的缓存策略.&lt;/p&gt;
&lt;h3 id=&#34;前提&#34;&gt;前提&lt;/h3&gt;
&lt;p&gt;在模拟测试中, 可以发现这样一个事实:&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/the-locality-property.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/memory-reference-patterns.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;direct-mapped&#34;&gt;Direct-Mapped&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/direct-mapped.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/block-size.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;full-associative&#34;&gt;Full-Associative&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/full-associative-cache.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;set-associative&#34;&gt;Set-Associative&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/n-way-associative-cache.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;policies&#34;&gt;Policies&lt;/h2&gt;
&lt;h3 id=&#34;replacement-policies&#34;&gt;Replacement Policies&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/replacement-policies.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;write-policy&#34;&gt;Write Policy&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/write-policy.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/write-back.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-14/cache-summary.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building the Beta</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-13/</link>
      <pubDate>Sat, 04 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-13/</guid>
      <description>&lt;h1 id=&#34;building-the-beta&#34;&gt;Building the Beta&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址：https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c13/c13s1/&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章主要是介绍如何实现一个beta处理器，应该是一个实验课，所以没啥要记录的（&lt;/p&gt;
&lt;p&gt;PS: 对着一堆逻辑门Debug了一整天终于把所有测试都通过了！累死人（&lt;/p&gt;
&lt;p&gt;Lab地址：https://computationstructures.org/exercises/beta/lab.html&lt;/p&gt;</description>
    </item>
    <item>
      <title>Compilers</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-11/</link>
      <pubDate>Wed, 01 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-11/</guid>
      <description>&lt;h1 id=&#34;compilers&#34;&gt;Compilers&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址：https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c11/&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章就是讲了一些简单的编译原理的内容，内容比较简单，就不多记录了。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;控制流图(CFG)是常用的IR&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-11/modern-compilers.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Procedures and Stacks</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-12/</link>
      <pubDate>Wed, 01 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-12/</guid>
      <description>&lt;h1 id=&#34;procedures-and-stacks&#34;&gt;Procedures and Stacks&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址：https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c12/c12s1/&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章的主要内容是讲解了为什么需要Procedures和Stacks, 应该是第一次这么清晰的理解栈（&lt;/p&gt;
&lt;h2 id=&#34;procedures&#34;&gt;Procedures&lt;/h2&gt;
&lt;p&gt;Procedures就是一组指令的集合，目的是为了重用指令，节约空间。当然，在高级变成语言里面都叫函数或者方法。&lt;/p&gt;
&lt;p&gt;这里从汇编的角度来考虑如何实现Procedure, 一个最简单的办法是将Procedure在编译的时候展开，这样虽然重用了指令，但是并没有节省空间，而且无法递归调用！&lt;/p&gt;
&lt;p&gt;另一个比较好的做法是记录Procedure的开始位置，在需要调用的时候只需要把PC设置成Procedure的地址就可以了，这样即能重用指令，也能节省空间，还能递归调用！不过问题也随之而来，当Procedure运行完后，如何知道应该返回到哪里继续执行呢？Procedure所需要的参数该如何传递呢？&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/implementing-procedures.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;首先，在执行分支指令的时候，会自动计算$PC + 4$并存在指定的寄存器，所以我们可以在Procedure里面拿到要返回的地址。其次，我们可以固定几个寄存器来传递参数，比如R3 ~ R6。这样做的话，似乎可以正确执行procedure, 但是，一旦有递归调用，那这些指定的寄存器都会被覆盖，当递归最后一层结束后返回上一层时，整个调用链就“断掉”了！&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/procedure-calling-concention.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/procedure-linkage-first-try.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;而且，当procedure的参数变多时，寄存器根本不够用！&lt;/p&gt;
&lt;h2 id=&#34;stacks&#34;&gt;Stacks&lt;/h2&gt;
&lt;p&gt;有了上述的问题之后，让我们再来思考一下procedure的调用需要那些工作来完成。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/procedure-storage-needs.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;首先我们需要知道Procedure的参数、返回值以及结束后PC的值，其次是procedure里面的局部变量应该存在哪里，因为在procedure执行完后，这些局部变量应该要被完全清除。我们的目标是在procedure执行过程中不会影响caller的数据，在执行完成后回到caller的时候，各个寄存器除了存放返回值的那个外，都应该是调用procedure前的状态！我们把这些在每次procedure调用时都需要记录的东西称为Activation Record。&lt;/p&gt;
&lt;p&gt;下图演示了在递归调用时，Activation Record应该是如何变化的。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/activation-record.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;这不就是先进后出的Stack嘛！然后就是一系列的有关于Stack的定义了。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/we-need-a-stack.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/stack-implementation.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/stack-management-macros.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;stack-frame&#34;&gt;Stack frame&lt;/h2&gt;
&lt;p&gt;现在我们用Stack来解决之前的问题了！&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/solving-procedure-linkage-problems.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;我们可以把procedure的参数，局部变量，以及procedure要使用的寄存器的内容都存到stack了！除此之外，我们还需要一些特殊的记录，比如procedure执行完后该返回的地址以及一个可以随时在栈中寻址的指针。然后，约定一个顺序来存这些数据就可以了！&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/stack-frame-as-activation-record.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;栈中一个procedure的相关数据都在连续的区块中，我们称这个区块为stack frame.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/stack-frame-details.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/arguments-order-and-bp-usage.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;然后约定好caller和callee的职责，就可以开心地使用procedure啦！&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/procedure-linkage-contract.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/procedure-linkage-template.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;compile-procedure&#34;&gt;Compile procedure&lt;/h2&gt;
&lt;p&gt;如下是将C的一个递归调用编译成汇编的例子。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/procedure-factorial.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/recursion.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/stack-detective.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-12/procedure-stack-summary.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Assembly Language</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-10/</link>
      <pubDate>Mon, 29 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-10/</guid>
      <description>&lt;h1 id=&#34;assembly-language&#34;&gt;Assembly Language&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址: &lt;a href=&#34;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c10/c10s1/&#34;&gt;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c10/c10s1/&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;汇编语言是对指令集的抽象，用一些单词的缩写来替代指令集的opcode, 从而更容易记忆和理解。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-10/assembly-language.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;本课程中使用的汇编语言叫&lt;em&gt;USAM&lt;/em&gt;，课程Lab里面有详细的cookbook, 就不再记录了，下面主要记录图灵机相关的内容。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-10/assembly-language-summary.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;fsm的局限&#34;&gt;FSM的局限&lt;/h2&gt;
&lt;p&gt;FSM是一个很强大的计算模型，前面章节中我们已经用电路实现了通用FSM, 那么FSM是否可以计算所有能用数字设备计算的功能或者说函数呢？&lt;/p&gt;
&lt;p&gt;答案是不能，比如简单的括号匹配。因为FSM要靠状态来记住&lt;code&gt;(&lt;/code&gt;和&lt;code&gt;)&lt;/code&gt;的个数，当有一个长度无穷大的序列时，FSM便无法构造。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-10/fsm-limitation.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;为了解决这个问题，Alan turing提出了&lt;code&gt;图灵机&lt;/code&gt;的模型。&lt;/p&gt;
&lt;h2 id=&#34;图灵机&#34;&gt;图灵机&lt;/h2&gt;
&lt;p&gt;图灵机的核心还是FSM, 不过现在多了一条无限长的纸带，FSM可以通过存储在纸带上的符号来记录额外的信息，从而避免了状态数过多而无法构造FSM的问题。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-10/turing-machine.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;因为一段纸带上的符号可以被编码为一个整数，所以图灵机就是一个整数函数$y = TM_I(x)$。&lt;/p&gt;
&lt;p&gt;其中$I$是用来标识特定功能即有特定FSM的图灵机，我们可以将FSM的真值表编码成数字来表示$I$。&lt;/p&gt;
&lt;h2 id=&#34;churchs-thesis&#34;&gt;Church&amp;rsquo;s Thesis&lt;/h2&gt;
&lt;p&gt;$f(x) computable &lt;=&gt; for some k, all x f(x) = T_k[x]$&lt;/p&gt;
&lt;p&gt;该定理由图灵的老师Church提出，但目前并没有证明，不过已经被普遍接受（可能是还没找到反例吧）。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-10/computability.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;通用图灵机&#34;&gt;通用图灵机&lt;/h2&gt;
&lt;p&gt;对于不同的计算任务，其构造的FSM不同，所构造的图灵机便也不同，那么为了各种计算任务，就需要构造各种各样的图灵机（实际上只有FSM不同）。那么存在一种或者一个图灵机，能够计算所有图灵机能计算的函数吗？&lt;/p&gt;
&lt;p&gt;从21世纪的结果来看，当然是存在的！&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-10/the-universal-function.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;如上图所示，$U(k, j) = T_k[j]$是一个Universal Function, 实现这个函数的图灵机便是通用图灵机。&lt;/p&gt;
&lt;p&gt;实际上，这里的关键在于$k$。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-10/universality.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;$k$在这里是表示&lt;code&gt;program&lt;/code&gt;，理论上讲就是对FSM的编码，比如用FSM的真值表来编码，而从上层计算机的角度来讲的话，$k$就是可执行的二进制程序，而PC本身就是一个通用图灵机！通用图灵机的计算便是对$k$的interpret，实际上就是把$k$本身的计算步骤走一遍。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-10/coded-algorithms.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;现在的各种编码算法，实际上就是把一个FSM编码成整数从而输入给通用图灵机。&lt;/p&gt;
&lt;p&gt;不过由于内存的空间是有限的，所以实际中的计算机还是只能计算数据量不超过内存大小的任务。&lt;/p&gt;
&lt;h2 id=&#34;uncomputability&#34;&gt;Uncomputability&lt;/h2&gt;
&lt;p&gt;如下是一个不可计算函数的例子，也就是所谓的图灵停机问题。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-10/uncomputability.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-10/why-fh-is-uncomputable.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Designing an instruction set</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-09/</link>
      <pubDate>Wed, 24 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-09/</guid>
      <description>&lt;h1 id=&#34;designing-an-instruction-set&#34;&gt;Designing an instruction set&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址: &lt;a href=&#34;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c9/c9s1/&#34;&gt;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c9/c9s1/&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章用前8章所学的知识设计了一个简单的通用计算机，采用冯诺伊曼结构，即&lt;em&gt;main memory&lt;/em&gt; + &lt;em&gt;CPU&lt;/em&gt;，而CPU则主要由&lt;em&gt;datapath&lt;/em&gt;(即以ALU为主的计算电路)和&lt;em&gt;control logic&lt;/em&gt;(即用ROM和Register实现的FSM控制电路)。整体内容很简单，但是很好玩！&lt;/p&gt;
&lt;h2 id=&#34;datapaths-and-fsms&#34;&gt;Datapaths and FSMs&lt;/h2&gt;
&lt;p&gt;Let’s start by designing the logic that implements the desired computations — we call this part of the logic the “&lt;em&gt;datapath&lt;/em&gt;”.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-09/datapath-for-factorial.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;上图虽然实现了a和b的计算，但还不能控制其状态，即不能在b为0时结束循环，所以需要一个FSM来控制整个计算电路即datapath的状态。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-09/control-fsm-for-factorial.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-09/control-fsm-hardware.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;programmable-datapath&#34;&gt;Programmable Datapath&lt;/h2&gt;
&lt;p&gt;第一节中设计了一个可以计算介乘的datapath, 然后配上一个简单的FSM, 就可以完成计算任务。但实际中的计算任务有成千上万种，我们不能为每种任务都设计一个单独的datapath。&lt;/p&gt;
&lt;p&gt;首先每种计算都可以分解为ALU的几个基本计算类型(Arithmetic, Bool, Comparable, Shift)，所以就计算来说，一个ALU就差不多够用了。但有的任务可能需要更多的寄存器来保存中间结果，所以增加寄存器数量是必须的。如下是一个简单的可以进行通用计算的datapath.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-09/a-simple-programmable-datapath.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-09/a-control-fsm-for-factorial.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-von-neumann-model&#34;&gt;The von Neumann Model&lt;/h2&gt;
&lt;p&gt;在上一节的模型的基础上，冯诺伊曼引入了主存和输入/输出设备，从而执行数据量更大的计算任务，而且也可以有各种各样的输入输出设备，如下图所示。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-09/the-von-neumann-model.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;storage&#34;&gt;Storage&lt;/h2&gt;
&lt;p&gt;冯诺伊曼模型的要点是用主存来存储指令和数据，主存相对于寄存器来说，最主要的优点就是容量大，所以能存储很多条指令。假如一条指令是32位也就是4bytes的话，那么1KB就能存256条指令，1M就能存256000条！&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-09/stored-program-computer.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;在冯诺伊曼结构中，有一个专门的&lt;em&gt;PC&lt;/em&gt;寄存器，用来存储&lt;em&gt;下一条&lt;/em&gt;指令在主存中的地址。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-09/anatomy-of-von-neumann-computer.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;指令和指令集&#34;&gt;指令和指令集&lt;/h2&gt;
&lt;p&gt;指令就是用来告诉&lt;em&gt;control logic&lt;/em&gt;该干什么，指令集就是按同一标准设计的一大堆指令，可以控制&lt;em&gt;control logic&lt;/em&gt;干各种各样的事。指令集相关内容感觉没有太多需要记录的，所以就不记录啦。&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-09/beta-isa-summary.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Design Tradeoffs</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-08/</link>
      <pubDate>Thu, 18 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-08/</guid>
      <description>&lt;h1 id=&#34;design-tradeoffs&#34;&gt;Design Tradeoffs&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c8/c8s1/&#34;&gt;课程地址&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;本章从CMOS的电能消耗出发，讲如何减少不必要的能量损失，同时也讲了很多时间和空间的tradeoff.&lt;/p&gt;
&lt;h2 id=&#34;power-dissipation&#34;&gt;Power dissipation&lt;/h2&gt;
&lt;h3 id=&#34;电路优化的几个metrics&#34;&gt;电路优化的几个metrics&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/optimizing-your-design.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;cmos能耗&#34;&gt;CMOS能耗&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/cmos-static-power-dissipation.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/cmos-dynamic-power-dissipation.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/cmos-dynamic-power-dissipation-2.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;一个减小能耗的简单例子&#34;&gt;一个减小能耗的简单例子&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/how-can-we-reduce-power.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/fewer-transitions.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;carry-select-adder&#34;&gt;Carry-select Adder&lt;/h2&gt;
&lt;p&gt;设计一个N位的加法器，最直观的设计就是把N个全加器串联。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/adder-example.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;但是这样的$t_{PD}$是$\theta(N)$级别的。&lt;/p&gt;
&lt;p&gt;现在将一个32位的加法器分成两个16位的部分分别计算再组合，$t_{PD}$就差不多减小了一半。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/carry-select-adder.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;按这个思路一直二分下去，$t_{PD}$便能达到$O(\log n)$。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/32-bits-carry-select-adder.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;carry-lookahead-addercla&#34;&gt;Carry lookahead Adder(CLA)&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/faster-carry-logic.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;从$C_{out}$的计算公式中可以看出，一个FA的输入可以转换成3个变量$P$,$G$和$C_{in}$ ，其中只有$C_{in}$需要该位的前一位的$C_{out}$。&lt;/p&gt;
&lt;p&gt;如果知道了两个相邻位置的$P$和$G$，那么可以把这两位当作一个整体，计算出这个整体的$P$和$G$，这时$P$和$G$任然还保留着原来的性质，所以，我们可以用倍增来计算整个电路的$P$和$G$。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/carry-lookahead-adder.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;下图是一个8-bits的CLA的G&amp;amp;P generate的部分：&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/8-bit-cla-generate-G&amp;P.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;然后是计算Carry的方法：&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/8-bit-cla-carry-generation.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;完整版：&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/8-bit-cla-complete.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;multiplier&#34;&gt;Multiplier&lt;/h2&gt;
&lt;h3 id=&#34;binary-multiplication&#34;&gt;binary multiplication&lt;/h3&gt;
&lt;p&gt;就是普通的竖式乘法，但是要注意如果值是补码，那最高位的全值为$-2^{N-1}$而不是$2^{N-1}$。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/binary-multiplication.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/combinational-multiplier.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;如下是值为补码的情况：&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/complement-multiplication.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/complement-multiplier.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;pipelined-multiplier&#34;&gt;pipelined multiplier&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/pipelined-multiplier.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;虽然pipeline化了，但每个stage的$t_{PD}$还是$O(N)$的，主要问题在于要按行传递carry。&lt;/p&gt;
&lt;h3 id=&#34;carry-save-multiplier&#34;&gt;Carry-save multiplier&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/carry-save-multiplier.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;讲每行需要传递的carry降到下一行（反正都是加在同一列，所以对结果没影响），这样可以将每个stage的$t_{PD}$优化到$O(1)$，但是需要更多的行，也就是面积增加了。&lt;/p&gt;
&lt;h3 id=&#34;用时序电路减少面积&#34;&gt;用时序电路减少面积&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/sequential-logic-multiplier.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;求和-&amp;gt;移位-&amp;gt;求和。&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-08/design-tradeoff-summary.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Performance Measures</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-07/</link>
      <pubDate>Thu, 11 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-07/</guid>
      <description>&lt;h1 id=&#34;performance-measures&#34;&gt;Performance Measures&lt;/h1&gt;
&lt;p&gt;本章主要是讲&lt;em&gt;pipeline&lt;/em&gt;的原理以及如何将一般的逻辑电路转换为&lt;em&gt;pipeline&lt;/em&gt;，最后简单提到了一下异步电路和同步电路的区别。&lt;/p&gt;
&lt;h2 id=&#34;latency-and-throughput&#34;&gt;Latency and Throughput&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Latency&lt;/em&gt;: the delay from when an input is established until the output associated with that input becomes valid.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Throughput&lt;/em&gt;: The rate at which inputs or outputs are processed.&lt;/p&gt;
&lt;h2 id=&#34;pipelined-circuites&#34;&gt;Pipelined Circuites&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-07/back-to-circuits.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;如上图所示，在计算$P(X)$时，F和G一直处于空闲状态，那么有没有办法把这段时间利用起来呢？&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-07/pipelined-circuits.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;我们可以用寄存器来保持F和G的输出，从而在$P(X)$的工作时间内，可以让F和G去进行其他计算。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-07/pipelined-diagrams.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-07/pipeline-conventions.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;pipelining-methodology&#34;&gt;Pipelining Methodology&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-07/a-pipelining-methodology.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;如上是将一般逻辑电路pipeline化的一般步骤&lt;/p&gt;
&lt;h2 id=&#34;circuit-interleaving&#34;&gt;Circuit Interleaving&lt;/h2&gt;
&lt;p&gt;Pipeline的瓶颈在于$t_{PD}$最大的那个module, 我们可以用如下的方式将两个相同的module组合在一起，提高throughput.&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-07/circuit-interleaving.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-07/circuit-interleaving-timing.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-07/circuit-interleaving-timing-2.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-07/combine-techniques.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;异步及同步&#34;&gt;异步及同步&lt;/h2&gt;
&lt;p&gt;同一个module对于不同的输入，所需要的时间可能也不一样。按之前的CLK驱动来设计电路的话，计算CLK的时候需要用module的最长计算时间，才能保证正确性。但对于一些计算较快的输入，这样做肯定是浪费了时间的。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-07/control-structure-alternatives.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;上图展示了用同步和异步两种方式来实现一个简单的握手协议，对于异步电路来说，不再需要全局的CLK，所以效率非常高，但实际设计非常困难；对于同步电路来说，不再需要靠CLK来在module之间传输数据，效率也提高了，虽然还是在CLK上升沿才会有数据输入输出，但CLK不需要用最长计算时间的输入来计算了。&lt;/p&gt;
&lt;p&gt;这个简单的握手协议如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In phase 1, when the upstream stage has a new output and GOT-X is deasserted, it asserts its HERE-IS-X signal and then waits to see the downstream stage’s reply on the GOT-X signal.&lt;/li&gt;
&lt;li&gt;In phase 2, the downstream stage, seeing that HERE-IS-X is asserted, asserts GOT-X when it has consumed the available input.&lt;/li&gt;
&lt;li&gt;In phase 3, the downstream stage waits to see the HERE-IS-X go low, indicating that the upstream stage has successfully received the GOT-X signal.&lt;/li&gt;
&lt;li&gt;In phase 4, once HERE-IS-X is deasserted, the downstream stage deasserts GOT-X and the transfer handshake is ready to begin again. Note that the upstream stage waits until it sees the GOT-X deasserted before starting the next handshake.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-07/selfed-time-example.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Finite State Machine</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-06/</link>
      <pubDate>Sun, 07 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-06/</guid>
      <description>&lt;h1 id=&#34;finite-state-machine&#34;&gt;Finite State Machine&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;有穷自动机本身是一个比较简单的概念，不过这里的主要难点是考虑将异步信号转换为同步&lt;/p&gt;
&lt;p&gt;课程地址: &lt;a href=&#34;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c6/c6s1/&#34;&gt;Finate State Machine&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 id=&#34;本课程中自动机的表示图&#34;&gt;本课程中自动机的表示图&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-06/valid-state-fsm.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;异步时钟&#34;&gt;异步时钟&lt;/h2&gt;
&lt;p&gt;当电路中的时钟信号和输入变量的时钟信号不一样时，需要将输入的时钟信号转换为与电路时钟同步的信号，从而使得电路能正常工作。&lt;/p&gt;
&lt;h3 id=&#34;the-bounded-time-synchronizer&#34;&gt;The bounded-time Synchronizer&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-06/the-bounded-time-synchronizer.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;当&lt;code&gt;IN&lt;/code&gt;和&lt;code&gt;CLK&lt;/code&gt;的上升沿到来时间$t_{IN}$和$t_{CLK}$相差大于$t_{E}$时，Synchronizer将输出至少持续$t_{D}$时长的0或1。但如果&lt;code&gt;IN&lt;/code&gt;和&lt;code&gt;CLK&lt;/code&gt;的上升时间沿到来时间之差小于$t_E$时，就无法确定Synchronizer的输出。为什么无法确定？个人理解是因为上升沿实际是要一段时间才能完成的，如果两者上升沿到来时间相差太短，当&lt;code&gt;CLK&lt;/code&gt;达到1时，&lt;code&gt;IN&lt;/code&gt;可能还在中间。&lt;/p&gt;
&lt;p&gt;那么该如何用逻辑电路来实现这个Synchronizer，当然要靠&lt;em&gt;D-Register&lt;/em&gt;啦！&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-06/d-register-synchronizer.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;上图是用&lt;em&gt;D-Register&lt;/em&gt;实现的Synchronizer, 用$t_{setup}$和$t_{hold}$来充当$t_{E}$，看起来很美好，但还没有解决&lt;code&gt;IN&lt;/code&gt;和&lt;code&gt;CLK&lt;/code&gt;的上升沿同时到来的问题！&lt;/p&gt;
&lt;p&gt;当&lt;code&gt;IN&lt;/code&gt;和&lt;code&gt;CLK&lt;/code&gt;的上升沿同时到来时，可能会让D-latch进入metastable状态：&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-06/synchronizer-metastable-state.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-06/metastable-properties.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;解决办法：加D-Register!&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-06/declay-increases-reliability.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Sequential Logic</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-05/</link>
      <pubDate>Fri, 05 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-05/</guid>
      <description>&lt;h1 id=&#34;sequential-logic&#34;&gt;Sequential Logic&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;课程地址：https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017/c5/c5s1/&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;用简单的逻辑门与/或/非可以实现很多逻辑函数，但有一种很简单的电路，却没办法用与/或/非直接实现，如下图所示的开关电路。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/simple-switch.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;普通的组合逻辑电路和开关电路最大的区别在于开关电路的输出还于当前的输出(状态)有关。&lt;/p&gt;
&lt;p&gt;为了用逻辑电路来实现相同的功能，首先得让电路能&lt;em&gt;记住&lt;/em&gt;上一次的状态。&lt;/p&gt;
&lt;h2 id=&#34;memory&#34;&gt;Memory&lt;/h2&gt;
&lt;h3 id=&#34;using-capacitors&#34;&gt;Using Capacitors&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/memory-capacitor.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;如上图所示，电容是可以存储 ”电压“ 的装置，所以很容易想到用电容来实现存储电路。不过在现实环境中，电容没办法做到完全不漏电，所以用电容实现的存储电路每隔一段时间要充一次电。&lt;/p&gt;
&lt;p&gt;DRAM便是类似的原理，需要定时刷新电容上的电压，特点是体积小，便宜。&lt;/p&gt;
&lt;h3 id=&#34;using-feedback&#34;&gt;Using Feedback&lt;/h3&gt;
&lt;p&gt;另一个实现存储电路的思路便是正反馈，如下图所示。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/memory-feedback.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;上图中用两个&lt;em&gt;invertor&lt;/em&gt;实现的正反馈电路可以使输出稳定保持，但除了高低两个状态，还有一个中间的状态，而且该电路也可能会永远保持在中间的状态，所以我们需要避免这种情况。&lt;/p&gt;
&lt;h3 id=&#34;settable-memory&#34;&gt;Settable Memory&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/settable-memory-element.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;我们可以用一个两位的MUX来实现一个可设定的Memory.&lt;/p&gt;
&lt;p&gt;这样的元件叫做D-latch, 即D锁存器。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/d-latch.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;要理解D-latch输入输出和时间的关系，如下图。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/plea-for-lenience.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/little-displine-for-d-latch.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;try-it-out&#34;&gt;Try it out&lt;/h3&gt;
&lt;p&gt;虽然D-锁存器能够存储状态，但当有一连串的状态输入时，如果要保证每次只有一个状态能通过，然后被其余逻辑电路读取，然后下一个状态才能通过的话，需要对时间做非常严格的限制，但在实际环境中，各种干扰和噪声让这种限制变得几乎不太可能。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/try-it-out.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;move-to-register&#34;&gt;Move to Register&lt;/h2&gt;
&lt;h3 id=&#34;flaky-control-system&#34;&gt;Flaky Control System&lt;/h3&gt;
&lt;p&gt;为了解决上面&lt;em&gt;Try it out&lt;/em&gt;中提到的问题，这里先用一个现实中的例子来解释一下：&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/flaky-control-system-1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/flaky-control-system-2.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;d-register&#34;&gt;D-Register&lt;/h3&gt;
&lt;p&gt;我们可以按如上的例子用D-latch来实现一个这样的系统。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/d-register.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;各种时序图&#34;&gt;各种时序图&lt;/h3&gt;
&lt;p&gt;理解D-Register的时序很重要！！！&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/D-Register-waveforms.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/D-Register-hold-time.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/D-Register-timeing-1.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-05/sequential-logic-summary.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Combinational Logic</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-04/</link>
      <pubDate>Sun, 31 Oct 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-04/</guid>
      <description>&lt;h1 id=&#34;combinational-logic&#34;&gt;Combinational Logic&lt;/h1&gt;
&lt;h2 id=&#34;如何描述电子元件的功能&#34;&gt;如何描述电子元件的功能&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;真值表&lt;/li&gt;
&lt;li&gt;逻辑表达式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在输入变量比较多的时候，真值表就很难读/写了，所以逻辑表达式更加通用。&lt;/p&gt;
&lt;h2 id=&#34;设计数字电路的步骤&#34;&gt;设计数字电路的步骤&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;写出真值表&lt;/li&gt;
&lt;li&gt;写出逻辑表达式&lt;/li&gt;
&lt;li&gt;用AND/OR/NOT三种基本逻辑门实现，或者用NAND/NOR/NOT三种逻辑门实现&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因为CMOS本身就是Inverting的，所以实际中NAND/NOR更加通用。&lt;/p&gt;
&lt;h2 id=&#34;sum-of-products&#34;&gt;Sum of products&lt;/h2&gt;
&lt;p&gt;将真值表中为1的项用&lt;em&gt;OR&lt;/em&gt;连接起来就得到了相应的逻辑表达式。&lt;/p&gt;
&lt;p&gt;在功能不变的情况下，为了减少逻辑门的数量，也就是减小$t_{pd}$和$t_{cd}$，就需要将逻辑表达式中的项数最小化。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/sum-of-products-implementation.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/boolean-identities.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/boolean-minimization.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;卡诺图&#34;&gt;卡诺图&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&#34;Karnaugh-map&#34; loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/karnaugh-map.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;卡诺图化简步骤&#34;&gt;卡诺图化简步骤&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;找出Implicants&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/finding-implicants.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/finding-prime-implicants.png&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;合并&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/writing-down-equation.png&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;处理lenient&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/lenient.png&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;mux&#34;&gt;Mux&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/mux.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;decoder&#34;&gt;Decoder&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/decoder.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;rom&#34;&gt;ROM&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/ROM1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/ROM2.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-04/summary.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>CMOS</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-03/</link>
      <pubDate>Mon, 25 Oct 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-03/</guid>
      <description>&lt;h1 id=&#34;cmos&#34;&gt;CMOS&lt;/h1&gt;
&lt;h2 id=&#34;mosfet&#34;&gt;MOSFET&lt;/h2&gt;
&lt;h3 id=&#34;overview&#34;&gt;Overview&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&#34;N-channel MOSFET&#34; loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-03/nchannel-mosfet.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;characters&#34;&gt;Characters&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-03/nchannel-mosfet-characters.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;two-flavors&#34;&gt;Two Flavors&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-03/nchannel-two-flavors.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;cmos-1&#34;&gt;CMOS&lt;/h2&gt;
&lt;p&gt;CMOS is &lt;em&gt;Complementary Metal Oxide Semiconductor&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;two-switches&#34;&gt;Two switches&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-03/cmos-two-switches.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;inverter&#34;&gt;Inverter&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-03/cmos-inverter-vtc.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;basic-usage-of-cmos&#34;&gt;Basic usage of CMOS&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-03/basic-usage-of-cmos.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;timing-specifications&#34;&gt;Timing specifications&lt;/h3&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-03/cmos-timing-specifications.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;propagation-delay&#34;&gt;Propagation Delay&lt;/h4&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-03/cmos-propagation-delay.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;contamination-delay&#34;&gt;Contamination Delay&lt;/h4&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-03/contamination-delay.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-03/cmos-summary.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Digital Abstraction</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-02/</link>
      <pubDate>Thu, 30 Sep 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-02/</guid>
      <description>&lt;h1 id=&#34;the-digital-abstraction&#34;&gt;The Digital Abstraction&lt;/h1&gt;
&lt;h2 id=&#34;信息编码&#34;&gt;信息编码&lt;/h2&gt;
&lt;p&gt;信息的种类有各种各样，我们需要找到一种方式来表示这些信息。比如，生物的基因信息是通过DNA来记录和表达，在计算机中，所有的数据都是二进制，我们也需要一个物理介质来表达和存储这些二进制信息。&lt;/p&gt;
&lt;h2 id=&#34;电压&#34;&gt;电压&lt;/h2&gt;
&lt;p&gt;目前用来存储和表达二进制信息的物理介质绝大部分都是使用电压，高电平表示1, 低电平表示0。&lt;/p&gt;
&lt;h2 id=&#34;vtc和容错&#34;&gt;VTC和容错&lt;/h2&gt;
&lt;p&gt;VTC(voltage transfer characteristics)是用来表示一个电子原件的输入和输出电压关系的图，如下是一个&lt;em&gt;Buffer&lt;/em&gt;的VTC：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;img&#34; loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-02/Slide17.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;其中$V_{IL},V_{IH},V_{OL},V_{OH}$是一个电子元件最重要的参数，解释如下（这里假设最高电压为1）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$V_{IL}$是低电平的输入有效范围，即如果输入电压为$[0,V_{IL}]$，就会被元件当成0处理。&lt;/li&gt;
&lt;li&gt;$V_{IH}$是高电平的输入有效范围，即如果输入电压为$[V_{IH}, 1]$，就会被元件当成1处理。&lt;/li&gt;
&lt;li&gt;$V_{OL}$是低电平的输出电压，即如果元件想输出0，则其输出电压应该为$[0, V_{OL}]$。&lt;/li&gt;
&lt;li&gt;$V_{OH}$是高电平的输出电压，即如果元件想输出1，则其输出电压应该为$[V_{OH},1]$。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其中, $min(|V_{OL} - V_{IL}|, |V_{OH} - V_{IH}|)$即为该元件能容忍的噪声范围。&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&#34;img&#34; loading=&#34;lazy&#34; src=&#34;https://blog-img.rmtt.fun/posts/computation-structure-02/Slide20.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Basic of information</title>
      <link>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-01/</link>
      <pubDate>Sun, 19 Sep 2021 00:00:00 +0000</pubDate>
      <guid>https://rmtt.github.io/zh/posts/computation-structure/computation-structure-01/</guid>
      <description>&lt;h1 id=&#34;basic-of-information&#34;&gt;Basic of Information&lt;/h1&gt;
&lt;h2 id=&#34;信息是什么&#34;&gt;信息是什么&lt;/h2&gt;
&lt;p&gt;信息是我们接收到的关于确实某个特定事件或者情况的数据。&lt;/p&gt;
&lt;h2 id=&#34;量化信息&#34;&gt;量化信息&lt;/h2&gt;
&lt;p&gt;对于随机变量$X_i$，其发生的概率为$p_i$，则其传达的信息量为:&lt;/p&gt;
$$I(x_i) = \log_2(\frac{1}{p_i})$$&lt;h2 id=&#34;数据中的信息&#34;&gt;数据中的信息&lt;/h2&gt;
&lt;p&gt;假设收到data的概率$p_{data}$，则&lt;/p&gt;
$$I(data) = \log_2(\frac{1}{p_{data}})$$&lt;h2 id=&#34;entropy&#34;&gt;Entropy&lt;/h2&gt;
&lt;p&gt;信息论中的entropy：&lt;/p&gt;
$$H(X) = \sum_{i=1}^{N}p_i\log_2(\frac{1}{p_i})$$&lt;p&gt;其中$X$为随机变量。&lt;/p&gt;
&lt;p&gt;物理中的entropy：&lt;/p&gt;
$$ S = k\ln\Omega $$&lt;p&gt;其中，$k$为玻尔兹曼常数&lt;/p&gt;
&lt;h2 id=&#34;meaning-of-entropy&#34;&gt;Meaning of Entropy&lt;/h2&gt;
&lt;p&gt;为了描述某一个随机变量$X$，需要传输一系列的数据，Entropy就是确定$X_i$发生与否的平均位数，即传输量。&lt;/p&gt;
&lt;h2 id=&#34;编码&#34;&gt;编码&lt;/h2&gt;
&lt;p&gt;编码就是把一个数据集合映射为一系列二进制字符串。常见的编码是把英文字母用二进制来表示，比如如下表格：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;A&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;B&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;C&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;D&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;ABBC的编码&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;00&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;01&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;10&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;11&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;00 01 01 00&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;01&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;000&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;001&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;01 1 1 01&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;0&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;1&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;10&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;11&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;0 1 1 0（无法确定）&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;编码不能有二义性&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;二叉树编码&#34;&gt;二叉树编码&lt;/h3&gt;
&lt;p&gt;用二叉树的边当作0和1,叶子节点当作编码的值，可以去除二义性。&lt;/p&gt;
&lt;h3 id=&#34;定长编码&#34;&gt;定长编码&lt;/h3&gt;
&lt;p&gt;所有值的编码长度都相等。&lt;/p&gt;
&lt;h3 id=&#34;2的补码&#34;&gt;2的补码&lt;/h3&gt;
&lt;p&gt;即将二进制最高位的全值定为$-2^{N-1}$&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;负数的补码，按位取反再加1,因为$-A = -1 - A + 1$&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
