공부 팁
Issue 하려면
목적지가 비어있어야하고 (WAW)= Register result status
Functional unit status 도 비어 있어야 한다

time 20 사이클 끝에서 Mul이 청소가 된다, sub은 사이클이 시작할때 scoreboard를 보기 때문에 time21에서 issue 할수 있다.
Time = 1 (첫 번째 명령어 Issue)

L.D F6, 34(R2)
의미: R2 레지스터 값에 34를 더한 메모리 주소에서 데이터를 가져와(Load), F6 레지스터에 저장하라.
스코어보드 업데이트 (Bookkeeping 적용):
-
Instruction status (명령어 상태):
- L.D F6, 34(R2)의 Issue 칸에 체크(✓)가 생겼습니다. 무사히 발행되었다는 뜻입니다.
-
Functional unit status (연산기 상태):
- 메모리 주소 계산(R2 + 34)을 위해 정수 연산기(Integer ALU)를 사용합니다.
- Busy: Yes (이제 이 ALU는 내가 쓴다)
- Op: Load (수행할 작업은 Load)
- Fi: F6 (결과를 저장할 목적지 레지스터)
- Fj: R2 (필요한 첫 번째 재료 레지스터)
- Rj: Yes (R2 값을 누군가 계산 중인 상태가 아니므로, 즉시 읽을 수 있음)
Time = 2 (두 번째 명령어 Issue 시도 & 첫 번째 명령어 Read)

-
Instruction status:
- 첫 번째 명령어 L.D F6...: Read operands 칸에 체크(✓)가 생겼습니다. 재료(R2)가 준비되었으므로(Rj=Yes), 값을 무사히 읽어 들였습니다.
- 두 번째 명령어 L.D F2...: Issue 칸에 체크가 없습니다! 왜 그럴까요?
-
구조적 해저드 (Structural Hazard) 발생:
- 슬라이드 왼쪽 위를 보면 "Second load cannot be issued due to structural hazard"라고 적혀 있습니다.
- 두 번째 명령어인 L.D도 메모리 주소를 계산하려면 Integer ALU가 필요합니다.
- 그런데 현재 스코어보드를 보면 Integer ALU의 Busy가 여전히 Yes입니다. (첫 번째 L.D가 아직 다 안 썼음)
- 이전 수식에서 배운 Issue 통과 조건 중 Not busy [FU]를 만족하지 못했기 때문에, 두 번째 명령어는 스코어보드에 등록조차 되지 못하고 파이프라인 입구에서 대기(Stall)하게 됩니다.
-
Functional unit status:
- 첫 번째 명령어가 Read operands 단계를 마쳤기 때문에, Rj 깃발이 Yes에서 No로 바뀌었습니다. (이전에 배운 Bookkeeping 수식 Rj <- No가 적용된 것입니다.)
Time =3 : 계산 완료 (Execution complete)

첫 번째 명령어 (L.D F6): 드디어 메모리 주소 계산(또는 메모리 읽기)을 끝마쳤습니다. Execution complete 칸에 체크(✓)가 생겼습니다.
스코어보드 상태: 아직 결과값을 레지스터에 써넣기 전입니다. 따라서 Integer ALU는 여전히 사용 중(Busy = Yes)입니다.
두 번째 명령어 (L.D F2): 앞사람이 아직 연산기(오븐)를 완전히 비워주지 않았기 때문에, 여전히 파이프라인 입구에서 대기(Stall) 중입니다.
Time = 4: 장부 초기화 (Write result)

첫 번째 명령어 (L.D F6): 드디어 결과값을 F6 레지스터에 안전하게 덮어썼습니다. Write result 칸에 체크(✓)가 생기며 파이프라인을 완전히 빠져나갑니다.
스코어보드 상태 (Bookkeeping 발동!):
아까 그 머리 아프던 수식 표에서 제일 마지막에 있던 Busy[FU] <- No와 Result[Fi[FU]] <- 0 규칙이 바로 여기서 터집니다!
- 중간의 Functional unit status 표를 보세요. Integer ALU 행에 있던 빽빽한 글씨들이 싹 다 지워졌습니다. (연산기 반납 완료)
- 맨 아래 Register result status 표를 보세요. F6 밑에 적혀있던 'Integer'라는 예약 푯말도 말끔히 사라졌습니다. (레지스터 찜하기 해제)
두 번째 명령어 (L.D F2): 슬라이드 텍스트에는 아직 못 들어온다고 적혀있지만, 드디어 1번 화구(Integer ALU)가 청소되었으므로 희망이 보입니다.
위 4가지 instruction 은 동시에 일어난다
Time = 5: 구조적 해저드 해결 (Issue 성공)

