<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Blog16</title>
    <link>https://identity16.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 5 Apr 2026 21:04:38 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>blacksmith16</managingEditor>
    <item>
      <title>[컴퓨터 구조] 5.3 The Basics of Caches</title>
      <link>https://identity16.tistory.com/33</link>
      <description>&lt;h2&gt;Questions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;데이터가 존재하는지 어떻게 확인?&lt;/li&gt;
&lt;li&gt;우리가 어디를 보고 어디에 넣어?&lt;ol&gt;
&lt;li&gt;Directed-mapped&lt;/li&gt;
&lt;li&gt;Fully associative&lt;/li&gt;
&lt;li&gt;M-way Set associative&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Directive Mapped Cache&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;위치가 주소에 의해 결정됨&lt;/li&gt;
&lt;li&gt;나머지 연산을 이용해 캐시 주소 결정&lt;ul&gt;
&lt;li&gt;(주소) % (캐시 블럭 수)&lt;/li&gt;
&lt;li&gt;캐시 블럭 수는 2의 거듭제곱이다.&lt;/li&gt;
&lt;li&gt;주소 하위 비트 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tags and Valid Bits&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;어떤 블럭이 캐시에 있는지 알 수 있을까?&lt;ul&gt;
&lt;li&gt;블럭 주소도 저장해놓는다.&lt;/li&gt;
&lt;li&gt;상위 비트를 저장 =&amp;gt; 태그&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;데이터가 아예 없다면?&lt;ul&gt;
&lt;li&gt;Valid bit로 표시&lt;/li&gt;
&lt;li&gt;1 = 있, 0 = 없 (초기값 0)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>전공/컴퓨터 구조</category>
      <category>cache</category>
      <category>컴퓨터 구조</category>
      <author>blacksmith16</author>
      <guid isPermaLink="true">https://identity16.tistory.com/33</guid>
      <comments>https://identity16.tistory.com/33#entry33comment</comments>
      <pubDate>Mon, 26 Oct 2020 14:05:45 +0900</pubDate>
    </item>
    <item>
      <title>[컴퓨터 구조] 5.2 Memory Technologies</title>
      <link>https://identity16.tistory.com/32</link>
      <description>&lt;h2&gt;Memory Technology&lt;/h2&gt;
&lt;p&gt; 대표적인 메모리의 종류는 아래와 같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Static RAM(SRAM)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic RAM(DRAM)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Magnetic Disk&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SRAM -&amp;gt; DRAM -&amp;gt; Magnetic Disk로 갈수록 접근 속도가 100배 빨라지고 GB 당 가격이 100 배 낮아진다.&lt;br&gt;빠른 메모리는 비싸기 때문에 이들을 적절히 혼용하여 가능한 빠른 성능을 내는 것이 최상의 선택이다.&lt;/p&gt;
&lt;h3&gt;SRAM Technology&lt;/h3&gt;
&lt;p&gt; 6 ~ 8 개의 트랜지스터를 사용하여 데이터를 저장한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;빠르지만 비쌈&lt;/li&gt;
&lt;li&gt;접근 시간이 일정&lt;/li&gt;
&lt;li&gt;Refresh 될 필요 없음&lt;/li&gt;
&lt;li&gt;캐시 메모리로 많이 사용됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;DRAM Technology&lt;/h3&gt;
&lt;p&gt; 데이터는 Capacitor의 Charge로 저장됨&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;주기적으로 Refresh 되어야 함&lt;ul&gt;
&lt;li&gt;Read Contents and Write Back&lt;/li&gt;
&lt;li&gt;Performed on a DRAM &amp;quot;row&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Synchronous DRAM (SDRAM)&lt;ul&gt;
&lt;li&gt;대역폭을 향상하기 위해 클럭 추가&lt;/li&gt;
&lt;li&gt;Ex) Double Data Rate(DDR) DRAM : 클럭의 rising, falling edge에 데이터 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Flash Storage&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;비휘발성 반도체 스토리지&lt;ul&gt;
&lt;li&gt;디스크보다 100 ~ 1000배 빠름&lt;/li&gt;
&lt;li&gt;작고 저전력에 튼튼함&lt;/li&gt;
&lt;li&gt;근데 비쌈&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;종류&lt;ul&gt;
&lt;li&gt;NOR Flash&lt;/li&gt;
&lt;li&gt;NAND Flash&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Flash bit는 1000번 이상 접근하면 닳는다.&lt;ul&gt;
&lt;li&gt;Wear Leveling으로 최대한 고르게 사용하도록 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Disk Memory&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;부분 명칭 : Cylinder, Sector, Track, Disk Platters&lt;/li&gt;
&lt;li&gt;각각의 섹터에는..&lt;ul&gt;
&lt;li&gt;Sector ID&lt;/li&gt;
&lt;li&gt;Data&lt;/li&gt;
&lt;li&gt;Error Correcting Code(ECC)&lt;/li&gt;
&lt;li&gt;Synchronization Fields and Gaps&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Sector에 접근하기 위해서..&lt;ul&gt;
&lt;li&gt;다른 접근들은 큐에 대기시킴&lt;/li&gt;
&lt;li&gt;Seek : 트랙을 찾기 위해 헤드를 움직임&lt;/li&gt;
&lt;li&gt;Rotational Latency : 회전하는데 걸리는 시간&lt;/li&gt;
&lt;li&gt;Data Transfer : 데이터 전달&lt;/li&gt;
&lt;li&gt;Controller Overhead&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;평균 Read Time 계산&lt;ul&gt;
&lt;li&gt;평균 Seek Time + 평균 Rotational Latency + Transfer Time + Controller Delay&lt;/li&gt;
&lt;li&gt;강의 자료 13 참고&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Disk Performance Issues&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;제조업체는 평균 Seek Time을 알려준다.&lt;/li&gt;
&lt;li&gt;Disk Drive는 캐시를 포함한다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>전공/컴퓨터 구조</category>
      <category>disk</category>
      <category>DRAM</category>
      <category>flash</category>
      <category>memory</category>
      <category>SRAM</category>
      <category>컴퓨터 구조</category>
      <author>blacksmith16</author>
      <guid isPermaLink="true">https://identity16.tistory.com/32</guid>
      <comments>https://identity16.tistory.com/32#entry32comment</comments>
      <pubDate>Mon, 26 Oct 2020 14:03:01 +0900</pubDate>
    </item>
    <item>
      <title>[컴퓨터 구조] 5.1 Introduction</title>
      <link>https://identity16.tistory.com/31</link>
      <description>&lt;h2&gt;Principle of Locality&lt;/h2&gt;
&lt;p&gt; 프로그램은 한 번에 작은 비율의 주소 공간에 접근한다. 그래서 다시 접근할 확률이 높은 것들에 대한 원칙을 정의하여 효율적으로 공간을 사용하는 것이 좋다.&lt;/p&gt;
&lt;h3&gt;Temporal Locality(Time)&lt;/h3&gt;
&lt;p&gt;최근에 접근한 것들은 머지않아 다시 접근할 확률이 높다.&lt;/p&gt;
&lt;h3&gt;Spatial Locality(Space)&lt;/h3&gt;
&lt;p&gt;최근에 접근한 것과 가까이 위치한 것이 다음에 접근할 확률이 높다.&lt;/p&gt;</description>
      <category>전공/컴퓨터 구조</category>
      <category>Locality</category>
      <category>컴퓨터 구조</category>
      <author>blacksmith16</author>
      <guid isPermaLink="true">https://identity16.tistory.com/31</guid>
      <comments>https://identity16.tistory.com/31#entry31comment</comments>
      <pubDate>Mon, 26 Oct 2020 13:59:27 +0900</pubDate>
    </item>
    <item>
      <title>[컴퓨터 구조] 4.14 Fallacies and Pitfalls</title>
      <link>https://identity16.tistory.com/30</link>
      <description>&lt;h2&gt;Fallacy: Pipeline is easy&lt;/h2&gt;
&lt;p&gt; 지금까지 파이프라인을 잘 이해한 사람들은 어쩌면 이것이 별 거 아니라고 생각할 수도 있다. 그렇지만 지금까지 다룬 것은 파이프라인의 기본적인 개념이고, 더 세부적인 것을 고려하기 시작하면 만만치 않을 것이다.&lt;/p&gt;
&lt;p&gt; 파이프라인의 어려움에 대한 이야기를 말하자면, 이 강의 교재의 1st Edition에서 나온 파이프라인에 버그가 있었는데 이 버그는 100명 이상이 검토하고 18개 대학에서 시험을 칠 동안 발견되지 않았다. 어떤 사람이 이 책을 바탕으로 컴퓨터를 만드려고 시도하다가 그제서야 이 버그가 발견되었다고 한다.&lt;/p&gt;
&lt;h2&gt;Fallacy: Pipelining can be implemented independent of technology&lt;/h2&gt;
&lt;p&gt; 위 문장은 한국어로 &amp;quot;파이프라인은 기술과 상관 없이 구현 가능하다&amp;quot;는 착각인데 그렇지 않다. 칩에 들어가는 트랜지스터가 많아질수록 더 발전된 파이프라인을 만들 수 있으며, 파이프라인과 관련된 ISA 설계는 많은 기술 트렌드를 필요로 한다.&lt;/p&gt;
&lt;h2&gt;Pitfall: Failure to consider instruction set design can adversely impact pipelining&lt;/h2&gt;
&lt;p&gt;  파이프라이닝을 하기에 얼마나 힘든지는 Instruction Set의 설계를 잘했는지 보다는 얼마나 복잡한 Instruction Set인지에 영향을 많이 받는다. 복잡한 Instruction들은 파이프라이닝을 구현하기 위해서 상당한 오버헤드가 존재하기 때문이다.&lt;/p&gt;</description>
      <category>전공/컴퓨터 구조</category>
      <category>Fallacies and Pitfalls</category>
      <category>컴퓨터 구조</category>
      <category>파이프라이닝</category>
      <author>blacksmith16</author>
      <guid isPermaLink="true">https://identity16.tistory.com/30</guid>
      <comments>https://identity16.tistory.com/30#entry30comment</comments>
      <pubDate>Mon, 26 Oct 2020 13:58:02 +0900</pubDate>
    </item>
    <item>
      <title>[컴퓨터 구조] 4.7 Data Hazards: Forwarding versus Stalling</title>
      <link>https://identity16.tistory.com/29</link>
      <description>&lt;p&gt; 지금까지 구현한 회로는 Hazard가 발생하지 않는 상황에서는 잘 동작한다. 하지만 실제 프로그램에서는 Hazard가 많이 발생하기 때문에 이를 처리할 수 있도록 고쳐서 조금 더 현실적인 프로세서를 만들어보자.&lt;/p&gt;
