컴퓨터 구조는 다음의 세가지로 정의된다고 계속 강조한다.
ⓐ 내부 레지스터
- 사용할 하드웨어 자원을 정의하기
ⓑ instruction set
- 가능한 명령어 집합을 정의하기
ⓒ control unit
- 정의된 명령어들이 하드웨어 리소스상에서 제대로 작동하게끔 설계하기
위 세가지를 정의하고 설계해야 컴퓨터가 이루어진다.
앞선 포스팅에서는 ⓐ와 ⓑ에 해당하는 '레지스터를 정의하는 것, 명령어 집합을 정의하는 것'이 뭔지 확인했다. 그리하여 이번 포스팅에서는, 정의된 명령어들이 정의된 레지스터들을 기반으로 제대로 작동되게끔 설계하는 방법을 확인해 볼 것이다.
즉, Control unit 설계하기!
Control unit의 역할?
이 포스팅에서 다음과 같이 얘기했었다.
각 레지스터에는 clock이 연결되어있다. 클럭속도를 1GHz라고 하자(1초에 10억번씩 clock이 깜빡인다). 그럼 클럭이 켜진 상황에서 만약 LD라는 control signal이 켜져있는 상태라면, LD를 수행하게 된다. 즉, control signal이 타이밍에 맞게 발생해야 레지스터 연산이 제때제때 수행될 수 있다. 그래서 어떠한 control signal이 제시간에 잘 발생되는 것이 아주 중요한데, 이를 가능케 하는 'Control unit'이라는 것을 추후에 설계할 것이다. Control unit은 컴퓨터 구조를 정의하는 세가지 중 하나였음음을 기억하자. 곧 공부하게 될 것이고, 중요하다.
그렇다. 타이밍에 맞게 control signal(instruction의 선택)이 generate 되는 것이 중요하다.
레지스터의 내용은 control signal이 활성화되어있을 때 clock이 켜지면 바뀐다. 클럭은 아주 빠르게 켜졌다 꺼졌다 하므로, 중요한 것은 control signal이 타이밍에 맞게 활성화 되어야 한다. 이 control signal은 오늘 학습할 control unit에 의해 발생된다.
Control unit를 설계하는 방법
두 가지 방법이 있다.
Hardwired control unit과 Microprogrammed control unit이다.
▶ Hardwired control unit :
- 하드웨어 로직을 설계하는 것이다. 여러가지 gate들, fip-flop, decoder, 여러 logic circuit 등으로 구성된다. 우리가 아는 모든 컴퓨터, 장치들은 Hardwired control unit으로 설계되어 있을 것이다. 우리가 16비트 컴퓨터를 설계할 때에도 당연스럽게 Hardwired control unit으로 설계할 것이다.
- 속도가 엄청나게 빠르지만(3GHz.. 4GHz..) 수정이 어렵다(수정하려면 처음부터 다시 수정). 그리고 하드웨어 로직을 설계해내는 비용도 비싸다.
▶ Microprogrammed control unit :
- CPU 내부에는 아주 고가의 control memory라는 것이 있는데, 발생하는 control signal들을 여기 control memory에 집어넣어둔다(micro-instruction). 그리고 다시 이 control memory에서 해당되는 control signal을 읽어서 generate해준다.
- 얘는 control memory에 있는 micro-instruction들을 읽어서 control signal을 generate해야하기 때문에 속도가 Hardwired control unit과 비교도 안되게 느리다. 수정은 비교적 쉽다. micro programming만 하면 되기 때문에 설계 비용이 저렴하고 수정도 용이하다. 속도, 성능이 전혀 필요없고 하나도 중요하지 않다면 값싸게 microprogrammed unit으로 설계하면 되겠다. 지금 16비트 컴퓨터를 설계하는 데에는 이 방법을 사용하지 않지만, 추후에 이 방법도 배울 것이다. 사용되는 예시: 세탁기, 전기밥솥, 자판기 등은 연산속도같은 건 활용되지 않는다. 세탁하고 밥하는 건 0.000000000000001초만에 이루어지지 않는다. 세탁물은 여전히 오랜 시간 빨아서 깨끗하게 해야 하고, 밥하는데 시간은 예나 지금이나 30분(+a) 걸린다.
Control unit의 동작 구조
방금 전에 말했지만, control signal이 먼저 활성화되고 나서 clock이 떠야 레지스터의 데이터를 바꿀 수 있다. control signal이 어떻게 활성화될까? 아래의 Control unit에서 최종 출력하는 것이 control signal이다.
Control unit의 큰 구성은 2개의 decoder, 1개의 sequence counter (CS), 그리고 여러 논리 게이트들, 그리고 instruction register (IR)로 이루어져있다.
먼저 간단히 슥 보자.
Instruction Register의 명령어가 해독되어 Control logic 게이트로 들어가고
Sequence Counter가 일으키는 타임값이 Control logic 게이트로 들어가서
결과적으로 control signal이 도출된다.
조금 더 자세히 살펴보자.
명령어 코드가 저장되는 부분 (그림의 상단)
- 메모리에서 읽어온 명령은 명령레지스터(IR)에 저장된다.
- 저번 포스팅에서 보았듯이 명령어의 구조는 'addressing모드, opecode, address부분'으로 나누어져있다. 그중 operation code에 해당하는 14, 13, 12비트 이렇게 세비트는 "3x8사이즈의 decoder(명령해독기)"로 들어가게 된다. 어떤 operation인지 결정하는 그 비트 3개가 입력되었으므로, decoder의 결과는 2^3=8가지다.
- 명령어 코드에서 가장 최상위에 있는 addressing mode 비트는 I라는 flip-flop으로 전송된다. 모드를 구분하는 역할.
- 명령어 코드에서 오른쪽에 있는 12비트는 control logic gate로 들어간다.
Sequence Counter (그림의 하단)
- 4비트 Sequence Counter(순차 카운터)는 4비트의 값을 출력하여 4x16사이즈의 decoder로 들어가게 하고 있다. 4비트 카운터에서는 0001, 0010, 0011, ..., 1111의 비트를 발생시켜 카운트를 진행한다. 이는 순서값을 발생시킨 것이라고 볼 수 있는데, 그 4비트가 순서의 의미를 가지고 decoder의 입력값으로 들어간다. 그럼 그 순서값이 차례대로 들어옴에 따라서 디코더 출력은 2^16개의 타임 신호를 순차적으로 발생시키게 된다.
- 예를들어 SC의 출력이 0000이었다면 디코더의 입력은 0000이고 디코더의 출력은 0이며, 이는 time T0에 해당한다. 이후에도 카운터가 계속 진행됨에 따라 T1, T2, ... 의 순서대로 타임 신호가 발생한다.
결과적으로 Sequence counter에 의해 time들이 뜨게 된다. (T0, T1, T2, ...)
그리고 T0, T1, ... 의 timing signal은 순차적으로 뜨게 된다.
명령이 들어올 때 Timing signal이 발생하는 과정?
컴퓨터의 하드웨어 자원들, 즉 레지스터에는 각각의 기능을 수행하는 LD, INR, CLR 등의 control signal이 연결되어 있다고 했다. 이 control signal들이 타이밍이 맞게 잘 발생해야 레지스터 연산이 제때제때 수행될 수 있다. 그래서 control signal들이 제시간에 잘 발생되는 것이 중요하다고 지난 포스팅에서 말했었다.
그럼 우리가 실행해야 할 control signal, 즉 명령어들이 decode되어서 결국 출력되는 건 알겠는데, 도대체 어떤 time에 출력되어야 하는가? 그걸 알아보자.
■ 일단 아래 그림을 이해할 수 있어야 한다.
잠시 아래 그림을 보자.
맨 위는 Clock이고 그 밑은 time T0, T1, ...이다.
Clock이 뜨기 이전에 timeT가 켜져있으면,
Clock이 켜질때 time T가 발생한다는 것을 확인할 수 있다.
또한 아래 그림에서 보면 매 클럭마다 time이 순차적으로 켜지고 있다. (실제로는 그렇지는 않다. 사이클이 이런 식으로 딱딱 맞지 않는다. )
이어서 상황파악을 해보자.
- 잘 보면 D3라는 신호가 time T2에 1이 되었다. D3이라는 신호는 연산코드 디코더에서 출력한 D0, D1, ..., D7의 8개값 중 D3이다. 즉, 아까 회로그림에 있었던 3x8 decoder가 어떤 operation code를 읽었는데, decoder를 거치니까 D3이 1값으로 출력된 것이다.
- 아무튼 time T2에서 D3가 1로 떴다는 말을 하고 싶었다. 즉, time T2에서 어떤 instruction이 들어왔다.
참고: D3가 쭉 1로 유지되고 있다. 언제 바뀌는가? IR에 새로운 instruction이 fetch되면 새로운 세비트 opcode가 들어온다. 그게 decoding되면 그때 바뀐다.
■ 사실 위 그림은 D3T4 : SC <- 0이라는 제어문을 나타낸 것이다. 차근차근 이해해보자.
여기까지 이해했으면 다음의 제어문을 보자.
D3T4 : SC <- 0
위 제어문은 D3=1이고 T4=1이라면, SC를 0으로 클리어하라는 문장이다.
(참고로 SC 클리어를 하려면 CLR=1 신호가 떠야 한다.)
D3T4 : SC <- 0라는 제어문을 그림과 함께 다시 보자.
T2부터 D3=1로 쭉 켜져있고, T4도 1인 상황이 왔다. 즉 T4=1 and D3=1인 상황.
그 때는 이제 위 제어문에 따라 SC<-0을 실행해야 한다. SC<-0을 실행하려면 CLR를 1로 띄우면 된다. 그러면 Clear되어서 SC값이 0이 된다.
깔끔하게 정리하자면 T2에서 intruction을 해독하였고, T4에서 Clear하였다.
이건 Instruction cycle과 관련있다. 이제 곧 언급할거다.
■ 그렇구나.. 근데 자꾸 time T0로 초기화되네?
가만보면 사실 time T0이전에 이미 CLR 신호가 떴었고, SC는 초기화되어서 time신호가 다시 T0로 되돌아갔었다. 그래서 위 클락을 보면 다시 time T0부터 시작되는 것이다. 또다시 순차적으로 T0, T1, ....가다가 이번에는 T4=1이고 D3=1인 상황이 왔다. 그러면 CLR=1로 하여 SC를 초기화하라는 저 제어문이 작동한다. 그러면 또 SC를 초기화하고 time 신호는 T0부터 시작되게 된다. (참고로 SC는 동기적으로 클리어되는 기능을 가진다.)
즉, 항상 instruction은 T0부터 시작하는 꼴이다!
Instruction Cycles
방금 보고 왔듯이, 어떤 instruction이 뜨면 항상 T0로 초기화되었다.
사실 아래와 같은 사이클 개념이 있다!
- memory-reference instruction인 경우 -
▽ 메모리로부터 instruction을 fetch
▽ instruction을 decode
▽ 메모리로부터 effective address를 읽기
(정해진 addressing mode 고려한다. indirect라면 유효 주소를 읽어오면 되지만, 만약 direct모드라면 어떻게 될까? direct모드면 명령어의 address부분에 주소가 아닌 피연산자 값 자체가 들어가는데 말이다. 아 그러면 이 clock은 쉬어가는 clock이 된다. 아무런 micro operation도 일어나지 않는다.)
▽ instuction을 실행
만약 memory-reference instruction이 아니라, 다른 두개의 instruction 즉 I/O나 register-reference intruction인 경우에는 세번째를 거치지 않는 사이클이다.
특히 Fetch와 Decode는 아래와 같은 time에서 실행된다!
T0 : AR <- PC
T1 : IR <- M[AR],
PC <- PC + 1
T2 : D0, ..., D7 <- decode IR(12-14),
AR <- IR(0-11),
I <- IR(15)
이렇게 Fetch와 Decode하는 데에는 3클락이 소요된다.
이해를 위해 살짝 더 설명하겠다.
▷ T0에서는 PC가 가리키는 주소를 AR에 전송한다.
- PC는 다음 fetch(인출)될 명령어의 주소를 가지고 있는 레지스터다.
- AR은 이제 사용될 명령어 주소를 일시적으로 저장해두는 주소 레지스터다.
▷ T1에서는 IR <- M[AR], 그리고 PC의 값을 하나 증가시킨다.
- IR은 가장 최근에 fetch된 명령어(현재 실행 중인 명령어)가 저장되는 레지스터다. intruction register.
▷ T2에서는 IR에 저장된 명령어 코드의 ①operation code 부분이 디코드되고, ②AR에다가 피연산자를 담고 있는 주소 정보를 넘기고, ③addressing mode 선택지가 담긴 명령어코드의 최상위비트(15비트)를 I라는 레지스터에 담는다.
instruction Cycles에 대한 다른 중요한 내용은
바로 다음 포스팅에서 따로 설명하겠다.
이번 포스팅에서 본 것은?
■ 정의된 레지스터 환경 하에서, 정의된 명령어가 타이밍에 맞게 잘 발생되기 위해서는 이번 시간에 배운 Control Unit을 잘 설계해야 한다고 했다.
■ 그래서 Control Unit의 구조를 학습했다. 이 회로의 최종 출력값이 control signal이었다.
■ Control unit에서 Sequence Counter가 발생시키는 time T0, T1, ...에 대한 개념도 접했다.
■ 이 time과 관련하여 Instruction Cycle이 존재함을 인지했다.
그래서 다음 포스팅에서는 instruction cycle을 공부해보고자 한다.
'컴퓨터구조 & OS' 카테고리의 다른 글
[컴퓨터구조] 16비트 컴퓨터 설계하기 - 명령어의 실행단계에서 벌어지는 일들 (2) | 2021.10.15 |
---|---|
[컴퓨터구조] 16비트 컴퓨터 설계하기 - Instruction Cycles (2) | 2021.10.15 |
[컴퓨터구조] 16비트 컴퓨터를 설계하자 - Instruction set 정의하기 (0) | 2021.10.13 |
[컴퓨터구조] 16비트 컴퓨터 설계하기 - 레지스터를 정의하자 (0) | 2021.10.13 |
[컴퓨터구조] 16비트 컴퓨터 설계하기 - 명령어 코드의 구조 | Instruction Codes (0) | 2021.10.12 |