레지스터 파일: 접근할 레지스터 번호를 지정함으로써 알고 쓸 수 있는 레지스터들의 집합으로 구성된 state element
위 그림은 명령어를 인출하고 프로그램 카운터를 증가시키는 데 사용하는 데이터패스 일부분이다.
R형식 ALU연산을 구현하는데 필요한 두 개의 구성 요소는 레지스터 파일
과 ALU
이다.
위 그림은 R형식
명령어 연산을 수행 할때 볼 수 있는 모습이다.
R형식 명령어들은 레지스터 피연산자 세 개를 가지고 있기 때문에, 매 명령어마다 레지스터 파일에서 2개의 데이터 워드를 읽고 데이터 워드 하나를 써야 한다.
레지스터에서 데이터 워드를 읽으려면 레지스터의 입력과 출력이 하나씩 필요하다.
읽을 레지스터 번호를 지정하는 입력
,레지스터에서 읽을 값을 내보내는 출력
이다.
데이터 워드를 쓰기 위해서는 입력이 두개 필요하다. 첫번째 입력은 레지스터 번호를 지정하고 두번째 입력은 레지스터에 쓸 데이터 값을 제공한다.
레지스터 파일은 Read register 입력에 실리는 번호에 해당하는 레지스터 내용을 항상 출력한다.
그러나 쓰기는 쓰기신호에 의해 제어되므로 클럭 에지에서 쓰기가 일어나려면 이 제어 신호가 인가되어야 한다.
따라서 전체적으로 네 개의 입력(레지스터 번호용 세 개, 데이터용 한 개)과 두개의 출력(모두 데이터용)이 필요하다.
레지스터 번호 입력은 32개의 레지스터중 하나를 지정해야 하므로 5비트 크기()인 반면, 데이터 입력과 데이터 출력 버스는 모두 32비트 폭을 가진다.
위 그림에 있는 ALU는 32비트 입력 두 개를 받아서 32비트 결과와 결과가 0인지 아닌지를 나타내는 1비트 신호를 만든다.
MIPS에서 lw는 load word sw는 store word로 사용된다.
lw $t1, offset_value($t2)
- t1의 레지스터에 t2로부터 offset_value만큼 떨어진 값을 불러온다.
sw $t1, offset_value($t2)
- t2의 레지스터에서 offset_value만큼 떨어진 주소에 t1레지스터의 값을 저장한다.
이 두 명령어에서 ALU, 레지스터 파일이 필요한 이유는 다음과 같다.
1.이 명령들은 베이스 레지스터(여기서는 $t1)와 명령어에 포함되어 있는 16비트 부호있는 변위 필드를 더하여 메모리 주소를 계산한다.
2.명령어의 16비트 변위 필드값을 32비트 부호있는 값으로 부호확장(sign-extend)하기 위한 유닛이 필요하며 또 읽고 쓸 데이터 메모리가 필요하다. 데이터 메모리는 저장 명령어 일때만 쓰기를 해야 한다. 따라서 데이터 메모리는 읽기와 쓰기 제어신호, 주소 입력, 메모리에 쓸 데이터 입력이 필요하다.
레지스터와 ALU 이외에 load와 store에 필요한 두 유닛은 Data memory unit
과 sign extension unit
이다.
beq 명령어는 비교할 레지스터 두개와 16비트 변위 세 피연산자를 갖는다.
형식은 beq $t1 $t2,offset
이다.
이 명령어를 구하기 위해서는 PC 값에다 명령어 변위 필드의 부호확장 값을 더해서 분기 목적지 주소를 구해야 한다. (beq의 offset은 word 단위 이므로 byte 단위 절대주소와 착각하지 않도록 주의해야한다. 또한 한 명령어가 끝나면 +4byte를 한다는 것도 잊지 말아야 한다. 예를들어, beq의 offset이 1이라면 beq 바로 다음 명령어 주소로 이동하는 것이아니라, beq로 부터 2word 떨어진 주소로 이동한다. 즉, 1word는 하나 이동했다고 생각하고, beq의 offset이 입력되어 있는 것이다.)
offset을 word 단위로 입력하는 이유는, 변위 필드의 유효범위를 증가시키기 위해서이다. 약 4배 증가시킬 수 있다.(1word = 4byte)
이러한 분기 데이터패스는 분기목적지를 계산하고 레지스터 내용을 비교하는 두 가지 일을 해야 한다. 분기를 다루는 데이터패스 부분은 밑에 있는 그림과 같다.
분기 목적지 주소를 계산하기 위해서는 분기 데이터패스는 부호확장 유닛과 덧셈기를 포함한다.
비교를 수행하기 위해서는 레지스터 피연산자 두개가 필요하고 이들을 읽기 위해서는 레지스터 파일이 필요하다(레지스터 파일에 쓸 필요는 없지만)
이외에도 비교연산은 ALU를 사용한다. ALU는 결과가 0인지를 나타내는 출력 신호를 제공하기 때문에, 두 레지스터 피연산자를 제어신호와 함께 ALU에 보내 뺄셈을 하게 된다.
ALU에 0신호가 인가되면, 두 레지스터 값이 같다는 걸 알 수 있다.
jump 명령어는 하위 26비트를 2비트만큼 왼쪽으로 자리이동한 값으로 PC하위 28비트를 대체한다. 이 자리이동은 점프 변위 뒤에 00을 덧붙이면 된다.
MIPS 명령어 집합에서 분기 명령어는 지연분기이다.
지연분기는 분기조건이 참이건 거짓이건 무조건 다음 명령어를 실행하는 분기를 말한다.
예를들어서, 조건이 거짓이면 보통의 분기처럼 실행되지만, 조건이 참이면 바로 다음 명령어를 실행한뒤 해당 주소로 분기하게 된다.
지연분기를 사용하게 된 이유는 파이프라이닝이 분기에 미치는 영향 때문이다.
위 그림은 R형식 명령어와 메모리 명령어(lw, sw)를 위한 데이터 패스이다. 여기에 더해서
위 그림은 full datapath이다.
파란색 글씨로 되어있는 것은 제어신호이다.
제어유닛은 제어신호중 하나만 빼고는 모두 Opcode만 보고 결정 할 수 있다. PCSrc 제어선만은 예외이다. 실행중인 명령어가 branch or equal이며 동시에 ALU의 Zero 출력이 참일 경우에만 PCSrc가 인가되어야 한다. PCSrc신호를 만들려면 제어 유닛에서 나오는 Branch신호와 Zero신호를 And 해야 한다.
분기 명령어는 ALU를 레지스터 피연산자 비교에 사용하므로 분기 목적지 주소 계산을 위해서는 덧셈기가 있어야 한다. 또한 PC에 들어갈 값으로 순처적인 다음 명령어 주소(PC+4)와 분기 목적지 주소 중 하나를 선택하기 위해 또 다른 멀티플렉서가 필요하다.
ALU는 위의 표에 있는 첫 5가지 기능 중 하나를 수행한다.(NOR은 우리가 구현하는 부분집합에서는 보이지 않는 MIPS 명령어 집합의 다른 부분에서 필요하다.) lw,sw는 메모리 주소 계산을 위해서 덧셈용으로 사용하고
,R형식 같은 경우에는 명령어 하위 6비트의 기능 필드값(Func code)에 따라 위의 표에 있는 첫5가지 연산중 하나를 수행하게 된다.
명령어의 기능 필드와 2비트 제어 필드(ALUOp)를 입력으로 갖는 조그만 제어 유닛을 만들어서 4비트 ALU 제어 입력을 발생시킬 수 있다.
ALUOp가 표시해야 될 연산은 lw,sw는 덧셈(00)
beq는 뺄셈(01),산술/논리 연산의 경우에는 (10)이 된다.
위 그림은 제어유닛이 있는 간단한 데이터패스이다.
제어 유닛의 입력은 명령어의 6비트 Opcode필드이다.
제어 유닛의 출력은
RegDst,ALUSrc,MemtoReg
RegWrite,MemRead,MemWrite
Branch
ALUOp
분기 제어신호와 ALU의 Zero 출력을 결합하는 데 AND 게이트를 사용한다. 이 AND 게이트 출력은 다음 PC값을 출력하는데 쓰인다.
PCSrc는 제어 유닛으로부터 직접 나오는 값이 아니고 만들어야 되는 신호이다.
위의 그림은 add $t1,$t2,$t3
같은 R형식 명령어의 데이터 패스 동작을 보여주고 있다.
모든 일이 하나의 clock cycle에서 일어나지만, 명령어 실행을 네 단계로 생각할 수 있다. 이들 단계는 정보 흐름에 따라 순서가 결정된다.
위 그림은 lw 명령어를 위한 데이터패스 동작이다.
lw 명령어는 5단계로 동작한다.
branch에서 같다 라는 결과가 나왔을때 명령어 수행을위한 데이터패스 동작이다.
beq $t1, $t2, offset
- t1,t2가 같을때, offset으로 이동한다.
이 명령어는 R타입과 상당히 비슷하게 동작한다. 다른점은 ALU 출력이 사용되는 용도인데, 여기서 ALU는 PC 값이 PC+4로 바뀔것인지 아니면, 분기 목적지 주소로 바뀔 것인지를 판단한다.
1.명령어를 명령어 메모리에서 가져오고 PC값을 증가시킨다.
2.두 레지스터 $t1과 $t2를 레지스터 파일로부터 읽는다.
3.ALU는 레지스터 파일에서 읽어 들인 값들에 대해 뺄셈을 한다.
명령어의 하위 16비트(offset)을 부호확장한 후 2비트 왼쪽 자리이동한 값에다 PC+4값을 더한다. 결과 값이 분기 목적지 주소이다.
4.어떤 덧셈기의 결과를 PC에 저장할지 ALU의 Zero출력을 이용하여 판단한다.
Jump 명령어는 어떤 면에서는 분기 명령어와 비슷하지만 목적지 PC값 계산방식이 다르고 조건 분기가 아니라는 점이 다르다.
분기 명령어처럼 점프 명령어의 하위 2비트는 항상 00(2)이다.
점프 명령어의 목적지 주소
: 현PC+4의 상위 4비트 + 점프명령어 26비트 주소필드+00 (하위 2비트)
비효율성 때문에 현대적 설계에서는 사용하지 않는다.
왜? 이 같은 단일 사이클은 clock cycle이 모든 명령어에 대해서 같은 길이를 가져야 하기 때문이다.