&lt;h2&gt;Forwarding&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;sub   $2, $1,$3 # Register $2 written by sub
and   $12,$2,$5 # 1st operand($2) depends on sub
or    $13,$6,$2 # 2nd operand($2) depends on sub
add   $14,$2,$2 # 1st($2) &amp;amp; 2nd($2) depend on sub
sw    $15,100($2) # Base ($2) depends on sub&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; 위 코드의 &lt;code&gt;$2&lt;/code&gt;를 보자. &lt;code&gt;sub&lt;/code&gt;에서 처음 값이 저장된 후, 다음 4 개의 instruction에서 읽기 레지스터로 사용된다. 낭비되는 사이클 없이 파이프라인에서 실행된다면 Multi-cycle-pipeline 다이어그램은 아래 이미지 &lt;em&gt;(강의 교재 figure 4.52)&lt;/em&gt; 와 같을 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zVt4r/btqLOPZzDUv/v2dGoaNT8gIoTnZ76RH5wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zVt4r/btqLOPZzDUv/v2dGoaNT8gIoTnZ76RH5wk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zVt4r/btqLOPZzDUv/v2dGoaNT8gIoTnZ76RH5wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzVt4r%2FbtqLOPZzDUv%2Fv2dGoaNT8gIoTnZ76RH5wk%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 여기서 파란색은 &lt;code&gt;$2&lt;/code&gt;를 쓰거나 읽는 부분인데, 첫 줄에서 &lt;code&gt;$s2&lt;/code&gt;가 저장되기 전에 &lt;code&gt;$2&lt;/code&gt;를 읽는 곳은 &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt; 두 군데이다. 즉, Data Hazard가 발생했으며 이를 해결하기 위해서는 Forwarding이 필요하다. 이 경우에는 &lt;code&gt;sub&lt;/code&gt; 의 EX 단계 ALU 결과를 &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;의 EX 입력으로 연결해 주어야 한다.&lt;br&gt; 그렇다면 Data Hazard가 발생했는지는 어떻게 알 수 있을까? 그 방법은 각 단계의 사이에 있는 파이프라인 레지스터(ID/EX 등)에 저장되어 있는 레지스터 값을 비교하는 것이다. 다음 네 가지 경우이면 Data Hazard이다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EX/MEM의 R&lt;sub&gt;d&lt;/sub&gt; = ID/EX의 R&lt;sub&gt;s&lt;/sub&gt;&lt;/li&gt;
&lt;li&gt;EX/MEM의 R&lt;sub&gt;d&lt;/sub&gt; = ID/EX의 R&lt;sub&gt;t&lt;/sub&gt;&lt;/li&gt;
&lt;li&gt;MEM/WB의 R&lt;sub&gt;d&lt;/sub&gt; = ID/EX의 R&lt;sub&gt;s&lt;/sub&gt;&lt;/li&gt;
&lt;li&gt;MEM/WB의 R&lt;sub&gt;d&lt;/sub&gt; = ID/EX의 R&lt;sub&gt;t&lt;/sub&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; 항상 저 값들을 비교하는 것은 아닌데, 간혹가다 EX/MEM이나 MEM/WB의 R&lt;sub&gt;d&lt;/sub&gt;에 값이 저장되지 않는 경우에는 포워딩을 하면 안되기 때문이다. EX/MEM과 MEM/WB에 RegWrite라는 신호를 추가하면 해결할 수 있다. 그리고 R&lt;sub&gt;d&lt;/sub&gt;가 &lt;code&gt;$0&lt;/code&gt;(항상 값이 0이어야 하는 레지스터)이면 값을 저장해선 안되기 때문에 EX/MEM의 R&lt;sub&gt;d&lt;/sub&gt; != 0, MEM/WB의 R&lt;sub&gt;d&lt;/sub&gt; != 0 조건까지 추가한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5r4tQ/btqLNrEET5Y/LUnAGVstYTmUAvu691KVGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5r4tQ/btqLNrEET5Y/LUnAGVstYTmUAvu691KVGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5r4tQ/btqLNrEET5Y/LUnAGVstYTmUAvu691KVGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5r4tQ%2FbtqLNrEET5Y%2FLUnAGVstYTmUAvu691KVGk%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 위 이미지 &lt;em&gt;(강의 교재 figure 4.54)&lt;/em&gt; 는 Forwarding을 고려해 변경한 회로이다. ALU 입력값 MUX에 포워딩 된 값이 추가되었다. 그리고 포워딩 상태를 다루기 위한 Forwarding Unit도 더해졌다.&lt;br&gt; Forwarding Unit에서 ForwardA와 ForwardB의 값을 정하는 기준을 살펴보자. 우선 ForwardA는 R&lt;sub&gt;s&lt;/sub&gt;, ForwardA는 R&lt;sub&gt;t&lt;/sub&gt;에 대한 MUX를 제어한다. 두 신호 공통으로 00은 Read Register에서 읽어온 값을 그대로 선택한다는 뜻이고, 10은 ALU 결과를 포워딩, 01은 메모리에서 읽은 값을 포워딩한다는 의미이다. 값을 결정하는 기준은 앞에서 얘기한 Data Hazard를 판단하는 네 가지 경우와 RegWrite 상태, R&lt;sub&gt;d&lt;/sub&gt;가 $0이 아닌지이다.&lt;/p&gt;
&lt;p&gt; 정리해보면 아래와 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;EX hazard:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;if (EX/MEM.RegWrite
    and (EX/MEM.RegisterRd ≠ 0)
    and (EX/MEM.RegisterRd = ID/EX.RegisterRs)) ForwardA = 10 

if (EX/MEM.RegWrite
    and (EX/MEM.RegisterRd ≠ 0)
    and (EX/MEM.RegisterRd = ID/EX.RegisterRt)) ForwardB = 10&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;MEM hazard:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;if (MEM/WB.RegWrite
    and (MEM/WB.RegisterRd ≠  0)
    and (MEM/WB.RegisterRd = ID/EX.RegisterRs)) ForwardA = 01
if (MEM/WB.RegWrite
    and (MEM/WB.RegisterRd ≠  0)
    and (MEM/WB.RegisterRd = ID/EX.RegisterRt)) ForwardB = 01&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Double Data Hazard&lt;/h2&gt;
&lt;p&gt; 아래 코드를 보자&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-assembly&quot;&gt;add $1, $1, $2
add $1, $1, $3
add $1, $1, $4&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 코드의 경우, 세 번째 &lt;code&gt;add&lt;/code&gt;에서 두 종류의 Hazard가 동시에 발생하는데 세 번째 &lt;code&gt;add&lt;/code&gt;가 EX 단계에 들어가는 상황을 생각해보자. 우선, 세 번째 &lt;code&gt;add&lt;/code&gt;의 R&lt;sub&gt;s&lt;/sub&gt;(ID/EX)가 두 번째 &lt;code&gt;add&lt;/code&gt;의 R&lt;sub&gt;d&lt;/sub&gt;(EX/MEM)와 같기 때문에 EX Hazard가 발생했다. 또 세 번째 &lt;code&gt;add&lt;/code&gt;의 R&lt;sub&gt;s&lt;/sub&gt;는 첫 번째 &lt;code&gt;add&lt;/code&gt;의 R&lt;sub&gt;d&lt;/sub&gt;(MEM/WB)와도 같아서 MEM Hazard도 동시에 발생한다.&lt;/p&gt;
&lt;p&gt;  위 예시처럼 EX Hazard와 MEM Hazard가 동시에 발생했을 때 EX/MEM의 R&lt;sub&gt;d&lt;/sub&gt;와 MEM/WB의 R&lt;sub&gt;d&lt;/sub&gt; 중에서 더 최근 값인 두 번째 &lt;code&gt;add&lt;/code&gt;의 R&lt;sub&gt;d&lt;/sub&gt;, 즉 EX/MEM의 값을 포워딩해야 한다. 다시 말해 MEM Hazard일 때 포워딩하기 위한 조건에 EX Hazard가 아니어야 한다는 조건이 더 추가되어야 한다. 이 조건을 추가한 MEM Hazard 조건은 아래와 같다.&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;MEM hazard:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;if (MEM/WB.RegWrite
    and (MEM/WB.RegisterRd ≠0)
    and not(EX/MEM.RegWrite and (EX/MEM.RegisterRd ≠0)
        and (EX/MEM.RegisterRd ≠  ID/EX.RegisterRs))
    and (MEM/WB.RegisterRd = ID/EX.RegisterRs)) ForwardA = 01
if (MEM/WB.RegWrite
    and (MEM/WB.RegisterRd ≠0)
    and not(EX/MEM.RegWrite and (EX/MEM.RegisterRd ≠0)
        and (EX/MEM.RegisterRd ≠  ID/EX.RegisterRs))
    and (MEM/WB.RegisterRd = ID/EX.RegisterRt)) ForwardB = 01&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Load-Use Data Hazard&lt;/h2&gt;