상황: 1번 화구(Integer ALU) 청소가 끝났습니다.
두 번째 명령어 (L.D F2, 45(R3)):
- 드디어 기다리던 Issue 통과 조건(Not busy [FU])을 만족했습니다!
- Instruction status: Issue 칸에 당당하게 체크(✓)를 그렸습니다.
- Bookkeeping 발동: 텅 비어있던 Integer ALU 장부에 내 정보(Op=Load, Fi=F2, Fj=R3, Rj=Yes)를 새로 쫙 적어 넣습니다.
- 레지스터 예약: F2 접시는 이제 Integer ALU가 쓴다고 예약 장부(Register result status)에 찜을 해둡니다.
Time = 6: 새로운 명령어 등장과 RAW 해저드 감지! ⭐ (초집중)

- 두 번째 명령어 (L.D F2):
- 재료(R3)가 준비되어 있었으므로 무사히 재료를 읽어갔습니다 (Read operands 체크 ✓).
- 재료를 가져갔으니 장부에서 Rj를 Yes에서 No로 바꿉니다.
- 세 번째 명령어 (MUL.D F0, F2, F4):
- Issue 통과: 다행히 곱셈기(FP Mult1)가 비어있고, 목적지(F0)도 아무도 안 쓰고 있어서 Issue 단계를 무사히 통과했습니다.
Bookkeeping (장부 기록) 👉 여기서 대박 사건이 터집니다!
- Op=Mult, Fi=F0, Fj=F2, Fk=F4 까지는 평범하게 적습니다.
- Qj = Integer: 이 곱셈의 첫 번째 재료인 F2를 지금 누가 만들고 있나 장부를 봤더니, 방금 앞서 들어온 두 번째 Load 명령어(Integer ALU)가 찜해놓은 상태입니다! 그래서 Qj 칸에 "내 재료는 저기 저 Integer 요리사가 만들고 있어"라고 적어둡니다.
- Rj = No: 앞사람이 아직 요리를 안 끝냈으므로, 내 첫 번째 재료는 준비되지 않았습니다(No).
- Rk = Yes: 반면 두 번째 재료인 F4는 아무도 안 건드리고 있으니 바로 쓸 수 있습니다(Yes).
Time = 7: 줄줄이 밀리는 대기줄 (RAW 해저드 파티)

두 번째 명령어 (L.D F2):
- 메모리에서 값을 다 찾았습니다! (Execution complete ✓)
- 하지만 아직 레지스터에 쓰지는 않았습니다. 장부상 Integer ALU는 여전히 Busy=Yes 상태입니다.
네 번째 명령어 (SUB.D F8, F6, F2) 진입 시도:
- Issue 통과: 뺄셈기(FP Add 연산기)가 비어있고, 목적지 F8도 아무도 안 쓰고 있으니 무사히 Issue 칸에 체크(✓)를 하고 장부에 등록합니다.
장부 기록 (RAW 해저드 감지!):
- 첫 번째 재료 F6: 아주 옛날에 1번 명령어가 완성해 뒀으니 바로 쓸 수 있습니다. (Rj = Yes)
- 두 번째 재료 F2: 어? 이거 지금 Integer ALU가 쥐고 있네요. (Qk = Integer)
- 따라서 두 번째 재료는 아직 준비 안 됨! (Rk = No)
- 결과: 3번 명령어(MUL.D)와 4번 명령어(SUB.D) 둘 다 F2 재료가 안 나와서 나란히 손가락만 빨며 무한 대기(Stall)에 들어갑니다.
Time = 8: 구세주의 등장과 깃발(Ready) 업데이트 ⭐ (초집중)