&lt;p&gt; Load-Use Data Hazard에 대해서는 &amp;quot;4.5 An Overview of Pipelining(2)&amp;quot; 포스팅에서 설명했으므로 자세한 설명은 일단 생략하겠다. 이러한 경우에는 무조건 Stall(대기 상태)이 한 사이클 발생하는데, 회로에서 구현하기 위해서는 Load-Use Data Hazard를 감지한 다음에 해당 instruction을 일부러 한 사이클 늦게 실행해야 한다. 다음은 파이프라인에서 Stall을 만드는 방법이다.&lt;/p&gt;
&lt;p&gt; Load-Use Data Hazard는 아래 조건과 같이 감지할 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (ID/EX.MemRead and
    ((ID/EX.RegisterRt = IF/ID.RegisterRs) or
        (ID/EX.RegisterRt = IF/ID.RegisterRt)))
            stall the pipeline&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;How to Stall the Pipeline&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;ID / EX 레지스터의 Control 값을 전부 0으로 만든다.&lt;ul&gt;
&lt;li&gt;Control이 전부 0이면 EX, MEM, WB에서 아무 연산도 하지 않는다.(&lt;strong&gt;nop&lt;/strong&gt; : no-operation)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;PC와 IF/ID 레지스터를 업데이트 하지 않는다.&lt;ul&gt;
&lt;li&gt;IF 단계와 ID 단계를 한 사이클 반복한다.&lt;/li&gt;
&lt;li&gt;그러면 같은 동작을 반복하므로 IF, ID도 사실상 한 사이클 동안 &lt;strong&gt;nop&lt;/strong&gt; 상태라고 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt; 아래는 Load-Use Data Hazard를 위와 같은 방식으로 처리한 것을 multi-cycle pipeline diagram으로 나타낸 이미지 &lt;em&gt;(강의 교재 figure 4.59)&lt;/em&gt; 이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dMyaNr/btqLGYct1k9/epCkpzGcXavGWTpIkUoBOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dMyaNr/btqLGYct1k9/epCkpzGcXavGWTpIkUoBOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dMyaNr/btqLGYct1k9/epCkpzGcXavGWTpIkUoBOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdMyaNr%2FbtqLGYct1k9%2FepCkpzGcXavGWTpIkUoBOk%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 여기서는 nop 이후에 &lt;code&gt;and&lt;/code&gt;의 IF를 한 번 더 실행하는 것처럼 표현되었지만, 실제로는 두 번째 사이클에서 가져온 instruction을 한 사이클 대기한 뒤 EX 단계로 넘어가는 거지만 그냥 넘어가자.&lt;/p&gt;
&lt;p&gt; Load-Use Data Hazard를 감지하는 Hazard Detection Unit을 추가한 최종 회로의 이미지 &lt;em&gt;(강의 교재 figure 4.60)&lt;/em&gt; 를 끝으로 포스팅을 마칩니다.&lt;/p&gt;
&lt;p&gt; &lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y5SbD/btqLIH9iS83/GkcFJbADbGHBgt9Db9BNUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y5SbD/btqLIH9iS83/GkcFJbADbGHBgt9Db9BNUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y5SbD/btqLIH9iS83/GkcFJbADbGHBgt9Db9BNUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy5SbD%2FbtqLIH9iS83%2FGkcFJbADbGHBgt9Db9BNUK%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>전공/컴퓨터 구조</category>
      <category>Data Hazard</category>
      <category>Forwarding</category>
      <category>Stalling</category>
      <category>컴퓨터 구조</category>
      <author>blacksmith16</author>
      <guid isPermaLink="true">https://identity16.tistory.com/29</guid>
      <comments>https://identity16.tistory.com/29#entry29comment</comments>
      <pubDate>Mon, 26 Oct 2020 13:56:00 +0900</pubDate>
    </item>
    <item>
      <title>[컴퓨터 구조] 4.6 Pipelined Datapath and Control</title>
      <link>https://identity16.tistory.com/28</link>
      <description>&lt;p&gt; 여기서는 4.4장에서 완성했던 기존의 Single-Cycle Datapath를 Pipelined Datapath로 바꾸는 과정을 살펴볼 예정이다. 우선 회로를 아래 다섯 단계로 나누어 표시해보자.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IF&lt;/strong&gt;(Instruction Fetch)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ID&lt;/strong&gt;(Instruction Decode, Register File Read)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EX&lt;/strong&gt;(Execute, Address Calculation)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MEM&lt;/strong&gt;(Memory Access)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WB&lt;/strong&gt;(Write Back)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6PmUl/btqLRjZ70UB/arCFNDtJAqYHtWr9u9GMUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6PmUl/btqLRjZ70UB/arCFNDtJAqYHtWr9u9GMUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6PmUl/btqLRjZ70UB/arCFNDtJAqYHtWr9u9GMUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6PmUl%2FbtqLRjZ70UB%2FarCFNDtJAqYHtWr9u9GMUk%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위 이미지 &lt;em&gt;(강의 교재 figure 4.33)&lt;/em&gt; 과 같이 나눌 수 있는데, 여기서 파란색 선은 다른 단계로 데이터가 전달되는 상황임을 표시한 것이다. 위쪽 파란 선은 MEM에서 IF로, 아래쪽 파란 선은 WB에서 ID로 데이터가 전달되는 부분이다. WB -&amp;gt; ID의 Right-to-Left 상황은 Data Hazard와 Control Hazard를 유발한다. 이것을 해결하는 방법은 둘째 치고, 각 단계에서 각기 다른 Instruction을 수행해야 하므로 단계마다 다른 데이터를 이용해 연산을 해야한다. 따라서 단계의 사이사이에 사용할 데이터를 저장하는 레지스터를 추가한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5RB8r/btqLOPZyGPh/6OEucLnIFduQ4QBxSLT3L0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5RB8r/btqLOPZyGPh/6OEucLnIFduQ4QBxSLT3L0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5RB8r/btqLOPZyGPh/6OEucLnIFduQ4QBxSLT3L0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5RB8r%2FbtqLOPZyGPh%2F6OEucLnIFduQ4QBxSLT3L0%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;추가된 레지스터의 이름은 양쪽의 두 단계의 이름을 합친 IF/ID, ID/EX, EX/MEM, MEM/WB이다. 이 레지스터들도 State Element이므로 각 클럭마다 상태가 업데이트 되어야 한다. 따라서 위 이미지 &lt;em&gt;(강의 교재 figure 4.35)&lt;/em&gt; 의 회로에는 이 레지스터들과 PC에 Clock 입력이 있어야 한다.&lt;/p&gt;
&lt;h2&gt;Representing Pipeline Operation&lt;/h2&gt;
&lt;p&gt; 파이프라인의 상태를 표현할 때 우리는 다음 두 가지 방식을 사용할 것이다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&amp;quot;Single-clock-cycle&amp;quot; pipeline diagram : 특정 사이클에서 사용되는 부분을 표시하고 단계 별로 어떤 Instruction을 실행하고 있는지 표시한 그림이다.&lt;/li&gt;
&lt;li&gt;&amp;quot;Multi-clock-cycle&amp;quot; pipeline diagram : 아래 이미지 &lt;em&gt;(강의 교재 figure 4.34)&lt;/em&gt; 참고&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FBilP/btqLLGWnU95/vTssNDhPrBOmP2Ih0jGMXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FBilP/btqLLGWnU95/vTssNDhPrBOmP2Ih0jGMXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FBilP/btqLLGWnU95/vTssNDhPrBOmP2Ih0jGMXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFBilP%2FbtqLLGWnU95%2FvTssNDhPrBOmP2Ih0jGMXk%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt;IF for Load&lt;/h3&gt;
&lt;p&gt; 제일 첫 번째 단계인 IF 단계의 다이어그램이다. 아래 이미지 &lt;em&gt;(강의 교재 figure 4.36)&lt;/em&gt; 를 보고 Single-clock-cycle 다이어그램이 어떻게 생겼는지 살펴보길 바란다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MSp0d/btqLQcGWOII/48Auf0RkZngHp9HmahrJO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MSp0d/btqLQcGWOII/48Auf0RkZngHp9HmahrJO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MSp0d/btqLQcGWOII/48Auf0RkZngHp9HmahrJO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMSp0d%2FbtqLQcGWOII%2F48Auf0RkZngHp9HmahrJO1%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt;WB for Load&lt;/h3&gt;
&lt;p&gt; 이번에는 WB 단계인데, 우선 이미지 &lt;em&gt;(강의 교재 figure 4.38)&lt;/em&gt; 부터 보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7lbMb/btqLJVGg7Cq/NJsKl1Hhf4NEk9H25DsVKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7lbMb/btqLJVGg7Cq/NJsKl1Hhf4NEk9H25DsVKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7lbMb/btqLJVGg7Cq/NJsKl1Hhf4NEk9H25DsVKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7lbMb%2FbtqLJVGg7Cq%2FNJsKl1Hhf4NEk9H25DsVKK%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 다른 단계를 건너뛰고 바로 WB 단계를 소개하는 이유는 위 회로에서 오류가 하나 있기 때문이다. 그것은 바로 ID 단계의 Write Data로 값을 넘기는 부분인데, 이대로 회로를 사용한다면 넘어간 데이터가 쓰여질 레지스터는 ID 단계에서 실행 중인 Instruction의 Write Register이어서 엉뚱한 곳에 쓰이게 된다. 이를 해결하기 위해서는 WB 단계의 Instruction에서 사용하는 Write Register 넘버를 같이 넘겨줘야 한다. 그렇게 구성한 회로는 아래 이미지 &lt;em&gt;(강의 교재 figur 4.41)&lt;/em&gt; 에 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDeEmN/btqLOQjPWxT/A0Pi3Skgevh7u639P3wkp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDeEmN/btqLOQjPWxT/A0Pi3Skgevh7u639P3wkp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDeEmN/btqLOQjPWxT/A0Pi3Skgevh7u639P3wkp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDeEmN%2FbtqLOQjPWxT%2FA0Pi3Skgevh7u639P3wkp1%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2&gt;Pipelined Control&lt;/h2&gt;
&lt;p&gt;  지금까지 작성한 회로는 동작 상으로는 문제가 없겠지만 뭔가 부족한 점이 하나 있다. 바로 Control의 부재이다. Control 신호도 앞선 데이터들과 마찬가지로 Instruction마다 다르기 때문에 단계가 넘어갈 때마다 레지스터에 저장해 주어야 한다. 그러나 모든 신호를 매번 다 저장하면 공간낭비이므로 단계별로 사용하는 신호를 나눈 다음, 더이상 필요없는 신호들은 다음 단계로 갈 때 저장하지 않도록 한다. 아래 표 &lt;em&gt;(강의 교재 figure 4.49)&lt;/em&gt; 는 단계 별로 Control 신호를 나눈 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bICHz1/btqLOPrHFil/e4CtIb3sGmGPEc0E471C9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bICHz1/btqLOPrHFil/e4CtIb3sGmGPEc0E471C9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bICHz1/btqLOPrHFil/e4CtIb3sGmGPEc0E471C9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbICHz1%2FbtqLOPrHFil%2Fe4CtIb3sGmGPEc0E471C9k%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;그리고 Control 신호를 저장할 레지스터를 덧붙인 상태의 회로는 아래 &lt;em&gt;(강의 교재 figure 4.51)&lt;/em&gt; 와 같이 생겼다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2Thv2/btqLFo3JQtg/KcgoLnuZi7R9elChgfbZn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2Thv2/btqLFo3JQtg/KcgoLnuZi7R9elChgfbZn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2Thv2/btqLFo3JQtg/KcgoLnuZi7R9elChgfbZn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2Thv2%2FbtqLFo3JQtg%2FKcgoLnuZi7R9elChgfbZn0%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;완성!은 아직 아니고 Hazard를 해결하는 걸 조금 더 해야한다. 그건 다음 포스팅에서 다룰 예정이다.&lt;/p&gt;</description>
      <category>전공/컴퓨터 구조</category>
      <category>Datapath</category>
      <category>pipelined datapath</category>
      <category>컴퓨터 구조</category>
      <category>파이프라이닝</category>
      <author>blacksmith16</author>
      <guid isPermaLink="true">https://identity16.tistory.com/28</guid>
      <comments>https://identity16.tistory.com/28#entry28comment</comments>
      <pubDate>Mon, 26 Oct 2020 13:40:44 +0900</pubDate>
    </item>
    <item>
      <title>[컴퓨터 구조] 4.5 An Overview of Pipelining(2)</title>
      <link>https://identity16.tistory.com/27</link>
      <description>&lt;h2&gt;Hazards&lt;/h2&gt;
&lt;p&gt;Hazard란 다음 Instruction을 바로 다음 사이클에서 실행할 수 없도록 하는 상황을 뜻한다. Hazard를 해결하지 못하면 작업을 하지 않는 사이클이 발생해 Pipeline이 느리게 동작한다. Hazard의 종류를 살펴보자.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Structure Hazard : 사용하려는 자원이 이용 중인 경우&lt;/li&gt;
&lt;li&gt;Data Hazard : 앞선 Instruction이 Read나 Write를 할 때까지 기다려야 하는 경우&lt;/li&gt;
&lt;li&gt;Control Hazard : 앞 Instruction에 의해 Control 동작이 결정되는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Structure Hazard&lt;/h3&gt;
&lt;p&gt;여러 Instruction이 동시에 같은 리소스에 접근하는 경우이다. 메모리가 하나 뿐인 MIPS pipeline에서는, Load / Store가 메모리 데이터에 접근을 요청하면 Instruction Fetch 단계인 다른 Instruction은 Load / Store이 끝날 때까지 기다리고 있어야 한다. IF 단계인 Instruction은 한 사이클을 아무 작업도 하지 못하고 기다리는데, 이 때 Pipeline &quot;Bubble&quot;이 발생했다고 한다.&lt;/p&gt;
&lt;p&gt;이러한 Structure Hazard를 해결하기 위해서는 Instruction 메모리와 Data 메모리를 분리해야 한다. 아니면 Instruction / Data 캐시를 분리해도 된다.&lt;/p&gt;
&lt;h3&gt;Data Hazard&lt;/h3&gt;
&lt;p&gt;이전 Instruction의 결과를 현재 Instruction에서 사용하려고 할 때, 이전 Instruction의 WB가 끝날 때까지 기다린 다음 현재 Instruction의 ID를 수행해야 한다. 이 경우를 Data Hazard라 한다. 아래와 같은 상황을 예시로 들어보자.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;add $s0, $t0, $t1
sub $t2, $s0, $t3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;여기를 보면 &lt;code&gt;add&lt;/code&gt;의 R&lt;sub&gt;d&lt;/sub&gt;인 &lt;code&gt;$s0&lt;/code&gt;가 &lt;code&gt;sub&lt;/code&gt;의 R&lt;sub&gt;s&lt;/sub&gt;로 사용되었다. 우리가 아는 파이프라인에서는 아래와 같이 두 사이클을 쉬어야한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sElRC/btqLLF4abrA/h5uFAwkGePzocICfrkod0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sElRC/btqLLF4abrA/h5uFAwkGePzocICfrkod0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sElRC/btqLLF4abrA/h5uFAwkGePzocICfrkod0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsElRC%2FbtqLLF4abrA%2Fh5uFAwkGePzocICfrkod0k%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4&gt;Forwarding(Bypassing)&lt;/h4&gt;
&lt;p&gt;Data Hazard를 피하기 위한 방법인 Forwarding은 이전 Instruction의 WB 단계까지 기다리지 않고 레지스터에 저장될 값을 현재 Instruction의 EX의 입력값으로 끌어올 수 있도록 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bb4v0M/btqLIH9dnIo/AOXb7akI7VdJU665Hq1Lf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bb4v0M/btqLIH9dnIo/AOXb7akI7VdJU665Hq1Lf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bb4v0M/btqLIH9dnIo/AOXb7akI7VdJU665Hq1Lf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbb4v0M%2FbtqLIH9dnIo%2FAOXb7akI7VdJU665Hq1Lf1%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이렇게 하면 낭비되는 사이클 없이 바로 Instruction을 이어서 실행할 수 있다.&lt;/p&gt;
&lt;h4&gt;Load-Use Data Hazard&lt;/h4&gt;
&lt;p&gt;이번에는 EX 단계에서 계산되는 것이 아닌 메모리에서 가져오는 데이터로 인해 발생하는 Data Hazard에 대해 살펴보자. 이번에는 예시코드가 아까와는 다르다.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;lw $s0, 20($t1)
sub $t2, $s0, $t3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;$s0&lt;/code&gt;에 들어갈 값은 EX에서 결정되던 이전 상황과는 달리 MEM에서 결정된다. Forwarding을 하더라도 &lt;code&gt;lw&lt;/code&gt;의 MEM 단계 이후에 sub의 EX가 나와야 하기 때문에 아래 이미지와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blzpzt/btqLJU8mNP3/ct84rKE8UFfPciJG4AM1X0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blzpzt/btqLJU8mNP3/ct84rKE8UFfPciJG4AM1X0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blzpzt/btqLJU8mNP3/ct84rKE8UFfPciJG4AM1X0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fblzpzt%2FbtqLJU8mNP3%2Fct84rKE8UFfPciJG4AM1X0%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4&gt;Code Scheduling to Avoid Stalls&lt;/h4&gt;
&lt;p&gt;Hazard가 발생하지 않도록 Instruction을 순서 재배치하라는 얘기이다. 자세한 설명은 일단 생략하겠다.&lt;/p&gt;
&lt;h3&gt;Control Hazard&lt;/h3&gt;
&lt;p&gt;파이프라이닝을 할 때, 이전 Instruction이 Branch(ex - &lt;code&gt;beq&lt;/code&gt;)이면 ID 단계가 지난 후에야 다음에 실행할 Instruction을 알 수 있다. 그렇게 되면 아래 이미지 &lt;i&gt;(강의 교재 figure 4.31)&lt;/i&gt; 처럼 한 사이클의 대기(Stall)가 발생한다.(&lt;code&gt;beq&lt;/code&gt;의 EX 단계까지 기다리지 않는 이유는 &lt;code&gt;beq&lt;/code&gt;의 ALU 연산과 다음 Instruction의 IF 까지 한 사이클 내에 실행할 수 있어서라고 합니다. 이 내용에 대해서는 확신이 없기 때문에 정확한 이유를 알고 계신 분은 알려주시면 감사하겠습니다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GspDT/btqLJWE7ASI/0FlaQkNMJfb0xDa2nFv1qK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GspDT/btqLJWE7ASI/0FlaQkNMJfb0xDa2nFv1qK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GspDT/btqLJWE7ASI/0FlaQkNMJfb0xDa2nFv1qK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGspDT%2FbtqLJWE7ASI%2F0FlaQkNMJfb0xDa2nFv1qK%2Fimg.png&quot; width=&quot;100%&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;이를 개선하는 방법으로 Branch Prediction이 있다.&lt;/p&gt;
&lt;h4&gt;Branch Prediction&lt;/h4&gt;
&lt;p&gt;더 많은 일을 수행하는 파이프라인에서는 브랜치 결과를 빨리 낼 수 없다. 그렇게 되면 지금처럼 한 사이클이 아니라 훨씬 더 많은 사이클 대기(Stall)가 발생한다. Stall을 조금이라도 줄이기 위해 브랜치의 결과를 예측하여 예측이 틀릴 때만 Stall이 발생하도록 하는 방식이 Branch Prediction이다.&lt;br /&gt;Branch Prediction의 동작은 다음 사이클에서 예측되는 Instruction을 미리 Fetch한 다음, 만약 예측이 맞았으면 계속 수행하고 틀렸다면 Fetch된 것은 무효화하고 다른 주소에 대해 IF 단계부터 다시 수행한다. 그렇게 하면 예측이 맞았을 때의 사이클 낭비는 없게 된다.&lt;/p&gt;
&lt;h4&gt;More-Realistic Branch Prediction&lt;/h4&gt;
&lt;p&gt;Branch Prediction으로 예측이 맞았을 때의 Stall을 제거할 수 있다는 것을 알았으니, 이것을 더 효율적으로 만들기 위해서는 예측이 맞을 확률을 높일 필요가 있다. 어떻게 예측 확률을 높일 수 있을지 한 번 알아보자.&lt;/p&gt;
&lt;h5&gt;Static Branch Prediction&lt;/h5&gt;
&lt;p&gt;코드를 해석하여 문법의 특성에 맞게 예측한다. 그 예시로 반복문과 조건문(if)을 들 수 있다. 우선, 반복문은 반복이 수행되는 것이 더 확률이 높기 때문에 반복할 첫 Instruction의 주소로 예측한다. 다음으로 조건문에서의 branch는 조건이 맞았을 때를 예측하는 편이 더 확률이 높다고 보고 조건문의 첫 Instruction의 주소를 예측한다. 물론, 다른 이유로 다른 예측을 할 수도 있으므로 위 예시는 무조건적인 정답은 아니다.&lt;/p&gt;
&lt;h5&gt;Dynamic Branch Prediction&lt;/h5&gt;
&lt;p&gt;지금까지 브랜치가 동작한 기록을 바탕으로 앞으로 예상되는 값을 추정하는 방식이다. 하드웨어에서 기록을 측정한다.&lt;/p&gt;
&lt;h2&gt;Pipeline Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;파이프라이닝은 Throughput을 향상시킴으로서 성능을 향상하는 방법이다.
&lt;ul&gt;
&lt;li&gt;여러 Instruction을 병렬적으로 실행함&lt;/li&gt;
&lt;li&gt;각각의 Instruction은 같은 실행시간을 가짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Hazard에 영향을 받는다.&lt;/li&gt;
&lt;li&gt;Instruction Set 설계는 파이프라인 구현의 복잡도에 영향을 미친다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>전공/컴퓨터 구조</category>
      <category>pipelining</category>
      <category>컴퓨터 구조</category>
      <category>파이프라이닝</category>
      <author>blacksmith16</author>
      <guid isPermaLink="true">https://identity16.tistory.com/27</guid>
      <comments>https://identity16.tistory.com/27#entry27comment</comments>
      <pubDate>Mon, 26 Oct 2020 13:34:03 +0900</pubDate>
    </item>
    <item>
      <title>[컴퓨터 구조] 4.5 An Overview of Pipelining(1)</title>
      <link>https://identity16.tistory.com/26</link>
      <description>&lt;p&gt; 앞서 만든 프로세서 회로는 실제로는 거의 사용되지 않는다. 4.3의 마지막 단락은 다음과 같았다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;PC는 State Element이고, 나머지는 Combinational Element이기 때문에 전체 회로를 도는 데에는 1 Clock이 소요(CPI = 1)되어야 한다. 즉, 이 회로가 도는 속도에 따라 프로세서의 클럭 주기가 결정된다고 할 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; CPI가 1인 프로세서는 한 클럭에 한 명령어가 실행된다는 것이고, 이보다 더 효율적이려면 한 클럭에 여러 명령어가 동시에 수행되어야 한다. 이걸 가능하게 하는 것이 파이프라인이며, 주저리주저리 설명하면 괜히 어렵게 들리니까 어떤 느낌인지 비유로 아래에서 설명하겠다.&lt;/p&gt;
&lt;h2&gt;Pipelining Analogy&lt;/h2&gt;
&lt;p&gt;  강의 교재에서는 파이프라인을 설명하기 위한 비유로 빨래하는 과정을 이야기한다. 빨래를 A, B, C, D로 총 네 번을 수행해야 하고 세탁 -&amp;gt; 건조 -&amp;gt; 빨래 개기 -&amp;gt; 옷장에 넣기 단계로 나뉜다고 하자. 각 단계는 0.5 시간 소요된다. 파이프라인이 적용되지 않은 경우, 빨래는 아래 이미지 &lt;em&gt;(강의 교재 figure 4.25)&lt;/em&gt; 와 같이 이루어진다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u62TI/btqLOOfbXFC/nFDX69Yd3jIwZ5ZJ48ep60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u62TI/btqLOOfbXFC/nFDX69Yd3jIwZ5ZJ48ep60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u62TI/btqLOOfbXFC/nFDX69Yd3jIwZ5ZJ48ep60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu62TI%2FbtqLOOfbXFC%2FnFDX69Yd3jIwZ5ZJ48ep60%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 세탁 ———&amp;gt; 옷장을 총 네 번 반복한다. 그러면 총 8시간이 걸리게 된다. 마치 우리가 지금까지 짠 회로와 같이 명령어 4개를 실행하면 Instruction Fetch ---&amp;gt; ... 단계를 총 4번 도는 것과 같다.&lt;/p&gt;
&lt;p&gt; 파이프라인은 &amp;quot;A 빨래를 건조기에 돌리는 동안 일이 끝난 세탁기에 B 빨래를 돌리고 있자!&amp;quot;라고 생각하면 된다. 그걸 이미지로 표현한 것이 아래 이미지 &lt;em&gt;(강의 교재 figure 4.25)&lt;/em&gt; 이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRuwU7/btqLJUUNPNj/kJWaPkCjFqbwFRQKvOkhZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRuwU7/btqLJUUNPNj/kJWaPkCjFqbwFRQKvOkhZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRuwU7/btqLJUUNPNj/kJWaPkCjFqbwFRQKvOkhZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRuwU7%2FbtqLJUUNPNj%2FkJWaPkCjFqbwFRQKvOkhZk%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 그러면 4 세트의 빨래를 돌리는 데 걸리는 시간을 3.5시간으로 줄일 수 있다. 파이프라인을 회로에 적용하려면 빨래, 건조 등과 같이 회로 안에서 역할 별로 단계(stage)를 나누어 놓아야 한다.&lt;/p&gt;
&lt;h2&gt;MIPS Pipeline&lt;/h2&gt;
&lt;p&gt; 파이프라인을 적용하기 위해 우리는 회로를 총 다섯 단계로 나눌 것이다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;IF&lt;/strong&gt;(Instruction Fetch) : 메모리에서 Instruction을 가져옴&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ID&lt;/strong&gt;(Instruction Decode) : Instruction을 해석하고 레지스터에서 값을 읽음&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EX&lt;/strong&gt;(Execute) : 연산 수행, 주소 계산&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MEM&lt;/strong&gt;(Memory) : 메모리에 접근&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WB&lt;/strong&gt;(Write Back) : 결과를 레지스터에 저장(write)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EJvO8/btqLNrxRwaZ/V3LnQLdJ51mLNoY1sibik0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EJvO8/btqLNrxRwaZ/V3LnQLdJ51mLNoY1sibik0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EJvO8/btqLNrxRwaZ/V3LnQLdJ51mLNoY1sibik0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEJvO8%2FbtqLNrxRwaZ%2FV3LnQLdJ51mLNoY1sibik0%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 위 이미지 &lt;em&gt;(강의 교재 figure 4.33)&lt;/em&gt; 는 단계별로 회로의 어느 부분인지 표시한 것이다. 아래 &lt;em&gt;(강의 교재 figure 4.28)&lt;/em&gt; 는 이전에 세탁 단계를 나타내듯 그림으로 파이프라인 단계를 표시한 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpVcI0/btqLGZvAe8y/jwbVJGFT0KKQJX01pRers1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpVcI0/btqLGZvAe8y/jwbVJGFT0KKQJX01pRers1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpVcI0/btqLGZvAe8y/jwbVJGFT0KKQJX01pRers1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpVcI0%2FbtqLGZvAe8y%2FjwbVJGFT0KKQJX01pRers1%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 여기서 오른쪽이 어두운 부분은 Read를 수행하는 것이고, 왼쪽이 어두운 부분은 Write를 수행하는 것으로 생각하면 된다. 그 외에 전체 색칠은 수행하는 회로, 색칠되지 않은 것은 이 명령에서 수행하지 않는 회로이다. 이미지의 instruction은 &lt;code&gt;add&lt;/code&gt;이므로 MEM 단계는 수행되지 않는다고 해석할 수 있다.&lt;/p&gt;
&lt;h2&gt;Pipeline Performance&lt;/h2&gt;
&lt;p&gt; 파이프라인을 적용했을 때 얼마나 성능이 향상되는지 살펴보자. 그 전에 상황을 다음과 같이 가정한다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Instruction class&lt;/th&gt;
&lt;th&gt;IF(Instruction fetch)&lt;/th&gt;
&lt;th&gt;ID(Register read)&lt;/th&gt;
&lt;th&gt;EX(ALU operation)&lt;/th&gt;
&lt;th&gt;MEM(Data access)&lt;/th&gt;
&lt;th&gt;WB(Register write)&lt;/th&gt;
&lt;th&gt;Total time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Load word (lw)&lt;/td&gt;
&lt;td&gt;200 ps&lt;/td&gt;
&lt;td&gt;100 ps&lt;/td&gt;
&lt;td&gt;200 ps&lt;/td&gt;
&lt;td&gt;200 ps&lt;/td&gt;
&lt;td&gt;100 ps&lt;/td&gt;
&lt;td&gt;800 ps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Store word (sw)&lt;/td&gt;
&lt;td&gt;200 ps&lt;/td&gt;
&lt;td&gt;100 ps&lt;/td&gt;
&lt;td&gt;200 ps&lt;/td&gt;
&lt;td&gt;200 ps&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;700 ps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;R-format&lt;br&gt;(add, sub, AND, OR, slt)&lt;/td&gt;
&lt;td&gt;200 ps&lt;/td&gt;
&lt;td&gt;100 ps&lt;/td&gt;
&lt;td&gt;200 ps&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;100 ps&lt;/td&gt;
&lt;td&gt;600 ps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch (beq)&lt;/td&gt;
&lt;td&gt;200 ps&lt;/td&gt;
&lt;td&gt;100 ps&lt;/td&gt;
&lt;td&gt;200 ps&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;500 ps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt; 레지스터 Read/Write는 100ps, 나머지는 200 ps가 소요된다. 이제 본격적으로 파이프라인이 적용된 Datapath와 그렇지 않은(Single-cycle) Datapath를 비교해보자.&lt;/p&gt;
&lt;p&gt; &lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2PVIb/btqLNsi9PbF/uZyJauLo0PnoTsvSufqjJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2PVIb/btqLNsi9PbF/uZyJauLo0PnoTsvSufqjJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2PVIb/btqLNsi9PbF/uZyJauLo0PnoTsvSufqjJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2PVIb%2FbtqLNsi9PbF%2FuZyJauLo0PnoTsvSufqjJk%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 우선, Non-pipelined Datapath이다. 단순히 모든 단계를 순차적으로 실행하며 한 명령이 전부 끝나고 다음 명령이 수행되는 방식이다. 한 Instruction 당 800ps가 소모되고 n 개의 instruction이 있으면 800n ps가 걸린다. 한 클럭에 모든 단계가 순차적으로 수행되어야 하므로 클럭 사이클은 800ps 이상이어야 한다.&lt;/p&gt;
&lt;p&gt; &lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cASbP4/btqLOPd7pIY/Q3qetk8sgMI2d13uc4gZjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cASbP4/btqLOPd7pIY/Q3qetk8sgMI2d13uc4gZjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cASbP4/btqLOPd7pIY/Q3qetk8sgMI2d13uc4gZjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcASbP4%2FbtqLOPd7pIY%2FQ3qetk8sgMI2d13uc4gZjK%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 이번에는 Pipelined Datapath이다. 여기서는 200 ps을 한 클럭으로 두고, 클럭마다 한 단계씩 실행하는데 이렇게 하면 한 Instruction을 수행하는 데 총 1000 ps가 소요된다. 하나만 실행했을 때는 더 느리지만, 파이프라이닝을 하기 때문에 첫 번째 명령이 ID 단계를 수행할 때 동시에 두 번째 명령의 IF 단계를 수행한다. 이런 방식으로 세 Instruction을 한 프로세서의 다른 부분에서 동시에 돌리기 때문에 전체 시간은 더 짧아진다. 이 방식으로 n개의 Instruction을 수행하는 데에는 (800 + 200n) ps가 소요된다.&lt;/p&gt;
&lt;h2&gt;Pipeline Speedup&lt;/h2&gt;
&lt;p&gt; 파이프라인을 통해 얻을 수 있는 속도 향상을 알아보자. 만약 모든 단계가 같은 시간을 소요하고 있다면 다음 식이 성립한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(Instruction 간의 시간 간격&lt;sub&gt;pipelined&lt;/sub&gt;)&lt;br&gt;= (Instruction 간의 시간 간격&lt;sub&gt;nonpipelined&lt;/sub&gt;) / (단계의 수)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;파이프라인을 사용하면 더 짧은 간격으로 Instruction을 실행할 수 있으므로 속도가 향상된다. 각 단계 별 소요 시간이 차이가 난다면 속도가 상대적으로 조금만 향상될 것이다.&lt;/p&gt;
&lt;p&gt;파이프라이닝은 Throughput을 향상시키는 방식으로 속도를 향상시킨다. 그렇지만 Latency(한 Instruction의 실행 시간)가 증가하는데, 우리는 실제로 수백만 ~ 수십억 Instruction을 실행해야 하기 때문에 이런 식으로 Throughput을 늘림으로서 더 시간을 아낄 수 있다.&lt;/p&gt;</description>
      <category>전공/컴퓨터 구조</category>
      <category>pipelining</category>
      <category>컴퓨터 구조</category>
      <category>파이프라이닝</category>
      <author>blacksmith16</author>
      <guid isPermaLink="true">https://identity16.tistory.com/26</guid>
      <comments>https://identity16.tistory.com/26#entry26comment</comments>
      <pubDate>Mon, 26 Oct 2020 13:26:20 +0900</pubDate>
    </item>
    <item>
      <title>[컴퓨터 구조] 4.4 A Simple Implementation Scheme</title>
      <link>https://identity16.tistory.com/25</link>
      <description>&lt;h2&gt;ALU Control&lt;/h2&gt;
&lt;p&gt;MIPS의 ALU는 4 bit Control 입력에 따라 어떤 연산을 할 지 결정한다.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;ALU Control&lt;/th&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;Function&lt;/th&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;Instruction 예시&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0000&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;AND&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;and&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0001&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;OR&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;or&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0010&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;add&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;lw, sw, add&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0110&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;subtract&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;sub, beq&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0111&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;set-on-less-than&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;slt&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1100&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;NOR&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt; 위 표는 4 bit Control 신호에 따른 ALU 연산과 어떤 Instruction에서 그 연산이 사용되는 지를 정리한 것이다. 이 4 bit 신호는 ALU Control이라는 유닛에서 결정한다.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;opcode(Instruction)&lt;/th&gt;
      &lt;th&gt;ALUOp&lt;/th&gt;
      &lt;th&gt;Instruction 연산&lt;/th&gt;
      &lt;th&gt;Funct field&lt;/th&gt;
      &lt;th&gt;ALU 연산&lt;/th&gt;
      &lt;th&gt;ALU Control&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;LW&lt;/td&gt;
      &lt;td&gt;00&lt;/td&gt;
      &lt;td&gt;load word&lt;/td&gt;
      &lt;td&gt;XXXXXX&lt;/td&gt;
      &lt;td&gt;add&lt;/td&gt;
      &lt;td&gt;0010&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;SW&lt;/td&gt;
      &lt;td&gt;00&lt;/td&gt;
      &lt;td&gt;store word&lt;/td&gt;
      &lt;td&gt;XXXXXX&lt;/td&gt;
      &lt;td&gt;add&lt;/td&gt;
      &lt;td&gt;0010&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Branch equal&lt;/td&gt;
      &lt;td&gt;01&lt;/td&gt;
      &lt;td&gt;branch equal&lt;/td&gt;
      &lt;td&gt;XXXXXX&lt;/td&gt;
      &lt;td&gt;subtract&lt;/td&gt;
      &lt;td&gt;0110&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;R-type&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;add&lt;/td&gt;
      &lt;td&gt;100000&lt;/td&gt;
      &lt;td&gt;add&lt;/td&gt;
      &lt;td&gt;0010&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;R-type&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;subtract&lt;/td&gt;
      &lt;td&gt;100010&lt;/td&gt;
      &lt;td&gt;subtract&lt;/td&gt;
      &lt;td&gt;0110&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;R-type&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;AND&lt;/td&gt;
      &lt;td&gt;100100&lt;/td&gt;
      &lt;td&gt;AND&lt;/td&gt;
      &lt;td&gt;0000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;R-type&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;OR&lt;/td&gt;
      &lt;td&gt;100101&lt;/td&gt;
      &lt;td&gt;OR&lt;/td&gt;
      &lt;td&gt;0001&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;R-type&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;set on less than&lt;/td&gt;
      &lt;td&gt;101010&lt;/td&gt;
      &lt;td&gt;set on less than&lt;/td&gt;
      &lt;td&gt;0111&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt; ALU Control는 Control로부터 ALUOp라는 2 bit 신호를 입력으로 가지고 그 입력에 따라 위 표의 ALU Control에 해당하는 4 bit 값을 ALU에게 넘겨준다. Control에서는 opcode의 종류에 따라 ALUOp를 생성한다. 이 때 LW와 SW의 ALUOp가 00으로 동일한 것은 어차피 ALU에서는 같은 연산을 하므로 굳이 구분할 필요가 없기 때문이다. 그리고 R-type은 000000으로 opcode가 동일하므로 ALUOp로 10을 넘겨준 다음, ALU Control에서 funct 필드를 읽어 어떤 R-type 명령인지 해석한 다음 ALU 연산을 결정한다.&lt;/p&gt;
&lt;p&gt; ALU Control 동작을 구현하는 회로를 작성하려면, 입력값인 ALUOp에 따른 4 bit 출력을 진리표로 만든 다음 카르노맵을 통해 각 출력 비트에 맞는 논리식을 얻을 수 있다. 그 식을 논리 게이트로 배치하면 ALU Control 회로 작성이 끝난다. 여기서는 굳이 그림이나 표로 표현하지는 않겠다.&lt;/p&gt;
&lt;h2&gt;Control&lt;/h2&gt;
&lt;p&gt; 이 부분은 ALU Control이 아니라 전체적인 동작을 제어하는 메인 Control에 대해 알아본다. 아래 이미지는 4.3에서 보여준 전체 회로이다.&lt;/p&gt;
&lt;p&gt; &lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cc7W0H/btqLNsDrsQS/fJTSKkjVy81Rv5KsvsXSo1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cc7W0H/btqLNsDrsQS/fJTSKkjVy81Rv5KsvsXSo1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cc7W0H/btqLNsDrsQS/fJTSKkjVy81Rv5KsvsXSo1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcc7W0H%2FbtqLNsDrsQS%2FfJTSKkjVy81Rv5KsvsXSo1%2Fimg.jpg&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 여기서 Control이라고 적혀있는 유닛이 우리가 다룰 Control이다. Instruction을 나타내는 비트 중에서 앞의 6 bit인 opcode를 입력으로 가진다. 많은 출력이 있는데 각 출력이 어디에 연결되는지를 주의깊게 보면서 하나씩 살펴보자.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RegDst&lt;/strong&gt; : Registers 유닛의 Write Register 입력을 결정하는 MUX에 연결되어 있다. 이 비트가 0이면 Write Register로 R&lt;sub&gt;t&lt;/sub&gt;를 사용한다는 의미이며, 1이면 R&lt;sub&gt;d&lt;/sub&gt;를 사용한다는 뜻이다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RegWrite&lt;/strong&gt; : Registers 유닛에 직접 연결되어 있다. 이 비트가 1이면 Write Register에 Write Data를 저장하는 동작을 수행하며, 0이면 저장하지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ALUSrc&lt;/strong&gt; : ALU의 두 입력 중 하나를 결정하는 MUX에 연결되어 있다. 이 비트가 0이면 R&lt;sub&gt;t&lt;/sub&gt;의 값을 ALU의 피연산자로 사용하고, 1이면 즉시값을 Sign Extend한 값을 사용한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Branch&lt;/strong&gt; : PC에 저장될 주소를 결정하는 MUX와 연관되어 있으며, 이 비트가 0이면 PC + 4가 PC에 저장된다. 그리고 Branch와 연결된 AND 게이트는 &lt;code&gt;beq&lt;/code&gt;를 처리하는 데에 쓰이는데, ALU의 Zero가 1이고 Branch가 1이면 MUX에서 Branch 타겟 주소가 PC에 저장되고 그렇지 않으면 PC + 4가 PC에 저장된다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MemRead&lt;/strong&gt; : Data Memory에 연결되어 있으며, 이 비트가 1이면 입력 주소의 값을 메모리에서 읽어 오고 0이면 읽지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MemWrite&lt;/strong&gt; : Data Memory에 연결되어 있으며, 이 비트가 1이면 입력된 메모리 주소에 Write Data 입력값을 저장하고 0이면 저장하지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MemtoReg&lt;/strong&gt; : Registers의 Write Data를 결정하는 MUX에 연결되어 있으며, 이 비트가 1이면 메모리에서 읽은 값이 Write Data로 들어가고 0이면 ALU 연산 결과가 들어간다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ALUOp&lt;/strong&gt; : 위에서 설명함&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; 아래 표는 Instruction의 종류에 따라 Control 출력이 어떻게 되어야 하는지 나타낸 것이다. X는 상관 없음을 뜻한다. 왜 이렇게 되어야 하는지는 각 Instruction의 동작을 생각해본다면 쉽게 이해할 수 있을 것이다.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;Instruction&lt;/th&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;RegDst&lt;/th&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;ALUSrc&lt;/th&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;Memto- Reg&lt;/th&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;Reg- Write&lt;/th&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;Mem- Read&lt;/th&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;Mem- Write&lt;/th&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;Branch&lt;/th&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;ALUOp1&lt;/th&gt;
      &lt;th style=&quot;text-align:center&quot;&gt;ALUOp0&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;R-format&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;lw&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;sw&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;X&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;X&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;beq&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;X&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;X&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align:center&quot;&gt;1&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2&gt;Implementing Jumps&lt;/h2&gt;
&lt;p&gt; 드디어 마지막 Instruction인 &lt;code&gt;j&lt;/code&gt; 명령어를 지금까지 만든 회로에 추가할 시간이다. &lt;code&gt;j&lt;/code&gt;는 J-Format Instruction이라서 앞의 6 bit(opcode)를 제외한 나머지 26 bit는 주소값을 나타낸다. Branch 명령어와의 공통점은 주소가 Word Address이기 때문에 Shift Left 2를 하여서 맨 뒤에 00 비트를 추가해준다는 것이다. 그렇지만 차이점은 &lt;code&gt;beq&lt;/code&gt;의 주소는 offset(현재 PC 값에서 더해서 진짜 주소 계산)이지만 &lt;code&gt;j&lt;/code&gt;의 주소는 그 값이 곧 메모리 주소라는 것이다.&lt;br&gt; 하지만 진짜 메모리 주소는 32 bit가 되어야 하는데, J-Format에서는 26 bit 값을 입력받고 Shift 한 것까지 생각하면 총 28 bit라서 4 bit가 부족하다. 그래서 &lt;code&gt;j&lt;/code&gt;에서는 (PC + 4)에서 왼쪽 4 bit를 그대로 가져와 남은 4 bit를 채운다. 이러한 점 때문에 &lt;code&gt;j&lt;/code&gt; 명령어는 Branch 명령보다는 더 넓은 범위를 오갈 수 있지만 (PC + 4)와 앞 4 bit가 같은 영역으로 점프 가능 범위가 제한된다.&lt;br&gt; 이런 특성을 반영하여 &lt;code&gt;j&lt;/code&gt;를 회로에 추가하면 아래 이미지와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0AbNn/btqLNtbh6qk/JgnONkTnjlAqHAkiCHeaw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0AbNn/btqLNtbh6qk/JgnONkTnjlAqHAkiCHeaw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0AbNn/btqLNtbh6qk/JgnONkTnjlAqHAkiCHeaw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0AbNn%2FbtqLNtbh6qk%2FJgnONkTnjlAqHAkiCHeaw1%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; Shift를 하기 위한 유닛과 PC에 들어갈 수 있는 값이 하나 더 추가되었기 때문에 MUX 하나를 더 넣었고 이를 제어하기 위한 Jump가 Control에 추가되었다.&lt;/p&gt;</description>
      <category>전공/컴퓨터 구조</category>
      <category>ALU</category>
      <category>control</category>
      <category>컴퓨터 구조</category>
      <category>회로 설계</category>
      <author>blacksmith16</author>
      <guid isPermaLink="true">https://identity16.tistory.com/25</guid>
      <comments>https://identity16.tistory.com/25#entry25comment</comments>
      <pubDate>Mon, 26 Oct 2020 13:18:28 +0900</pubDate>
    </item>
    <item>
      <title>[컴퓨터 구조] 4.3 Building a Datapath</title>
      <link>https://identity16.tistory.com/24</link>
      <description>&lt;p&gt; Datapath란 CPU에서 데이터와 주소를 처리하는 요소들을 말한다. 레지스터, ALU, MUX, 메모리 등이 Datapath라 할 수 있다. 지금부터는 &lt;code&gt;lw&lt;/code&gt;, &lt;code&gt;sw&lt;/code&gt;, &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;slt&lt;/code&gt;, &lt;code&gt;beq&lt;/code&gt;, &lt;code&gt;j&lt;/code&gt; 총 9가지 명령어를 수행할 수 있는 프로세서의 Datapath를 점점 완성해 나갈 것이다.&lt;/p&gt;
&lt;h2&gt;Instruction Fetch&lt;/h2&gt;
&lt;p&gt; 우선 모든 Instruction을 처리하기 위한 첫 단계인 Instruction Fetch를 먼저 살펴보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ket0r/btqLIGICRLA/HvEUYKw6VYpklQFzAv1pV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ket0r/btqLIGICRLA/HvEUYKw6VYpklQFzAv1pV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ket0r/btqLIGICRLA/HvEUYKw6VYpklQFzAv1pV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKet0r%2FbtqLIGICRLA%2FHvEUYKw6VYpklQFzAv1pV0%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 위 이미지 &lt;em&gt;(강의 교재 figure 4.6)&lt;/em&gt; 의 요소들에 대해 간단하게 알아보자.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PC&lt;/strong&gt; : Program Counter. 실행할 명령어의 주소를 저장하고 있는 레지스터이다. State Element이기 때문에 이미지엔 없지만 Clock Input도 있다고 생각하면 된다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instruction Memory&lt;/strong&gt; : 명령어의 주소를 받아서, 그 주소에 맞는 Instruction을 내보낸다. Instruction은 2장에서 다룬 32 bit 형식(R, I, J Format)이다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Adder&lt;/strong&gt; : 말 그대로 덧셈을 하는 요소. 위 이미지에서는 다음 명령어 주소를 가리키기 위해 (현재 주소 + 4)를 하기 위해 존재한다. 4를 더하는 것는 Instruction의 길이가 32 bit이고, 주소 하나가 1 byte(8 bit)이므로 4 byte 뒤의 주소가 다음 명령어의 주소이기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;R-Format Instructions&lt;/h2&gt;
&lt;p&gt; 여기에서 소개할 것들은 R-Format Instruction을 구현하는 데 필요한 요소들이다. 우리가 구현하려는 Instruction 중에서 R-Format은 &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;slt&lt;/code&gt;이다.&lt;br&gt; R-Format Instruction의 형태는 2장에서 다루기 때문에 &lt;em&gt;(포스팅은 아직 올리지 않음)&lt;/em&gt; 바로 설명하자면, R-Format은 피연산자로 2개의 Read Register(R&lt;sub&gt;s&lt;/sub&gt;, R&lt;sub&gt;t&lt;/sub&gt;) Number와 1개의 Write Register(R&lt;sub&gt;d&lt;/sub&gt;) Number를 가진다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciGjzW/btqLNr40Rha/ewSH07ASw1HpoDfWRzxmH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciGjzW/btqLNr40Rha/ewSH07ASw1HpoDfWRzxmH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciGjzW/btqLNr40Rha/ewSH07ASw1HpoDfWRzxmH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciGjzW%2FbtqLNr40Rha%2FewSH07ASw1HpoDfWRzxmH0%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위 이미지 &lt;em&gt;(강의 교재 figure 4.7)&lt;/em&gt; 와 같이 살펴보자.&lt;/p&gt;
&lt;p&gt; Registers에서는 3개의 Register Number(각 5 bits)를 입력으로 받는다. 그리고 출력으로 두 Read Register의 값을 읽어와 ALU로 넘긴다. ALU에서는 Instruction의 종류에 맞는 연산을 수행하는데, 이는 ALU operation이라는 플래그에 의해 결정된다. 그리고 연산 결과가 Write Register에 저장되어야 하므로 ALU result는 Registers의 Write Data 포트로 들어가고 Write Register에 저장된다.&lt;/p&gt;
&lt;h2&gt;Load / Store Instructions&lt;/h2&gt;
&lt;p&gt; &lt;code&gt;lw&lt;/code&gt;, &lt;code&gt;sw&lt;/code&gt;를 구현할 때 신경써야 할 점은, 메모리에 접근한다는 점과 레지스터 2개(R&lt;sub&gt;s&lt;/sub&gt;, R&lt;sub&gt;t&lt;/sub&gt;)를 입력받는데 &lt;code&gt;lw&lt;/code&gt;에서는 R&lt;sub&gt;t&lt;/sub&gt;가 Write로 사용된다는 것이다. 또, 메모리 offset을 16 bit 즉시 값(&lt;code&gt;lw&lt;/code&gt;, &lt;code&gt;sw&lt;/code&gt;가 I-Format이기 때문)으로 입력받고 이를 R&lt;sub&gt;s&lt;/sub&gt;에서 읽은 베이스 주소값(32 bit)에 더해야 한다. 우리가 사용할 ALU는 32 bit 값 두 개의 연산을 할 수 있기 때문에 16 bit인 offset을 32 bit로 확장한 다음 ALU의 입력 값으로 넘겨야 하는데, 이 때 Sign Extension을 하여 값을 유지한 채로 32 bit로 바꿔준다.&lt;/p&gt;
&lt;p&gt; &lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cb6ix0/btqLElzajUl/f9P5WSh7f7sVOlrh5FwEC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cb6ix0/btqLElzajUl/f9P5WSh7f7sVOlrh5FwEC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cb6ix0/btqLElzajUl/f9P5WSh7f7sVOlrh5FwEC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcb6ix0%2FbtqLElzajUl%2Ff9P5WSh7f7sVOlrh5FwEC0%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 위 이미지 &lt;em&gt;(강의 교재 figure 4.9)&lt;/em&gt; 는 이 단계에서 사용되는 두 유닛을 나타낸다. Sign Extension Unit은 16 bit 즉시값을 32 bit로 변환하는데 사용되고, Data Memory Unit은 메모리 주소를 입력받고 MemWrite, MemRead 플래그 상태에 따라 메모리를 읽거나 Write Data 입력으로 들어온 데이터(&lt;code&gt;sw&lt;/code&gt;일 때 R&lt;sub&gt;t&lt;/sub&gt;의 값)를 메모리에 쓴다. 이 때, 메모리 주소는 (R&lt;sub&gt;s&lt;/sub&gt; 레지스터에 들어 있는 베이스 주소 + Sign Extension한 offset)으로 결정된다. &lt;code&gt;lw&lt;/code&gt;이면 Read Data를 R&lt;sub&gt;t&lt;/sub&gt;에 저장하기 위해 Registers의 Write Data로 연결해준다. 지금까지 나온 부분을 합쳐서 그리면 아래 이미지와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cm38b9/btqLJWLdKuR/jsmB0ciFMZxbJaWBR1ZMlK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cm38b9/btqLJWLdKuR/jsmB0ciFMZxbJaWBR1ZMlK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cm38b9/btqLJWLdKuR/jsmB0ciFMZxbJaWBR1ZMlK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcm38b9%2FbtqLJWLdKuR%2FjsmB0ciFMZxbJaWBR1ZMlK%2Fimg.jpg&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; 같은 포트로 들어갈 수 있는 데이터들은 MUX로 Instruction에 따라 선택할 수 있도록 하였고 MUX, Registers, Data Memory, ALU의 동작을 제어하기 위한 플래그(빨간 색으로 표시된 것)들은 다음 포스팅에 설명할 Control에서 Instruction의 종류에 따라 결정한다.&lt;/p&gt;
&lt;p&gt; 지금까지 만든 회로로 실행할 수 있는(Control이 있다고 가정) 명령어는 &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;stl&lt;/code&gt;, &lt;code&gt;lw&lt;/code&gt;, &lt;code&gt;sw&lt;/code&gt; 이다. 이제 &lt;code&gt;beq&lt;/code&gt;, &lt;code&gt;j&lt;/code&gt;만 남았다. 일단 &lt;code&gt;j&lt;/code&gt;는 다음 포스팅에서 다루도록 하겠다.&lt;/p&gt;
&lt;h2&gt;Branch Instructions&lt;/h2&gt;
&lt;p&gt; &lt;code&gt;beq&lt;/code&gt;는 I-Format이기 때문에 값이 같은지 비교할 두 레지스터와 두 값이 같을 때 수행할 Instruction의 주소 Offset을 16 bit 즉시값을 피연산자로 갖는다. &lt;code&gt;lw&lt;/code&gt;, &lt;code&gt;sw와&lt;/code&gt; 마찬가지로 즉시값은 Sign Extend하여 32 bit로 만들어 준다. 하지만 &lt;code&gt;beq&lt;/code&gt;에서는 Shift left를 두 번(4배) 해주는데, Instruction은 1 word이고 word가 위치한 곳은 정렬되어 있기 때문에 항상 주소값의 뒷자리가 00이다. 바이트 정렬에 대해서는 &lt;img src=&quot;https://stackoverflow.com/questions/2846914/what-is-meant-by-memory-is-8-bytes-aligned&quot; alt=&quot;링크 1(영어)&quot;&gt; &lt;img src=&quot;https://kldp.org/node/95018&quot; alt=&quot;링크 2(한글)&quot;&gt; 을 참고하면 더 자세하게 알 수 있고, 2장의 Branch Addressing &lt;em&gt;(포스팅은 아직 올리지 않음)&lt;/em&gt; 을 설명하는 부분에서 앞서 설명되었다.&lt;br&gt; Branch Target Address는 (PC + 4) + (offset * 4)으로 계산할 수 있고 &lt;em&gt;(이것도 2장에서 이미 언급)&lt;/em&gt;, 두 레지스터(R&lt;sub&gt;s&lt;/sub&gt;, R&lt;sub&gt;t&lt;/sub&gt;)의 값이 같으면 이 주소가 PC에 저장된다. 두 레지스터의 값을 비교할 때는 ALU에서 두 값을 뺀 다음, Zero 출력이 1이 되는지 확인한다. ALU의 Zero는 연산의 결과가 0이면 1이되고 아니면 0이 되는 출력값이다. ALU에는 출력이 ALU Result와 Zero 총 2개가 있다고 생각하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tLeCA/btqLGXKFmDX/PkJje3iyGvHEYZqexEX7Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tLeCA/btqLGXKFmDX/PkJje3iyGvHEYZqexEX7Kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tLeCA/btqLGXKFmDX/PkJje3iyGvHEYZqexEX7Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtLeCA%2FbtqLGXKFmDX%2FPkJje3iyGvHEYZqexEX7Kk%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2&gt;Composing the Elements&lt;/h2&gt;
&lt;p&gt; 앞서 Instruction Fetch, R-Format, Load / Store 부분을 합친 회로를 보여줬는데 여기서는 요소들을 합칠 때 생각해 볼 것들을 알아볼 것이다.&lt;/p&gt;
&lt;p&gt; 합치기 전 각각의 Datapath들은 한 가지 Instruction을 실행할 수 있을 것이고 여러 Instruction을 동시에 수행하기 위해 이들을 병렬적으로 놓는다면 ALU 같이 여러 Datapath에 등장하는 요소는 같은 것이 여러 개가 필요할 것이다. 중복된 부품은 비용 증가로 이어지기 때문에, 그렇기 보다는 한 요소에 들어가는 Input을 선택적으로 넣을 수 있도록 MUX를 놓는 것이 더 효율적이다. 그래서 앞에서 보여준 회로는 MUX를 이용해 중복을 피하며 합칠 수 있었다. 그리고 이 MUX의 출력을 선택하는 플래그를 결정하기 위해 Control이 필요한 데 이는 다음 포스팅의 주제이다.&lt;/p&gt;
&lt;p&gt; MUX는 beq까지 합친 회로에서 어떤 부분에서 필요할까?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ALU 입력 : 레지스터 입력(&lt;code&gt;add&lt;/code&gt;, &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;slt&lt;/code&gt;) or 즉시값(&lt;code&gt;lw&lt;/code&gt;, &lt;code&gt;sw&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Register Write Data : ALU 결과(&lt;code&gt;add&lt;/code&gt;, &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;slt&lt;/code&gt;) or 데이터에서 읽은 값(&lt;code&gt;lw&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;다음 PC 값 : PC + 4(&lt;code&gt;add&lt;/code&gt;, &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;slt&lt;/code&gt;, &lt;code&gt;lw&lt;/code&gt;, &lt;code&gt;sw&lt;/code&gt;) or Branch Target Address(&lt;code&gt;beq&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Write Register Number : R&lt;sub&gt;d&lt;/sub&gt;(&lt;code&gt;add&lt;/code&gt;, &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;slt&lt;/code&gt;) or R&lt;sub&gt;t&lt;/sub&gt;(&lt;code&gt;lw&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBOJYj/btqLJUUblBl/ayIOUTfTjqcithMtypIxjk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBOJYj/btqLJUUblBl/ayIOUTfTjqcithMtypIxjk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBOJYj/btqLJUUblBl/ayIOUTfTjqcithMtypIxjk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBOJYj%2FbtqLJUUblBl%2FayIOUTfTjqcithMtypIxjk%2Fimg.jpg&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt; &lt;code&gt;beq&lt;/code&gt;까지 전부 합치고 Control, ALU Control까지 추가한 그림이다. Control에 대해서는 다음 포스팅에서 다루겠지만, 간단하게 말하자면 opcode를 읽고 instruction의 종류에 따라 MUX에서 어떤 값을 선택할지, 메모리를 쓸 지 읽을지, 레지스터에 값을 저장할 지 등에 대한 선택을 한다고 생각하면 된다. ALU의 연산을 결정하는 것은 ALU Control이라는 Control을 한 번 더 거쳐서 결정하게 된다.&lt;br&gt; PC는 State Element이고, 나머지는 Combinational Element이기 때문에 전체 회로를 도는 데에는 1 Clock이 소요(CPI = 1)되어야 한다. 즉, 이 회로가 도는 속도에 따라 프로세서의 클럭 주기가 결정된다고 할 수 있다.&lt;/p&gt;</description>
      <category>전공/컴퓨터 구조</category>
      <category>Datapath</category>
      <category>컴퓨터 구조</category>
      <author>blacksmith16</author>
      <guid isPermaLink="true">https://identity16.tistory.com/24</guid>
      <comments>https://identity16.tistory.com/24#entry24comment</comments>
      <pubDate>Sun, 25 Oct 2020 18:52:40 +0900</pubDate>
    </item>
  </channel>
</rss>