두 번째 명령어 (L.D F2): 결과 쓰기 완료!
- 드디어 F2 레지스터에 결과값을 덮어썼습니다! (Write result ✓)
- Bookkeeping 발동 1: Integer ALU의 모든 정보가 싹 지워졌습니다. (Busy = 빈칸)
- Bookkeeping 발동 2 (가장 중요!!): 장부 규칙 중 ∀f (if Qj[f]=FU then Rj[f]<-Yes) 기억나시나요?
Integer ALU가 일을 끝내면서 동네방네 소문을 냅니다. "나 끝났어! 나 기다리던 애들 다 재료 가져가!"
- MUL.D의 장부를 보니 Qj가 Integer였죠? -> 드디어 Rj가 No에서 Yes로 바뀝니다!
- SUB.D의 장부를 보니 Qk가 Integer였죠? -> 드디어 Rk가 No에서 Yes로 바뀝니다!
다섯 번째 명령어 (DIV.D F10, F0, F6) 진입:
- Issue 통과: 나눗셈기(FP Div)가 비어있어서 무사히 Issue에 들어왔습니다.
- 장부 기록:
- 첫 번째 재료 F0: 이걸 누가 만들지 찾아보니, 방금 전 3번 명령어(Mult1)가 찜해놨습니다. (Qj = Mult1) 당연히 아직 시작도 안 했으니 Rj = No (또 RAW 해저드 발생!)
- 두 번째 재료 F6: 이미 완성되어 있으니 Rk = Yes
Time = 9: 재료 획득과 새로운 병목(Structural Hazard)의 등장

막혀있던 3번(MUL.D)과 4번(SUB.D)의 대반격:
- Time 8에서 Rj, Rk 깃발이 모두 Yes로 바뀌었었죠? 드디어 두 명령어 모두 Read operands 칸에 체크(✓)를 긋고 재료를 연산기 안으로 빨아들였습니다.
- Bookkeeping 발동: 재료를 성공적으로 읽었으니, 장부에서 Rj, Rk를 다시 No로 리셋합니다. 그리고 앞선 연산기와의 연결 고리였던 Qj, Qk 칸도 깨끗하게 지워버립니다. (이제 누구의 눈치도 보지 않고 요리할 수 있는 독립 상태가 된 것입니다.)
6번 명령어(ADD.D F6, F8, F2) 진입 시도 실패:
- 제일 밑에 새로운 덧셈 명령어가 파이프라인에 들어왔지만, Issue 칸에 체크를 하지 못했습니다.
- 이유 (Structural Hazard): 덧셈을 하려면 FP Add 연산기가 필요한데, 윗줄의 장부를 보면 방금 전 들어온 4번 SUB.D가 FP Add를 꽉 쥐고 있습니다(Busy = Yes). 자리가 없어서 문전박대당한 것입니다.
Time = 10: 고난의 행군 (실행 시간의 차이)

여기서 파란숫자 10은 Cycle 10에 실행(execution)을 시작했다는 뜻
이제 본격적으로 연산기들이 요리를 시작(Execution)하는 단계입니다. 여기서부터는 각 연산기마다 '요리 시간(Latency)'이 다르다는 점이 엄청난 나비효과를 불러옵니다.
상황: 슬라이드 왼쪽 위 텍스트를 보면, 곱셈(Mult)은 10클럭이 걸리고 뺄셈(Sub)은 2클럭이 걸린다고 나와 있습니다. (파란색 숫자 '10'은 현재 사이클이 Time 10임을 표시하거나 타이머가 작동 중임을 나타냅니다.)
4번 명령어(SUB.D):
- 2클럭짜리 간단한 요리이므로, 다음 사이클(Time 11)이면 바로 요리를 끝내고(Execution complete) 결과를 뱉어낼 준비를 할 것입니다. 아주 빠르죠.
5번 명령어(DIV.D)의 비극 (RAW 해저드의 연장):
- 얘는 첫 번째 재료인 F0를 3번 명령어(MUL.D)가 만들어주기만을 기다리고 있습니다. (Qj = Mult1)
- 그런데 그 곱셈기가 무려 10클럭짜리 요리를 이제 막 시작했습니다! 즉, 나눗셈 명령어는 앞으로 10사이클 내내 저 Issue 칸에 머물면서 아무것도 못 하고 하염없이 대기(Stall)해야 합니다.
Time = 11: "나 먼저 끝났어!" (실행 완료)


4번 명령어 (SUB.D): 초고속 요리 완료
- 3번 MUL.D보다 늦게 파이프라인에 들어왔지만, 뺄셈은 2클럭밖에 안 걸리기 때문에 벌써 요리를 끝냈습니다. (Execution complete ✓)
- 반면 3번 MUL.D는 10클럭 중 겨우 2클럭째 진행 중입니다.
6번 명령어 (ADD.D)의 대기:
- FP Add 연산기를 4번 SUB.D가 아직 쥐고 있기 때문에(결과를 아직 안 썼음), 6번 명령어는 여전히 Issue를 통과하지 못하고 입구 컷 당하고 있습니다.
Time = 12: 장부 청소와 방 빼기 (Write Result) ⭐

무사히 F8 레지스터에 결과값을 덮어쓰고 파이프라인을 완전히 졸업합니다. (Write result ✓)
- WAR 해저드 검사 통과: 여기서 아까 배웠던 복잡한 ∀f 수식(WAR 해저드 검사)이 몰래 작동했습니다. 다른 명령어들(Mult, Div)의 장부를 쓱 봤는데, 아무도 내 목적지인 F8의 옛날 값을 읽으려고 대기(R=Yes)하고 있지 않았습니다. 그래서 안심하고 바로 덮어쓸 수 있었던 겁니다!
- Bookkeeping 발동 (방 빼기):중간 FP Add 연산기 장부가 싹 지워졌습니다. (Busy 빈칸 됨)맨 아래 F8 접시에 세워뒀던 'Add' 예약 푯말도 치웠습니다.




Time = 17: WAR 해저드 발동! 🚨 (가장 중요)

- 6번 명령어 (ADD.D): "나 결과 다 계산했어! 내 목적지인 F6 레지스터에 값 덮어쓸게!
- "스코어보드의 장부 검사 (∀f 수식 작동): "잠깐 멈춰! 다른 연산기들 장부 좀 뒤져보자.
- "5번 명령어 (DIV.D)의 상황: * 나눗셈기의 장부를 보니, 이 녀석이 필요한 두 번째 재료(Fk)가 바로 F6입니다.
- 그런데 나눗셈기는 아직 첫 번째 재료(F0)를 못 받아서 Read operands 칸에 체크도 못 하고 하염없이 대기 중입니다.
- 즉, 나눗셈기는 아직 '원래 있던 옛날 F6 값'을 읽지 않은 상태입니다.
- 결론 (대참사 방지): 만약 여기서 6번 명령어가 눈치 없이 F6에 새 값을 덮어써 버리면, 나중에 나눗셈기는 엉뚱한 새 값을 읽어가서 계산을 완전히 망치게 됩니다. 이것이 바로 뒷사람이 읽기도 전에 앞사람이 덮어쓰는 WAR 해저드입니다!
- 그래서 6번 명령어는 모든 계산을 끝내놓고도 Write result 칸에 체크를 못 하고 발만 동동 구르며 대기(Stall)하게 됩니다.



Time = 22: 체증 완벽 해소와 퇴근!

6번 명령어 (ADD.D): 퇴근!
- 드디어 나눗셈기(FP Div)가 옛날 F6 값을 안전하게 자기 뱃속(연산기)으로 가져갔습니다.
- 스코어보드가 장부를 다시 검사해보니, 이제 아무도 F6를 읽으려고 쳐다보지 않습니다. (WAR 해저드 완전 해제)
- 6번 명령어는 신나게 F6에 새 값을 덮어쓰고(Write result ✓), 장부에서 자기 이름을 싹 지우며 파이프라인을 빠져나갑니다.
5번 명령어 (DIV.D): 지옥의 40클럭 시작
- 파란색 숫자 22가 떴습니다! "나눗셈 요리 시작 시각 = Time 22"라는 뜻이죠.
- 나눗셈은 요리 시간이 자그마치 40클럭입니다.

