반응형
반응형
반응형

이 장에서는 라우터의 datapath를 구성하는 component들, 즉 input buffer, switch, output unit의 설계를 살펴본다. Input buffer는 flit들이 virtual channel, switch bandwidth, channel bandwidth를 기다리는 동안 저장된다. Input buffer는 중앙 집중식으로 구성하거나, physical channel 단위로 나누거나, virtual channel 단위로 나눌 수 있다. 중앙 buffer는 physical/virtual channel 간에 저장 공간을 유연하게 할당할 수 있지만, 대역폭 부족 때문에 실용적이지 않은 경우가 많다. 각 buffer partition 안에서 저장 공간은 circular buffer를 이용한 정적 할당, 또는 linked list를 이용한 동적 할당으로 관리할 수 있다.

Switch는 라우터의 핵심으로 flit이 input port에서 output port로 전환(switching)되는 곳이다. 중앙 buffer 자체도 input multiplexer와 output demultiplexer를 통해 switch 기능을 수행할 수 있다. 공유 bus 또한 switch 역할을 할 수 있는데, 이 경우 복잡한 switch 할당이 필요 없다는 장점이 있다. 입력이 버스를 획득하면 모든 출력으로 broadcast하기 때문이다. 그러나 내부 대역폭 활용이 비효율적이다. 대부분의 고성능 라우터는 crosspoint switch를 사용하며, switch 할당 문제를 단순화하고 고가의 channel bandwidth가 idle 상태가 되지 않도록 speedup을 적용하기도 한다.


17.1 Input Buffer Organization

Input buffer는 현대 라우터에서 가장 중요한 구조 중 하나다. Flow control protocol은 flit들이 라우터를 빠져나갈 때까지 대기할 공간을 이 buffer에 할당한다. 이 buffer들은 도착한 flit을 저장하여, pipeline stall이나 virtual/physical channel 경합으로 인해 패킷이 일시적으로 지연될 때 incoming channel의 속도를 늦추지 않아도 된다.


17.1.1 Buffer Partitioning

Input buffer의 partition 방식은 switch 설계와 밀접하게 연관된다. Input buffer는 전체 라우터에 걸쳐 하나로 묶거나, physical input channel 단위 또는 virtual channel 단위로 분할할 수 있다 (그림 17.1 참조).

  • 중앙 메모리를 사용하는 경우(그림 17.1(a)), 모든 input buffer를 하나의 메모리에 저장할 수 있어 switch가 필요 없다. 그러나 실제로는 입력을 메모리로 multiplex하고 출력을 demultiplex하는 두 개의 switch가 필요한 셈이다. 이 구조의 장점은 메모리를 input port 간에 유연하게 할당할 수 있다는 점이다. 하지만 두 가지 단점이 있다:
    1. 중앙 메모리의 대역폭이 병목이 될 수 있다. 예를 들어 input port가 8개라면, 메모리는 한 클럭에 8개를 쓰고 8개를 읽어야 하므로 16배의 대역폭이 필요하다.
    2. flit을 write하기 위해 wide word로 만들기 위한 serialization/deserialization 작업 때문에 latency가 증가한다.
  • 이러한 문제를 피하기 위해 input port마다 개별 메모리를 제공하는 방식(그림 17.1(b))이 있다. 총 메모리 대역폭은 동일하지만, 각 메모리는 input port의 2배만 되면 되므로 구현이 수월하고 latency도 낮다. 단, virtual channel 간 메모리 공유는 불가능하다.
  • virtual channel에 대해 개별 메모리를 제공하는 방식(그림 17.1(c))도 있다. 이 경우 하나의 physical channel에서 여러 virtual channel을 동시에 switch에서 접근할 수 있으므로 input speedup을 제공할 수 있다. 예를 들어 input port가 8개이고 각 port에 4개의 virtual channel이 있다면, 32개의 입력을 갖는 32×8 switch를 구성할 수 있다. 그러나 이런 방식은 idle 상태인 virtual channel의 메모리를 busy한 채널이 사용할 수 없어 buffer fragmentation 문제가 생긴다. 또한 작은 메모리들을 많이 사용해야 하므로 오버헤드가 크다.
  • 절충안으로는 각 physical channel마다 소수의 output port를 가진 buffer를 제공하는 방식(그림 17.2(a))이 있다. Per-virtual-channel buffer를 두지 않고도 switch speedup을 얻을 수 있다. 이보다 저렴한 방식은 physical channel buffer를 다중 port 대신 partitioned buffer로 구성하는 것이다(그림 17.2(b)). 예를 들어 virtual channel이 4개이고 buffer를 2개로 나눈다면, 짝수 채널은 하나의 buffer에, 홀수 채널은 다른 buffer에 저장한다. 이 방식은 일부 유연성을 희생하지만 성능은 거의 비슷하고 면적 비용은 훨씬 낮다.


17.1.2 Input Buffer Data Structures

어떤 buffer 조직이든 flit과 packet이 메모리의 어디에 있는지 추적하고 free memory를 관리하기 위한 data structure가 필요하다. 여러 virtual channel이 하나의 메모리를 공유하는 경우라면, 공정하게 공간을 분배하는 메커니즘도 필요하다.

일반적으로 circular bufferlinked list 두 가지 구조가 사용된다.

  • Circular buffer는 관리가 간단하지만 buffer 공간이 고정적으로 partition되어야 한다.
  • Linked list는 오버헤드는 크지만 다양한 buffer 간에 공간을 유연하게 공유할 수 있다.

여기서 buffer 또는 flit buffer는 특정 virtual channel 전체를 저장하는 구조를 뜻하고, cell 또는 flit cell은 개별 flit을 저장하는 단위를 뜻한다.

 

Circular buffer의 예는 그림 17.3에 있다. 고정된 FIRSTLAST 포인터는 메모리 내에서 buffer의 경계를 나타내며, 이 포인터는 register를 통해 설정할 수 있지만, buffer 사용 중에는 변경할 수 없다. buffer의 내용은 Head 포인터 아래, Tail 포인터 위에 위치하며, 끝을 기준으로 wrap-around 될 수 있다.

새로운 요소를 추가하려면 tail 포인터가 가리키는 cell에 저장한 후, tail 포인터를 원형으로 증가시키면 된다. 이 연산은 C 코드로 다음과 같이 표현된다:

 mem[Tail] = new_flit ;
 Tail = Tail + 1 ;
 if(Tail > LAST) Tail = FIRST ;
 if(Tail == Head) Full=1;

 

 

그림 17.3
(a) flit a부터 f까지 총 여섯 개의 flit이 들어 있는 buffer
(b) flit a부터 d를 제거하고, flit g부터 j를 추가한 상태로 tail 포인터가 buffer 끝을 넘어 wrap-around된 모습
Circular buffer는 고정된 FIRSTLAST 포인터로 메모리 내 영역이 정의되고, HeadTail 포인터로 현재 buffer의 내용을 나타낸다. 데이터는 tail 포인터 위치에 삽입되며, tail은 순환적으로 증가한다. 데이터는 head 포인터에서 제거되며, head 또한 순환적으로 증가한다.

 

위의 세 번째 줄은 tail 포인터가 buffer의 끝에 도달했을 때 처음 위치로 되돌리는 순환 처리를 한다.

마찬가지로 데이터를 제거할 때는 다음과 같다:

flit = mem[Head] ;
 Head = Head + 1 ;
 if(Head > LAST) Head = FIRST;
 if(Head == Tail) Empty=1;

 

두 코드 블록의 마지막 줄은 각각 buffer가 가득 찼는지 또는 비었는지를 감지한다. Head와 Tail 포인터가 같을 때 발생하며, 삽입에 의해 같아지면 Full 상태, 제거에 의해 같아지면 Empty 상태이다. 이 상태들은 외부 논리가 buffer가 Full일 때 삽입 요청을 막고, Empty일 때 제거 요청을 막기 위해 사용된다.

일반적인 구현에서는 위의 네 줄을 하나의 클럭 사이클 내에서 실행하는 logic으로 circular buffer를 구성한다. 많은 구현에서는 하나의 클럭에서 동시에 삽입과 제거가 가능하도록 설계되기도 한다.

buffer 크기가 2의 거듭제곱이고 해당 크기의 배수로 정렬되어 있으면(예: 16-flit buffer가 16의 배수 주소에 시작됨) 포인터의 wrap-around를 비교 연산 없이 구현할 수 있다. 이때 포인터의 하위 비트는 buffer 내부의 cell을, 상위 비트는 buffer 자체를 식별하는 데 사용된다. 예를 들어 flit buffer가 16 cell일 경우 포인터의 0~3비트는 cell을, 4비트 이상은 buffer를 나타낸다. 이때 3비트에서 4비트로의 carry를 막으면 포인터가 buffer의 끝에서 시작 위치로 wrap된다.


Linked list data structure그림 17.4에 나타나 있으며, buffer에 대한 free storage 할당의 유연성이 높지만 오버헤드와 복잡성이 증가한다. Linked list memory를 관리하려면 각 cell에 다음 cell을 가리키는 포인터가 있어야 하며, 이를 위해 포인터는 종종 flit cell과는 다른 다중 포트 메모리에 저장된다. 각 buffer는 head와 tail 포인터로 구성되며, free 상태인 cell들은 free list로 연결된다.

초기에는 모든 cell이 free list에 있고, 모든 buffer의 head/tail 포인터는 NULL이다. buffer마다 현재 저장된 cell 수를 나타내는 count register와 free list에 있는 cell 수를 나타내는 count register도 유지된다.

다음은 flit을 삽입하는 연산이다:

 if(Free != NULL) {
 mem[Free] = new_flit ;// store flit into head of free list
 if(Tail != NULL)
 ptr[Tail] = Free ; // link onto buffer list- if
 Tail = Free ; // it exists
 Free = ptr[Free] ;	// unlink free cell
 ptr[Tail] = NULL ;	// optional- clear link to free list
 if(Head == NULL)	 // if buffer was empty
 Head = Tail ;		// head and tail both point at this cell
 } else ERROR ;		 // no cells left on free list
 
 

이러한 삽입은 단일 cycle 내에서도 가능하나, dual-ported buffer가 필요하다. 이전 tail cell의 포인터를 쓰고, free list의 head를 읽는 작업이 동시에 필요하기 때문이다. 새로운 tail cell의 포인터를 NULL로 초기화하는 것은 consistency check를 위한 좋은 방법이지만 필수는 아니다.


그림 17.4

  • (a) linked list로 연결된 4개의 flit cell로 구성된 buffer. Head는 첫 번째 cell을, Tail은 마지막 cell을 가리킨다. Free는 5개의 free cell로 구성된 list를 가리킨다.
  • (b) flit e를 추가하면서 free list에서 cell을 제거하고 buffer list에 연결한 상태
  • (c) flit a를 제거하고 해당 cell을 free list에 다시 반환한 상태

flit 제거는 다음과 같은 절차를 따른다:

if(Head != NULL) {
 flit = mem[Head] ; // get the flit
 Next = ptr[Head] ; // save pointer to next flit in buffer
 ptr[Head] = Free ; // put old head cell on the free list
 Free = Head ;		 //
 if(Head == Tail) { // if this was the last cell- empty list
 Head = NULL ;
 Tail = NULL ;
 } else { 		// otherwise, follow the link to the
 Head = Next ;	// next cell
 }
 } else ERROR ; // attempt to remove from empty buffer

 

flit 제거는 단일 포트 pointer memory만으로도 한 cycle 내에서 가능하며, head cell의 link를 읽고 free list에 연결하는 read-modify-write 연산만 있으면 된다.


linked list의 단점은 포인터 memory 조작의 복잡성이다. 삽입/제거 시 포인터 메모리에 대한 다수의 연산이 필요하며, 에러 처리도 복잡해진다. 단순 저장 공간 측면에서의 오버헤드는 작다. 예를 들어, 8바이트 flit에 8비트 포인터를 붙이는 경우 12.5%의 오버헤드만 추가된다.

그러나 linked list 구조에서 발생한 비트 오류는 circular buffer보다 훨씬 심각한 영향을 끼칠 수 있다. circular buffer에서는 단순히 flit 데이터가 손상되거나 head/tail 포인터 오류로 일부 flit만 누락될 수 있지만, 상태 초기화(Head = Tail = FIRST)를 통해 오류를 국한시킬 수 있다.

반면, linked list에서는 pointer field에 비트 오류가 생기면 free list 전체가 끊기거나, 두 buffer가 동일한 cell을 공유하게 되는 등 심각한 문제가 발생한다. 이는 단일 오류가 전체 buffer 시스템에 걸쳐 영향을 미친다는 것을 의미하며, 조기 탐지와 격리가 중요하다.

이를 위한 에러 제어 방식으로는 방어적 코딩(defensive coding)과 백그라운드 모니터링이 있다. 방어적 코딩은 포인터에 패리티 비트를 추가하여 1비트 오류를 조기 탐지하고, flit cell에 free/allocated 상태를 나타내는 type field를 추가하여 일관성 체크에 활용한다. 또한 buffer 번호 또는 그 해시값을 함께 저장하여 오류 감지를 용이하게 할 수 있다.

 

할당된 cell에 buffer 번호나 그 해시 값을 저장하면, cell이 다른 buffer로 잘못 옮겨졌는지 확인할 수 있다. 마지막으로, 각 cell에 시퀀스 번호나 하위 몇 비트만이라도 저장하면, 입력 유닛이 flit 순서가 바뀌지 않았는지 확인할 수 있다. 삽입 및 제거 연산은 포인터의 유효성, 읽은 cell의 type 및 buffer 번호가 예상과 일치하는지, 제거되는 cell의 시퀀스 번호가 순서대로인지 검증한다. 예외가 감지되면 해당 buffer를 비활성화하고, 일반적으로 소프트웨어로 구현된 오류 처리 루틴이 호출된다.

 

백그라운드 모니터링 프로세스는 방어적 코딩을 보완하며, 접근되지 않은 cell의 일관성을 확인한다. 이는 linked list 중간에서 발생한 오류를 조기에 감지할 수 있게 한다. 이 모니터링 프로세스는 각 buffer의 head부터 tail까지 리스트를 순회하며, buffer의 cell 수가 count와 일치하는지, 모든 cell이 할당 상태인지, 각 cell이 올바른 buffer에 속해 있는지, parity 오류가 없는지 등을 확인한다. free list도 유사하게 확인한다. 이 리스트 순회는 마치 mark-and-sweep 방식의 garbage collection처럼, 어떠한 리스트에도 연결되지 않은 cell을 탐지할 수 있다. 대부분의 구현에서 이 모니터는 buffer memory의 idle cycle을 활용하는 하드웨어 프로세스로 구성되며, 오류가 감지되면 buffer는 비활성화되고 소프트웨어 오류 처리 루틴이 실행된다.


17.1.3 Input Buffer Allocation

Input buffer를 linked list 구조로 구현하면, 하나의 메모리를 공유하는 여러 buffer 간에 저장 공간을 동적으로 할당할 수 있다. 이 동적 메모리 할당은 busy한 virtual channel에 더 많은 메모리를, idle한 채널에는 적은 메모리를 배정할 수 있어 메모리 활용 효율을 높인다. 연구에 따르면 많은 수의 virtual channel이 있을 경우 부하가 고르게 분산되지 않고 일부는 idle 상태이고 일부는 과부하 상태가 되기 쉽다. 따라서 busy한 채널에 더 많은 메모리를 할당하는 것이 유리하다.

하지만 이를 신중하게 하지 않으면 virtual channel의 이점을 오히려 해칠 수 있다. 예를 들어 한 greedy한 virtual channel이 모든 메모리를 점유한 뒤 block 상태가 된다면, 다른 채널은 진전을 전혀 하지 못하게 된다. 이로 인해 virtual channel 간에 의존성이 생기고 deadlock이 발생할 수 있다.

이를 방지하기 위해 각 virtual channel buffer에는 해당 채널의 flit 개수를 추적하는 count register를 추가한다. free list에 남은 cell 개수를 추적하는 register도 하나 추가한다. 이 두 count 값을 활용해 다양한 buffer 할당 정책을 구현할 수 있다. 정책의 입력은 현재 count 상태이며, 출력은 각 virtual channel이 buffer를 하나 더 할당받을 수 있는지 여부이다.

예를 들어 가장 간단한 정책은 각 virtual channel buffer에 하나의 flit 저장 공간을 예약하는 것이다. 이는 특정 channel이 전체 메모리를 독점한 후 block됨으로써 다른 channel의 진전을 막는 상황을 방지한다. 최소한 각 채널이 하나의 flit은 처리할 수 있게 보장하는 방식이다.

이 정책을 구현하기 위해 다음 두 조건 중 하나를 만족하면 virtual channel이 buffer에 flit을 삽입할 수 있다:
(a) 현재 buffer가 비어 있는 경우 (모든 채널이 최소한 하나의 flit을 보장받음)
(b) free buffer의 수가 count가 0인 virtual channel buffer의 수보다 많을 경우

이 정책을 쉽게 관리하기 위해 free cell을 reserved cellfloating cell로 나누어 추적한다. Reserved cell은 각 virtual channel 단위로 관리되며, buffer가 비어 있거나 첫 flit이 삽입될 때 증가하거나 감소한다. 한편, flit이 1개 이상 존재하는 buffer에서의 삽입/제거는 floating cell count를 조정한다. 조건 (b)는 floating cell count가 0인지 여부를 확인하는 것으로 처리할 수 있다.

이 단순한 정책은 deadlock을 방지하지만 buffer 할당의 불균형을 초래할 수 있다. 이 문제를 해결하는 방법 중 하나는 sliding limit allocator를 사용하는 것이다. 이 방식은 두 개의 파라미터 r과 f로 정의된다.

  • r: 각 buffer에 예약된 cell 수 (deadlock 방지를 위해 최소 1 이상)
  • f: 예약된 cell을 제외하고 남은 cell 중 어느 하나의 buffer에 할당할 수 있는 최대 비율

이 sliding limit allocator를 구현하기 위해, 두 개의 free cell counter를 유지한다:

  • reserved cell용 Nr
  • floating cell용 Nf

buffer b에 flit을 삽입하려면, 다음 조건 중 하나를 만족해야 한다:

  • Nb < r: reserved pool에서 할당하며 Nr 감소
  • r ≤ Nb < f×Nf + r: floating pool에서 할당하며 Nf 감소

이 정책의 aggressiveness는 f 값으로 조절된다.

  • f = 1일 경우, 하나의 buffer가 모든 free pool을 사용할 수 있으며, 이는 고정 예약 정책과 동일하다.
  • f = 1/B일 경우 (B는 buffer 개수), 각 buffer는 전체 pool의 1/B만 사용 가능하며, 고정 partition 정책과 같다.
  • 일반적으로는 이 두 극단 사이의 값이 유용하다.
    예:
    • f = 0.5 → 어떤 buffer도 전체 floating pool의 절반 이상 사용 불가
    • f = 2/B → 어떤 buffer도 고정 partition보다 두 배 이상 공간을 사용하지 못함

17.2 Switches

Switch는 라우터의 핵심이다. 패킷과 flit이 원하는 output port로 실제로 전달되는 곳이 바로 switch이다. 설계에서 가장 중요한 요소는 speedup이다. 이는 switch가 제공하는 bandwidth와 full throughput을 지원하는 데 필요한 최소 bandwidth의 비율이다. Speedup이 있으면 switch 할당을 단순화하고 throughput을 높이며 latency를 줄일 수 있다. 이 speedup은 switch의 입력측과 출력측에 각각 독립적으로 설정할 수 있다.

같은 speedup을 갖는 switch도 여러 방식으로 구현 가능하다. flit 하나를 처리하는 시간이 여러 clock cycle에 걸쳐 있을 경우, 공간적 switching 외에 time-domain switching(bus처럼)을 사용할 수 있다. 또는 여러 작은 switch를 직렬로 구성하여 하나의 소형 네트워크로 구성할 수도 있다. 다만, 이와 같은 multistage switch는 복잡한 할당 및 flow control 문제를 야기하므로 간단한 경우에만 적합하다.


17.2.1 Bus Switches

Bus를 switch로 사용하는 경우는, flit 하나의 시간(flit time)이 내부 clock cycle(phit time)보다 길고 port 수보다 많을 때이다. 그림 17.5는 이를 나타낸다. 각 input deserializer는 phit들을 모아 일정 수(P)에 도달하면 버스를 arbitration하고, 버스를 획득하면 P개의 phit을 병렬로 출력 serializer에 전송한다. 출력 serializer는 이 phit들을 순차적으로 전송한다.

이 구조가 bandwidth 낭비 없이 동작하려면 flit의 길이가 P의 배수여야 한다. 예시는 input/output port가 각각 4개이며, flit은 4개의 phit로 구성된다. 모든 flit은 같은 시점에 첫 번째 phit을 가지며 정렬된다.

버스 arbitration은 매우 간단한 고정 스케줄 방식으로,

  • input port 0 → phit cycle 0
  • input port 1 → phit cycle 1
  • input port 2 → phit cycle 2
  • input port 3 → phit cycle 3
    으로 순차적으로 버스를 할당받는다.

bus switch에서는 speedup이 1이면 충분하다. 각 input은 자신의 cycle에 원하는 출력을 항상 사용할 수 있기 때문이다. 더 높은 speedup은 비용만 증가시키고 성능 향상은 없다.


그림 17.6은 4×4 bus switch의 타이밍 다이어그램을 보여준다.

  • 첫 번째 flit time 동안 flit a, f, k, p가 input port에 도착
  • 두 번째 flit time에는 b, g, l, q
  • 세 번째 flit time에는 c, h, m, r
  • i번째 flit이 도착하는 동안, i−1번째 flit이 bus로 전송되고, i−2번째 flit이 output port에서 재직렬화된다.

버스 구조는 매우 단순하지만, 그 단순성은 port bandwidth 낭비와 latency 증가를 대가로 한다.

  • bus bandwidth = P × b
  • 그러나 각 input/output serializer는 P × b의 대역폭이 필요하므로, 총 I/O 대역폭은 P² × b이다.
  • 단, 실제 사용되는 대역폭은 P분의 1 수준이므로 비효율적이다.

칩 내부 구현에서는 이 초과 대역폭이 치명적이지 않다. 그림 17.7에서처럼 버스 라인을 deserializer 및 serializer 위로 직접 배치하면 배선 비용은 크지 않다. 실제로 이 구조는 동일 bandwidth의 crossbar switch에 비해 배선 복잡도가 2배 수준이다(2P×P vs P×P). 또한 bus switch의 serializer/deserializer는 2P phit의 저장 공간이 필요하며, crossbar는 상태가 없는 구조(stateless)이다.

 

그림 17.7은 4×4 bus switch의 floorplan 및 배선 구조를 보여준다. 입력/출력 라인은 phit 단위로 수평 방향으로 흐르며, 각 입력 라인은 input deserializer(음영처리된 박스)로 연결되고, 각 출력 라인은 output serializer(해칭 처리된 박스)가 구동한다. 4-phit-wide bus는 수직 방향으로 serializer 및 deserializer 위를 가로지른다.

bus switch의 latency와 coarse granularity는 초과 대역폭보다 더 심각한 제약이 된다. 그림 17.6에서처럼, bus switch는 최소 P phit 단위로 동작해야 한다. flit 크기가 이보다 작다면 bus switch는 적합하지 않다. 또한 bus switch의 latency는 2P phit 시간이다. 이는 input을 deserialize하고 output을 정렬하는 데 필요한 시간 때문이다. 반면, crossbar는 단 1 phit 시간만의 지연만 갖는다.

bus switch와 crossbar 사이의 중간 방식으로 multiple-bus switch가 있다. 그림 17.8은 출력 분할 방식의 switch 예시로, 두 개의 버스를 사용한다. Output 0과 1은 Bus 1을, Output 2와 3은 Bus 2를 공유한다. 각 bus가 제공하는 output 수를 절반으로 줄이면, 출력을 유지하기 위해 매 cycle 운반해야 하는 phit 수도 절반이 되므로 serialization latency가 절반으로 줄어든다. 하지만 이는 allocation을 더 복잡하게 만든다. 더 이상 고정된 할당 방식은 사용할 수 없고, cycle마다 input과 output port를 매칭하는 문제를 해결해야 한다.

그림 17.8의 multiple-bus 구조는 2-phit wide 4×2 crosspoint switch와 동일한 구성이다. 각 4×2 switch 출력은 두 개의 output serializer를 구동하며, 이 serializer는 bus로부터 2 phit 폭의 데이터를 받아 한 번에 1 phit씩 출력한다. 극단적으로는, 각 출력을 독립된 bus에 연결하면 이 구조는 P×P crosspoint switch와 동일하게 된다.


17.2.2 Crossbar Switches

6.2절에서 설명한 것처럼, n×m crossbar (crosspoint) switch는 n개의 입력을 m개의 출력에 각각 연결할 수 있다. 그림 17.9는 crossbar를 나타내는 기호이며, 구조에 대한 상세한 설명은 6.2절에서 다루었으므로 여기서는 생략한다.

라우터 datapath의 switch로 crossbar를 사용할 때 주요 고려 사항은 speedup이다. 이는 제공되는 bandwidth와 필요한 bandwidth의 비율을 의미한다. crossbar의 입력, 출력, 또는 양쪽 모두에 대해 speedup을 제공할 수 있다. 이 speedup은 공간적 방법(추가 입력선) 또는

flit = mem[Head] ;
 Head = Head + 1 ;
 if(Head > LAST) Head = FIRST;
 if(Head == Tail) Empty=1;

시간적 방법(더 높은 대역폭 입력)으로 구현할 수 있다.

  • 그림 17.10(b): 입력 측에 speedup이 있는 예
  • 그림 17.11(a): 출력 측에 speedup이 있는 예
  • 그림 17.11(b): 양쪽에 speedup이 있는 예

crossbar에 speedup을 적용하면 switch allocation을 간소화하거나 단순한 allocator를 사용하더라도 더 좋은 성능을 낼 수 있다. 특히 flit 크기가 작고 latency 요구가 낮을수록, 복잡한 allocator 대신 speedup을 통해 switch를 구성하는 것이 더 저렴하다.

switch allocation은 crossbar의 입력과 출력을 충돌 없이 flit 간에 연결하는 작업이며, 이 주제는 19장에서 자세히 다룬다. 여기서는 random separable allocator를 사용해 다양한 speedup 수준에서 switch 성능을 비교한다.

random separable allocator는 다음과 같이 작동한다:

  1. 각 input buffer는 기다리는 flit 중 하나를 무작위로 선택해 crossbar의 각 입력에 할당한다.
  2. uniform traffic이라고 가정할 때, 각 출력은 선택된 입력 flit이 해당 출력으로 향할 확률이 동일하다.
  3. 각 출력은 자신을 요청하는 입력들 중에서 하나의 flit을 무작위로 선택해 수신한다.

예를 들어 입력과 출력이 k개씩 있는 라우터에서 입력 측 speedup이 s이고 출력 측 speedup은 없다면, crossbar는 총 sk개의 입력을 가진다. 이 경우, 할당의 첫 단계에서 선택된 sk개의 flit 중 하나라도 특정 출력으로 향할 확률이 switch의 throughput 𝜌가 된다. 이는 다음과 같은 수식으로 주어진다:

𝜌=1−(k−1k)sk𝜌 = 1 - \left( \frac{k - 1}{k} \right)^{sk}

이 수식은, k개의 입력이 있고 그중 s개의 입력이 각 출력에 무작위로 선택될 확률을 바탕으로, 적어도 하나가 특정 출력을 향할 확률을 나타낸다.


그림 17.10

  • (a) 4×4 switch로, 입력 speedup이 1이다. 입력 수와 출력 수가 같고, 모든 포트는 단위 대역폭을 가진다.
  • (b) 입력 speedup이 2인 구조로, 출력 수의 두 배만큼 입력이 존재한다. 이는 더 간단한 할당 문제를 만든다.

그림 17.12에서는 4개의 출력을 가진 switch에 대해 throughput과 input speedup의 관계를 보여준다.

  • speedup이 없는 경우 → 68% capacity
  • speedup이 2일 경우 → 90% capacity
  • speedup이 3일 경우 → 97% capacity

입력 speedup이 4에 도달하면 (일반적으로 k에 해당), 더 이상 allocator가 필요 없다. 이때, 각 input buffer의 crossbar 입력을 특정 출력 포트에 고정할 수 있으며, 이는 17.2.1절에서 설명한 bus switch와 동일한 상황이 된다. 즉, 100% throughputtrivial arbitration으로 달성할 수 있다. 따라서 speedup이 k 이상인 switch를 만드는 것은 불필요하다.

출력 측에 speedup을 적용한 switch도, 동일한 수준의 input speedup을 가진 switch와 동일한 throughput을 separable allocator를 통해 달성할 수 있다.

 

그림 17.11 설명 – Crossbar Output Speedup

  • (a) 출력 speedup이 2인 4×4 switch. 각 output port에 2개의 output buffer가 연결되어 있음.
  • (b) 입력과 출력 양쪽에 speedup이 2인 switch. 입력은 2배로 늘어난 buffer를 통해 들어오고, 출력도 2배의 속도로 처리됨.

이 경우, separable allocator는 반대 방향으로 동작한다. 즉, 각 출력 포트는 자신에게 도착해야 하는 flit을 기다리며, 해당 flit을 가진 입력 포트에 요청을 보낸다. 하지만 이 방식은 입력 포트의 정보를 출력 포트까지 전달해야 하므로 실제 구현이 어렵다. 또한 출력 버퍼링이 필요하기 때문에, 일반적으로는 출력 speedup보다는 입력 speedup이 선호된다.

입출력 모두에 speedup이 있는 switch는 throughput이 1을 초과할 수도 있다. 물론 input/output buffer가 유한하므로 지속적인 처리에는 한계가 있다. 입력 speedup을 si, 출력 speedup을 so라고 하고, si ≥ so라면, 전체 speedup은 so이며, 상대적인 입력 speedup은 si/so로 간주할 수 있다. 이때 throughput 𝜌는 다음과 같이 주어진다:

𝜌=so(1−(k−1k)(si⋅k)/so)𝜌 = so \left(1 - \left( \frac{k-1}{k} \right)^{(si \cdot k)/so} \right)


그림 17.12 – Throughput vs Input Speedup

이 그림은 출력 포트 수 k = 4인 crossbar switch에 대해 input speedup에 따른 throughput을 보여준다. random separable allocator를 1회 적용한 경우:

  • speedup = 1 → throughput 약 68%
  • speedup = 2 → throughput 약 90%
  • speedup = 3 → throughput 약 97%
  • speedup = 4 → throughput 약 100% 도달

대부분의 경우 crossbar는 전체 speedup이 1.2~1.5 사이일 때 100% throughput을 비교적 간단한 할당기와 낮은 latency로 달성할 수 있다. 이후 input 포트를 두 배로 늘려 할당기를 더 단순화하는 것이 일반적이다.


17.2.3 Network Switches

switch는 여러 개의 작은 switch로 구성된 network 형태로도 구현할 수 있다. 예를 들어, 3D torus network에서 dimension-order router를 구현하기 위해 필요한 7×7 switch는 3개의 3×3 switch로 구성할 수 있다(그림 17.13 참조). 이 구조는 crosspoint 수를 49개에서 27개로 줄여준다.

또한, 각 dimension을 +/- 방향으로 분리하여 더 세분화할 수도 있다(그림 17.14 참조). 이때 전체 crosspoint 수는 33개로 증가하지만, 각 switch는 2×2 크기로 작아진다.

이러한 partitioning은 전체 crosspoint 수를 줄이고 logic의 locality를 개선하여 배선 길이를 줄이는 효과가 있다. 그러나 전체 경로를 동시에 할당하려면 제어가 복잡해지며, 각 partition 사이에 flit buffer가 필요하다. 또한 traffic 패턴이나 routing 방식에 따라 내부 링크의 부하가 외부 채널보다 더 커질 수 있다.

따라서 특별한 이유가 없다면 switch를 여러 개의 작은 switch로 나누는 것은 피하는 것이 바람직하다. 단, 패키징 계층 구조에 따라 switch를 나눠야 하는 경우는 예외다.


17.3 Output Organization

그림 16.1에서 본 것처럼, output unit의 datapath는 주로 FIFO buffer로 구성되며, switch의 속도를 output channel의 속도에 맞추기 위한 역할을 한다. 출력 speedup이 없는 switch에서는 datapath가 필요 없으며, flit은 switch를 통과하자마자 직접 output channel로 전송된다.

반면 출력 speedup이 있는 switch에서는 switch와 채널 사이에 flit을 임시 저장할 수 있는 FIFO buffer가 필요하다.

output buffer는 virtual channel 별로 분할할 필요가 없다. 하나의 공용 FIFO buffer를 사용해도, 각 virtual channel 간의 의존성이 생기지 않는다. 그 이유는 output FIFO가 절대 block되지 않기 때문이다. 매 flit 시간마다, FIFO의 head에 flit이 있으면 이를 channel로 전송하고, downstream buffer 상태와 무관하게 동작한다. 따라서 backpressure는 output buffer에는 전달되지 않고, 대신 switch pipeline의 SA 단계에서 입력 측 traffic을 조절하게 된다.

하지만 output buffer가 overflow되지 않도록 하기 위해, switch allocator에 backpressure를 제공해야 한다. buffer 점유량이 특정 임계치를 초과하면, output buffer는 switch allocator에 해당 출력 포트로의 전송을 일시 중단하라고 알린다.

output buffer는 일반적으로 2~4 flit 정도면 충분하다. switch와 채널 간 속도 차이를 맞추는 데 이 정도면 충분하고, 그 이상 buffer를 늘려도 성능 향상 없이 면적만 낭비된다.

 

17.4 사례 연구: IBM Colony Router의 Datapath

IBM Colony router는 IBM SP 상호연결 네트워크 계열의 3세대 라우터로, 이전 세대인 Vulcan router에 대한 설명은 11.3절에서 다루었으며 Colony는 유사한 내부 구조와 동일한 다단계 네트워크 토폴로지를 채택하고 있다. Colony에는 여러 향상된 기능이 추가되었는데, 대표적으로는 더 높은 신호 속도, 더 빠른 내부 클럭 사이클, adaptive 및 multicast routing 지원이 포함된다. 이 결과, 대규모 상호연결 네트워크에까지 확장 가능한 router가 되었고, 예로는 8,192개의 프로세서를 가진 IBM SP 슈퍼컴퓨터인 ASCI White가 있으며, 이는 2000년부터 2001년까지 세계에서 가장 빠른 컴퓨터였다.

그림 17.15는 Colony 내부 구조를 보여준다. 8×8 switch는 hybrid datapath 구조를 채택하며, 이는 shared central memory와 input-queued bypass crossbar를 함께 사용하여 packet을 저장하고 전송한다. 어떤 packet이 switch의 input port에 도착하면, 먼저 bypass crossbar에 접근 요청을 한다. 요청한 output port가 사용 가능하면, packet은 즉시 router를 통과하며 pipeline 처리되어 지연이 최소화된다. 네트워크 부하가 낮을 때는 대부분의 packet이 bypass crossbar 접근에 성공하므로, 전체 지연은 일반적인 input-queued router와 거의 비슷해진다.

만약 bypass crossbar 접근에 실패하고, 8개의 flit으로 구성된 chunk 하나가 input port에 도착하면, 해당 packet은 central memory 접근을 요청한다. 이 요청은 결국 반드시 처리된다. 8개의 input port가 모두 block되고 central memory 접근이 동시에 필요한 경우도 있으므로, memory의 대역폭은 router의 총 입력 대역폭과 같아야 한다. 이론적으로는 16포트 SRAM (각 input/output port용)으로 구현 가능하지만, 실제로는 고포트 SRAM은 느리고 고가이기 때문에 부적절하다.

대신 Colony router는 8-flit 너비의 2-port SRAM으로 central memory를 구성하였다. SRAM의 read/write 포트를 시간 분할 방식으로 다루어, 각 input/output port가 8-flit chunk 전체를 한 번에 전송하도록 하였다. 동일 cycle에 여러 포트가 memory 접근을 요청하면, least recently used (LRU) 방식으로 순서를 정해 접근하게 된다. 이처럼 time-multiplex된 wide banked SRAM은 현실적인 구현을 가능하게 하지만, granularity가 8-flit 단위로 커져서, packet 길이가 8의 배수가 아닐 경우 bandwidth 낭비가 발생한다.

이를 최적화하기 위해, wide SRAM은 2-flit 너비의 4개 bank로 나뉜다. 각 포트는 한 cycle에 1 flit씩 순차적으로 전송하며, access가 staggered 방식으로 이루어진다. 예를 들어 input 1은 첫 cycle에 첫 flit, 다음 cycle에 두 번째 flit을 전송한다. 이 구조는 각 포트가 1-flit 너비의 채널로 SRAM에 연결될 수 있도록 하며, input/output 포트에서 central memory 접근을 위해 각각 하나의 crossbar가 필요하다. 만약 bank 접근이 동시에 이뤄진다면, 포트마다 8배 폭의 채널이 필요하므로 배선이 매우 복잡해졌을 것이다.

Colony의 central memory는 linked list 구조를 통해 관리된다. 각 chunk는 두 개의 필드를 추가로 가지고 있으며:

  • 첫 번째 필드는 next packet pointer, 각 output은 FirstP / LastP 포인터로 자신에게 도착할 packet 리스트를 유지함.
  • 두 번째 필드는 next chunk pointer, 각 packet은 여러 chunk로 구성될 수 있으므로 chunk 단위 리스트는 FirstC / LastC로 관리됨.
  • 또한 사용 가능한 chunk들은 free list로 관리되며, head 포인터는 Free, 두 번째 엔트리는 FreeList로 관리되어 read/write를 동시에 지원함.

그림 17.16은 이러한 linked list 구조의 예시이다.

  • (a)에서는 두 개의 packet이 central buffer에 저장되어 있으며,
  • (b)에서는 packet A의 첫 chunk가 읽히고, packet B의 chunk가 새로 기록된다.

읽기는 FirstC가 NULL인지 확인하여 새로운 packet이 필요한지 판단하고, 그에 따라 FirstP를 따라 첫 chunk를 읽고, FirstC 및 FirstP를 갱신한다. freed chunk는 free list로 이동된다. 쓰기는 free list에서 chunk를 꺼내 데이터를 저장하고, 기존 packet에 이어지는 chunk이면 LastC를 따라 next chunk pointer를 설정한다.


17.5 참고 문헌

  • Tamir & Frazier, Stunkel 등은 동적 buffer 관리 기법을 자세히 설명하였다.
  • J-Machine, Cray T3D 등은 dimension 단위로 switch를 분할하여 구현을 단순화하였다.
  • Nojima 등은 최대 분할 설계를 제시하였고,
  • Torus Routing Chip, SGI SPIDER, Cray T3E는 crossbar 기반 switch에 speedup을 적용하였다.
  • Shared memory 기반 접근은 Katevenis 및 이 장의 Colony 설계에서 볼 수 있다.
  • HIPIQS 아키텍처는 input-queued 방식에 speedup 및 동적 buffer 관리를 결합하였다.
  • Ahmadi & Denzel, Tobagi는 다양한 datapath 구조에 대한 훌륭한 서베이를 제공하였다.

17.6 연습문제

17.1 Circular buffer 관리 하드웨어
→ 삽입 및 제거를 동시에 수행하는 register-transfer-level 다이어그램을 그리라. full/empty 상태 판단 로직을 포함하라. Verilog로 구현해도 좋다.

17.2 Linked-list buffer 관리 하드웨어
→ 단일 cycle 내에 삽입 또는 제거가 가능한 linked-list 구조도 또는 Verilog 코드를 그리라.

17.3 Bus 기반 switch 설계
→ P=7의 입력/출력 포트를 가진 router와 8 phit 크기의 flit이 있다. 효율적인 bus switch 설계를 설명하라. 매 cycle bus가 운반해야 할 phit 수는?

17.4 입력 분할 bus 기반 switch
→ 두 개의 bus에 각각 두 개의 입력이 연결되고, 각 출력은 두 bus 중 하나에서 읽을 수 있는 구조를 그려라. allocation 방법을 설명하라. 출력이 두 bus에서 동시에 읽을 수 있는 경우 방법이 어떻게 달라지는가?

17.5 이중 분할된 bus 기반 switch
→ 입력과 출력을 두 그룹으로 분할한 8포트 switch 구조를 그리고, 네 개의 독립적인 bus를 사용하는 구조를 설명하라.

17.6 Memory switch 분할
→ 그림 17.1(a)의 memory switch 구조에서 출력이 두 그룹으로 나뉘었을 때 필요한 메모리 수와 너비를 일반화하라.

17.7 Buffered crossbar
→ 위의 memory switch 구조에 대해 입력과 출력을 P개 그룹으로 나누고, 메모리 수와 너비를 계산하라.

17.8 두 개의 free list entry 추적의 장점
→ IBM Colony linked list 구조에서 첫 번째 및 두 번째 free entry를 추적할 때, 삽입/삭제/simultaneous 수행을 위한 pseudocode를 작성하라. 각각 단일 read/write 포트를 가진 3개의 메모리(data, packet pointer, chunk pointer)를 사용하라.

반응형

'System-on-Chip Design > NoC' 카테고리의 다른 글

Allocation  (1) 2025.06.16
Arbitration  (1) 2025.06.16
Router Architecture  (2) 2025.06.05
Quality of Service  (1) 2025.06.05
Deadlock and Livelock  (2) 2025.06.05
반응형

라우터는 register, switch, function unit, control logic으로 구성되며, 목적지로 향하는 flit을 버퍼링하고 전달하는 데 필요한 라우팅 및 흐름 제어 기능을 함께 구현한다. 다양한 라우터 구성 방식이 있지만, 이 장에서는 일반적인 virtual-channel router의 아키텍처를 살펴보고 라우터 설계에서 고려되는 주요 이슈와 트레이드오프에 대해 논의한다.

현대 라우터는 flit 단위로 파이프라인화되어 있다. head flit은 라우팅과 virtual channel 할당을 수행하는 파이프라인 단계를 거치고, 모든 flit은 switch 할당 및 switch traversal 단계를 거친다. 특정 파이프라인 단계가 현재 사이클에서 완료되지 않으면 pipeline stall이 발생한다. 이 경우 flit의 순서를 유지해야 하므로 해당 stall 이전의 모든 파이프라인 단계의 동작이 중단된다.

대부분의 라우터는 buffer 공간을 할당하기 위해 credit 방식을 사용한다. flit이 채널을 따라 downstream으로 이동하면서, upstream 방향으로는 방금 비워진 버퍼에 접근할 수 있도록 credit이 전달된다. 버퍼 수가 제한된 라우터에서는 credit 처리 지연이 성능에 큰 영향을 줄 수 있다. 또한 credit은 deadlock 속성에도 영향을 미친다. 모든 credit이 반환되기 전에 virtual channel이 할당되면, 현재 채널을 할당받은 패킷과 downstream 버퍼에 아직 남아있는 다른 패킷 사이에 의존성이 생긴다.


16.1 기본 라우터 아키텍처

16.1.1 블록 다이어그램

그림 16.1은 일반적인 virtual-channel router의 블록 다이어그램을 보여준다. 이 블록들은 기능에 따라 datapath와 control plane의 두 그룹으로 구분할 수 있다. datapath는 패킷의 payload 저장 및 이동을 처리하며, 입력 버퍼 집합, 스위치, 출력 버퍼 집합으로 구성된다.

 

control plane은 datapath 자원 내에서 패킷의 이동을 조정하는 역할을 하며, 라우터에서는 route computation, virtual-channel allocation, switch allocation을 수행한다. 입력 버퍼에는 입력 제어 상태가 포함되어 input unit을 구성하며, 출력도 마찬가지 방식이다.

각 패킷의 flit은 라우터의 input unit에 도착한다. input unit은 도착한 flit을 저장하기 위한 flit buffer와 해당 입력 링크에 연결된 각 virtual channel의 상태를 유지한다. 일반적으로 각 virtual channel의 상태는 Table 16.1에 제시된 다섯 개의 필드로 구성된다.

패킷 전송을 시작하려면 우선 route computation을 수행해 어떤 출력 포트로 보낼지 결정해야 한다. 출력 포트가 정해지면, virtual-channel allocator에게 출력 virtual channel을 요청한다. 라우팅과 virtual channel 할당이 완료되면, switch allocator가 switch와 출력 채널에 대해 시간 슬롯을 할당해 flit을 해당 출력 unit으로 전송한다. 마지막으로, 출력 unit은 flit을 다음 라우터로 전달한다. 입력 unit과 마찬가지로, 출력 virtual channel 상태도 Table 16.2에 제시된 여러 상태 필드를 포함한다.

라우터의 제어는 packet 단위와 flit 단위라는 두 가지 다른 주기로 동작한다. route computation과 virtual-channel allocation은 packet당 한 번 수행되며, 이에 따라 virtual channel의 R, O, I 필드가 한 번만 갱신된다. 반면 switch allocation은 flit마다 수행되므로, P와 C 필드는 flit 주기로 갱신된다.

Table 16.1: 입력 virtual channel 상태 필드 (5-vector: GROPC)

필드 이름설명
G (Global state) idle (I), routing (R), output VC 대기 중 (V), active (A), credit 대기 중 (C) 중 하나의 상태
R (Route) 라우팅 완료 후 선택된 출력 포트
O (Output VC) virtual-channel 할당 완료 후 패킷에 할당된 출력 포트 R의 virtual channel
P (Pointers) 해당 virtual channel의 head와 tail flit이 위치한 input buffer 포인터
C (Credit count) 출력 포트 R의 virtual channel O에서 사용 가능한 downstream flit buffer 수
 

Table 16.2: 출력 virtual channel 상태 필드 (3-vector: GIC)

필드 이름설명
G (Global state) idle (I), active (A), credit 대기 중 (C) 중 하나의 상태
I (Input VC) 현재 이 출력 virtual channel로 flit을 전송하는 입력 포트 및 virtual channel 정보
C (Credit count) downstream 노드에서 이 virtual channel이 사용할 수 있는 빈 버퍼 수
 

16.1.2 라우터 파이프라인

그림 16.2는 일반적인 virtual-channel router의 파이프라인 동작을 Gantt 차트 형식으로 보여준다. 각 head flit은 라우팅 계산(RC), virtual channel 할당(VA), switch 할당(SA), switch 전송(ST)의 단계를 거쳐야 한다. 그림에서는 각 단계가 1 클럭 사이클씩 걸리는 파이프라인을 나타낸다. 도표에서는 stall 없이 패킷이 각 파이프라인 단계를 통과하는 이상적인 상황을 보여준다. 실제로는 어느 단계에서든 stall이 발생할 수 있다.

라우팅 과정은 head flit이 cycle 0에 라우터에 도착하면서 시작된다. 이때 flit의 헤더에는 도착한 입력 포트의 virtual channel 정보가 포함되어 있다. 이 virtual channel의 초기 global 상태(G)는 idle이다. head flit의 도착으로 인해 cycle 1 시작 시 해당 virtual channel은 routing 상태(G = R)로 전이된다.

cycle 1 동안 head flit의 정보를 이용해 라우터 블록은 출력 포트를 선택한다. 이 결과는 virtual channel 상태의 route 필드(R)에 반영되며, virtual channel 상태는 cycle 2 시작 시 output VC 대기 상태(G = V)로 전이된다. 이와 동시에 첫 번째 body flit이 라우터에 도착한다.

cycle 2에서는 head flit이 VA 단계로 진입하고, 첫 번째 body flit은 RC 단계를 통과하며, 두 번째 body flit이 도착한다. VA 단계에서는 R 필드의 값을 이용해 출력 포트를 지정하고, 해당 포트에서 사용할 수 있는 output virtual channel을 할당받는다. VA 결과는 virtual channel 상태의 O 필드에 반영된다.

그림 16.2에서 보는 바와 같이 RC와 VA는 head flit에만 적용되며, SA와 ST는 모든 flit에 대해 적용된다. stall이 없는 경우 각 flit은 앞선 flit보다 한 사이클씩 늦게 파이프라인에 진입하고 각 단계마다 한 사이클씩 진행된다.

 

virtual-channel allocator가 성공적으로 할당되면, 해당 입력 virtual channel의 상태는 active(G = A)로 전환된다. 동시에 할당된 출력 virtual channel의 상태 벡터도 active(G = A)로 설정되며, 해당 입력 virtual channel을 식별하기 위해 출력 virtual channel의 입력 필드(I)가 업데이트된다. tail flit이 채널을 해제할 때까지, 출력 virtual channel의 credit(C) 필드는 입력 virtual channel의 C 필드와 동일한 값을 유지한다.

deadlock 분석 관점에서 보면, VA 단계에서 입력 virtual channel에서 출력 virtual channel로의 의존성이 생긴다. 하나의 출력 virtual channel이 패킷에 할당되면, 해당 패킷이 전부 다음 노드의 출력 virtual channel buffer로 이동할 때까지 입력 virtual channel은 해제되지 않는다.

cycle 3이 시작되면 패킷 단위의 모든 제어 처리는 완료되고, 그 이후로는 flit 단위의 switch allocation(SA) 처리만 남는다. 이 시점에서 head flit이 시작하지만 다른 flit들과 동일하게 처리된다. 이 단계에서는, 활성 상태(G = A)이고 buffer에 flit이 있으며(P), downstream buffer가 비어 있는(C > 0) 모든 virtual channel이 switch를 통해 출력 unit으로 flit을 전송하기 위한 시간 슬롯을 요청한다. switch 구성에 따라, 이 할당은 switch의 출력 포트뿐 아니라 동일한 입력 unit 내 다른 virtual channel들과 입력 포트에 대해서도 경합할 수 있다. switch 할당 요청이 성공하면, 입력 버퍼의 포인터 필드(P)가 갱신되고, 해당 flit이 차지했던 buffer가 해제되었음을 반영해 credit count가 감소되며, 이전 라우터로 credit이 전송된다.

그림 16.2에서 cycle 3에 switch allocation이 성공하고, cycle 4에 head flit이 switch를 통과(ST)한다. switch가 비어 있는 상황이라면, cycle 5에 다음 라우터로 flit을 전송할 수 있다.

head flit이 virtual channel 할당을 받고 있는 동안 첫 번째 body flit은 RC 단계에 있으며, head flit이 SA 단계에 있을 때 첫 번째 body flit은 VA 단계, 두 번째 body flit은 RC 단계에 있다. 하지만 routing과 virtual-channel allocation은 패킷 단위로 처리되므로, body flit은 해당 단계에서 수행할 작업이 없다. body flit은 해당 단계를 우회할 수 없고 순서를 유지해야 하므로, SA 단계에 도달할 때까지 input buffer에 저장되어야 한다. stall이 없다면, 파이프라인에 동시에 세 개의 body flit이 존재하므로 최소 세 개의 입력 buffer 위치가 필요하다. 이후 credit stall을 방지하기 위해 더 큰 buffer가 필요함을 설명할 것이다.

각 body flit이 SA 단계에 도달하면 head flit과 동일하게 switch 시간 슬롯을 요청한다. 이 처리 과정은 flit 단위로 수행되며, head flit과 동일하게 취급된다. 각 flit에 대해 switch 슬롯이 할당되면 virtual channel의 P와 C 필드가 갱신되고 credit이 생성되어 이전 라우터로 전달된다.

마지막으로 cycle 6에서는 tail flit이 SA 단계에 도달한다. tail flit의 switch 할당도 head 및 body flit과 동일하게 처리된다. cycle 6에서 tail flit의 할당이 성공하면, cycle 7 시작 시 해당 virtual channel은 해제되며 출력 virtual channel 상태와 입력 virtual channel 상태는 idle(G = I)로 전환된다. 단, 입력 버퍼가 비어 있지 않다면 다음 패킷의 head flit이 이미 대기 중일 수 있으며, 이 경우 상태는 바로 routing(G = R)으로 전환된다.


16.2 Stall

앞서 설명에서는 flit과 packet이 파이프라인을 따라 지연 없이 진행된다는 이상적인 상황을 가정했다. 즉, 할당은 항상 성공하고 채널, flit, credit이 필요할 때 항상 사용 가능하다고 가정했다. 이 절에서는 이상적인 동작을 방해하는 6가지 stall 사례를 Table 16.3을 기준으로 설명한다.

처음 세 가지는 packet stall로, 라우터의 packet 처리 단계에서 발생한다. 이들은 virtual channel이 R, V, A 상태로 진입하지 못하게 한다. 반면 virtual channel이 active(A) 상태에 들어간 후에는 packet 처리가 완료되었으며, 이후에는 flit stall만 발생할 수 있다. flit stall은 switch allocation이 실패하여 flit이 진행하지 못하는 경우로, 그 원인은 flit 없음, credit 없음, switch 슬롯 경쟁 실패 등이 있다.

Table 16.3: 라우터 파이프라인 stall의 종류

Stall 종류P/F상태설명
VC Busy P ¬I 연속된 packet으로 인해 발생. 이전 패킷의 tail flit이 switch allocation을 마치기 전 다음 packet의 head flit이 도착해 buffer에 대기함
Route P R 라우팅 실패로 R 상태에서 재시도 필요
VC Allocation P V VA 실패로 V 상태에서 재시도 필요
Credit F A credit 없음. downstream에서 credit이 도착해야 진행 가능
Buffer Empty F A flit 없음. upstream에서 stall 발생 가능성
Switch F A switch 할당 실패. 다음 사이클에 재시도

Figure 16.3: Virtual-channel allocation stall 예시

패킷 A의 head flit은 cycle 1에서 라우팅을 마치고 cycle 2부터 출력 virtual channel을 요청하지만, 모두 사용 중이라 할당 실패. 이 요청은 tail flit이 cycle 4에 switch allocation을 마친 패킷 B가 virtual channel을 해제할 때까지 실패한다. cycle 5에 패킷 A가 virtual channel을 할당받고, cycle 6에 switch allocation, cycle 7에 switch traversal을 수행한다. 이때 A의 body flit도 head flit이 SA 단계를 마치기 전까지 stall된다. 단, 충분한 입력 버퍼(예: 6개 flit)가 있다면 입력 채널의 전달 속도는 느려지지 않는다.

Figure 16.4: Switch allocation stall 예시

head flit과 첫 번째 body flit은 stall 없이 통과하지만, 두 번째 body flit은 cycle 5에 switch 할당 실패. cycle 6에 재시도 성공. 이후 flit도 모두 1 사이클씩 지연됨. credit stall도 동일한 타이밍을 가지지만, switch 슬롯 부족이 아닌 credit 부족으로 인해 요청 자체를 못 하는 상황이다.

Figure 16.5: Buffer empty stall 예시

head flit과 body flit 1은 정상 처리되지만 body flit 2는 cycle 6에 도착. 이 flit은 도착 직후인 cycle 7에 SA 단계를 거치고, RC와 VA는 비워진 pipeline 단계를 그대로 우회한다. 이후 flit들도 마찬가지로 SA 단계로 바로 이동한다.


16.3 Credit을 이용한 루프 닫기

SA 단계에서 flit이 링크의 upstream 측을 떠나면 buffer가 할당된다. 이 buffer는 동일한 flit이 downstream의 SA 단계를 통과한 뒤 reverse 채널을 통해 credit이 반환되어야 재사용할 수 있다. 이 credit이 upstream 측의 입력 unit에 도달해야 buffer를 재사용할 수 있다. 따라서 buffer 하나를 나타내는 token은 하나의 루프를 따라 움직인다고 볼 수 있다: upstream의 SA → flit과 함께 downstream으로 이동 → downstream SA → credit으로 upstream으로 복귀. 이 동안 flit은 upstream 측의 RC, VA, SA 세 단계에서만 buffer를 점유하며, 루프의 나머지 시간은 buffer가 비어 있는 idle 시간이다.

credit 루프 지연 시간 tcrtt_{crt}는 flit 시간 단위로 표현되며, credit stall 없이 채널이 최대 대역폭으로 동작하려면 upstream 측에 필요한 최소 flit buffer 수의 하한을 제공한다. 각 flit이 하나의 buffer를 필요로 하므로...

 

token이 credit 루프를 완전히 한 바퀴 돌아야만 buffer를 재사용할 수 있기 때문에, flit buffer 수가 tcrtt_{crt}보다 적으면 첫 번째 credit이 돌아오기 전에 buffer가 모두 소진된다. credit 루프 지연 시간은 flit 시간 단위로 다음과 같이 정의된다.

즉, 충분한 buffer가 있으면 duty factor는 1이 되어 전체 대역폭을 사용할 수 있지만, buffer 수가 부족하면 credit stall로 인해 duty factor가 감소하고, 그에 따라 전송률도 비례하여 감소한다. 이때 남은 물리 채널 대역폭은 다른 virtual channel이 사용할 수 있다.

Figure 16.6: credit stall 예시
6개의 flit으로 구성된 패킷이 4개의 flit buffer만 있는 채널을 통과하는 경우를 보여준다. upstream은 흰색, downstream은 회색으로 표시했다. 링크 한 방향 이동 시간은 2 cycle이며, credit 전송은 CT, credit count 갱신은 CU 파이프라인 단계에서 수행된다.

이 예에서

  • tf=4t_f = 4 (RC, VA, SA, ST)
  • tc=2t_c = 2 (CT, CU)
  • Tw=2T_w = 2

이를 식 (16.1)에 대입하면 tcrt=11t_{crt} = 11 사이클이 된다. 실제로 body flit 4는 head flit의 credit을 재사용하여 cycle 12에서 SA 단계에 진입한다. buffer가 4개이므로, 식 (16.2)의 duty factor는 4/114/11로 계산된다.


16.4 채널 재할당

credit이 flit buffer의 재사용을 가능하게 하듯, tail flit의 통과는 출력 virtual channel을 재할당할 수 있도록 한다. 하지만 이 재할당은 네트워크의 deadlock 특성에 큰 영향을 줄 수 있다.

패킷 A의 tail flit이 ST 단계에 진입하면, A에 할당된 출력 virtual channel xx를 다른 패킷 B에 할당할 수 있다. B는 같은 입력 포트, 같은 입력 virtual channel, 다른 포트의 virtual channel 등 어디에서든 올 수 있다.

그러나 이 시점에 xx를 B에 할당하면 B → A의 의존성이 생긴다. downstream 라우터의 입력 버퍼에서 A가 차지하고 있다면, B는 그 공간이 비워질 때까지 대기해야 한다. 이를 방지하려면, upstream 라우터의 ST 단계가 아니라 downstream 라우터의 ST 단계에서 tail flit이 빠져나가는 시점까지 기다려야 한다. 실제로는 upstream 라우터가 downstream의 ST 상태를 알 수 없으므로, tail flit의 credit이 돌아와 credit count가 최대치가 되는 시점까지 기다린다. 그러나 이 방식은 많은 short packet이 연이어 전송되는 상황에서는 물리 채널의 대역폭 낭비로 이어질 수 있다.

Figure 16.7: 출력 virtual channel 재할당의 세 가지 방식

  • (a) 보수적 방식: tail flit의 credit이 돌아올 때까지 기다림. B의 head flit은 cycle 3에 RC를 완료한 뒤 cycle 15까지 VA 단계로 진입하지 못하고 12 cycle 동안 stall됨. 이 경우 지연은 tcrt+1t_{crt} + 1.
  • (b) 공격적 방식: tail flit이 SA 단계를 마치자마자 VA 수행. B는 cycle 5에 VA 완료, 단 한 번만 stall됨. 단, downstream 라우터의 RC는 tail flit이 해당 라우터의 ST 단계를 끝낸 cycle 11까지 지연됨. 논리 단순.
  • (c) 더욱 공격적 방식: tail flit이 아직 ST를 끝내기 전에도 B가 RC를 수행함. 이때 virtual channel은 동시에 두 패킷의 상태를 관리해야 하므로 제어 논리가 복잡해짐. 예를 들어 B는 RC를 완료했지만, A가 SA 할당에 실패하면 R 필드는 B의 것이고 O, P, C 필드는 A의 것이 되어 몇 cycle 동안 혼재된다. 이 경우 VA 단계에서 busy stall 발생 가능.

16.5 추측과 Lookahead

interconnection network의 지연(latency)은 파이프라인의 깊이와 직접적으로 연관되므로, 각 단계의 지연을 늘리지 않는 범위 내에서 파이프라인 단계를 줄이는 것이 이득이다. 이를 위해 다음 두 가지 방법을 사용할 수 있다:

  1. Speculation (추측 실행): 원래 순차적으로 수행되던 작업을 병렬로 수행
  2. Lookahead (선제 계산): 미리 계산을 수행하여 critical path에서 제거

예를 들어, virtual channel 할당이 성공할 것이라고 가정하고, VA와 SA를 동시에 수행하면 head flit은 세 단계만 거치게 되고, body flit은 RC에서 1 cycle 동안만 idle 상태가 된다.

RC 단계에서 가능한 virtual channel 집합을 얻은 뒤, 이 중 하나에 대한 VA와 해당 물리 채널의 switch 슬롯에 대한 SA를 동시에 요청할 수 있다. virtual channel 할당이 실패하면 다음 사이클에 VA와 SA를 다시 시도하며, switch 할당이 실패하면 다음 사이클에는 SA만 다시 시도하면 된다. 이 경우 이미 output virtual channel은 할당된 상태이므로 더 이상 추측이 아니다.

주: RC 결과가 여러 물리 채널에 걸쳐 있는 경우, 어떤 채널을 선택할지에 대해서도 추측할 수 있다.

 

Figure 16.8은 virtual-channel allocation(VA)과 switch allocation(SA)을 동시에 수행하는 speculative router pipeline을 보여준다. 이 경우 head flit에 대한 switch allocation은 추측(speculative)이며, VA가 성공할 때만 유효하다. VA가 실패하면 SA가 성공하더라도 무시된다.

성능에 부정적인 영향을 주지 않기 위해, switch allocation에서는 추측 요청보다 비추측(non-speculative) 요청에 우선권을 주는 보수적 추측 방식을 사용할 수 있다. 이렇게 하면 비추측 요청에 사용될 수 있는 switch 사이클이 잘못된 추측 요청에 낭비되는 일이 없다.

실제로는, 추측 실행은 파이프라인 지연이 중요한 상황에서 매우 잘 작동한다. 파이프라인 지연은 라우터가 적게 로드되었을 때 중요하며, 이 경우 대부분의 virtual channel이 비어 있어 추측이 거의 항상 성공한다. 반면 라우터가 무겁게 로드되면 대기열 지연(queueing latency)이 지배적이므로, 추측의 성공 여부가 전체 성능에 큰 영향을 미치지 않는다.

한 단계 더 나아가 switch traversal(ST)도 VA 및 SA와 병렬로 추측 수행할 수 있다. Figure 16.9는 VA, SA, ST를 모두 병렬로 수행하는 doubly speculative pipeline을 보여준다. 이 경우 flit은 switch allocation 결과를 기다리지 않고 출력으로 먼저 전송된다. 이를 위해 switch는 충분한 속도향상(speedup), 또는 최소한 입력 속도향상(input speedup)을 가져야 한다. flit이 switch를 통과하는 동안 switch allocation은 병렬로 수행되며, 결과적으로 선택된 flit이 출력된다.

이중 추측이 클럭 사이클 시간을 늘리지 않고 가능한지는 switch와 allocator의 구현 세부 사항에 따라 다르다. 많은 라우터에서는 virtual-channel allocator가 크리티컬 패스이고, switch allocation과 출력 선택은 직렬로 처리해도 클럭 시간을 증가시키지 않는다.

파이프라인 단계를 2사이클까지 줄였지만, 1사이클로 줄이는 것도 가능할까? routing computation도 VA, SA, ST와 병렬로 추측해 수행하는 세 번째 추측을 생각해볼 수 있다. 그러나 이는 비효율적이다. flit이 어디로 갈지를 모르고 채널이나 switch 슬롯을 할당하거나 전송을 시도하는 것은 불가능하기 때문이다.

대신, routing 결과를 lookahead 방식으로 미리 계산할 수 있다. hop i에서 라우터를 통과할 때, 현재 라우터에 대한 라우팅이 아니라, 다음 hop (i+1)의 라우터에 대한 라우팅을 미리 계산하고 그 결과를 head flit에 함께 전달하는 방식이다. 그러면 각 라우터에 도착할 때 이미 출력 경로가 정해져 있어 VA와 SA가 즉시 시작될 수 있다. 다음 hop 라우팅 계산(NRC)은 파이프라인 어느 단계와도 병행 수행 가능하다.

Figure 16.10은 이러한 1-hop route lookahead 방식을 두 가지 파이프라인에 적용한 예다.

  • 왼쪽: 기존 4단계 파이프라인에서 NRC를 VA에 병합해 3단계로 줄임
  • 오른쪽: Figure 16.9의 이중 추측 파이프라인에 적용하여 단일 단계로 축소

latency가 중요한 응용에서는 이보다 더 줄이기 어렵다.


16.6 Flit 및 Credit 인코딩

지금까지 flit과 credit이 라우터 사이를 오간다고 했지만, 실제로 어떻게 구분하고, 어디서 시작하는지, 어떤 방식으로 인코딩되는지는 설명하지 않았다. 이 절에서는 그 구체적인 방식을 간략히 설명한다.

Flit과 Credit의 분리

가장 단순한 방법은 flit과 credit을 별도의 채널로 전송하는 것이다 (Figure 16.11(a)). 일반적으로 flit 채널은 더 많은 정보를 담아야 하므로 credit 채널보다 훨씬 넓다. 그러나 이 방식은 비효율적이다. credit 채널에 대역폭이 남는 일이 많고, 채널이 좁으면 credit을 serialize하여 latency가 증가한다.

더 일반적이고 효율적인 방식은 flit과 credit을 하나의 물리 채널로 통합하는 것이다 (Figure 16.11(b)). 이 경우 각 flit에 credit을 포함시키는 방식(piggybacking)을 사용할 수 있다. 이는 credit이 flit에 '태워져' 같이 전송되는 형태다. 두 객체의 크기는 다르지만, 평균적으로는 flit 하나당 credit 하나가 필요하므로 이 방식은 적절하다.

다른 방법으로는 flit과 credit을 phit 단위로 멀티플렉싱하는 것도 있다. 이 방법은 flit과 credit 비율이 일시적으로 달라질 때, 전체 대역폭을 flit 또는 credit에 집중할 수 있는 장점이 있다. 단, credit이 phit 단위에 딱 맞지 않으면 단편화(fragmentation) 손실이 발생할 수 있다.

Phit-level 멀티플렉싱과 인코딩

phit 단위 멀티플렉싱을 위해서는 각 phit이 무엇의 시작인지(flit/credit/idle), 어디서 시작되는지 알아야 한다. 이 정보는 phit-level 프로토콜로 인코딩된다. Figure 16.12(a)에서 각 phit은 타입 필드(type field)와 payload 필드를 가진다. 타입 필드는 다음과 같이 정의될 수 있다:

  • 10: credit 시작
  • 11: flit 시작
  • 0X: idle

credit과 flit의 길이는 고정되어 있으므로, 중간에 있는 phit은 별도 표시 없이 길이로 추론 가능하다. 중간 phit의 type 필드는 추가 payload 정보에 사용할 수 있다. 만약 credit을 flit에 piggyback한다면 credit 시작 인코딩은 필요 없고, type 필드는 1비트로 줄일 수 있다.

Flit과 Credit의 내용

Figure 16.13에서 각 flit은 다음 필드를 포함한다:

  • VC 식별자: 해당 flit이 속한 virtual channel
  • Type: head flit인지 아닌지, tail 여부도 포함 가능
  • Payload: 실제 데이터
  • Check: 오류 검사용 필드
  • Route 정보: head flit에만 존재, routing 함수가 출력 virtual channel 선택 시 사용
  • Credit 필드: piggyback 방식인 경우 head 및 non-head flit 모두에 포함

Credit은 다음 필드를 포함한다:

  • VC 식별자: credit을 받을 virtual channel
  • Check: 오류 검사용
  • Type (선택): on/off flow control 등의 back-channel 정보 포함 가능

16.7 사례 분석: Alpha 21364 라우터

Alpha 21364는 Alpha 마이크로프로세서 아키텍처 계열의 최신 버전이다. 이 1.2GHz, 1억 5200만 개의 트랜지스터로 이루어진 칩은 Alpha 21264 프로세서 코어에 cache coherence 하드웨어, 두 개의 메모리 컨트롤러, 그리고 네트워크 라우터를 단일 다이에 통합했다. 이를 통해 Alpha 21364는 대규모 공유 메모리 시스템의 단일 칩 구성 블록으로 활용될 수 있다.

이 라우터는 4개의 외부 포트를 가지며 총 22.4GB/s의 네트워크 대역폭을 제공하고, 최대 128개의 프로세서를 2D torus 네트워크로 연결할 수 있다. 21364 라우터의 아키텍처는 본 장에서 소개한 기본 virtual-channel 라우터 구조와 매우 유사하다. 높은 1.2GHz 작동 주파수를 만족시키기 위해 라우터 내부에서 패킷은 깊은 파이프라인을 거치며, 이로 인한 지연을 회복하기 위해 speculation도 사용된다.

Figure 16.14는 21364 라우터 아키텍처의 단순화된 구조를 보여준다. 실제 구현은 8개의 입력 포트와 7개의 출력 포트를 가지지만, 그림에서는 단순화를 위해 3×3 라우터만 표시되어 있다. crossbar는 각 출력 포트에 대한 mux로 구현되어 있으며, switch allocator는 local arbiter와 global arbiter 두 부분으로 나뉘어 있다.

이 설계는 wormhole flow control이 아닌 cut-through flow control을 사용한다. 이로 인해 각 입력 unit은 전체 패킷을 저장할 수 있어야 하지만, coherence 프로토콜에서 최대 패킷 크기가 76바이트에 불과하기 때문에 실용적인 접근이다. 각 입력 unit은 여러 개의 최대 크기 패킷을 저장할 수 있는 버퍼를 포함하고 있으며, 전체 라우터는 316개의 패킷 버퍼를 가진다. 이 정도의 버퍼 수는 deadlock 회피와 adaptive routing을 위한 여러 개의 virtual channel 운용에 충분하다.

Figure 16.15는 라우터의 파이프라인 단계를 보여준다. cut-through 방식이므로 phit 기준으로 파이프라인이 정의된다. 첫 번째 phit은 RC 단계에서 라우팅되고, 이후 wire 지연(T) 단계를 거친다. header decode 및 입력 unit 상태 갱신(DW)을 수행한 후, payload는 input queue에 저장(WrQ)된다. 이 과정과 병행하여 첫 번째 phit이 입력 버퍼에 저장되는 동안 switch allocation이 시작된다.

cut-through flow control을 사용하므로 일반 virtual-channel 라우터에서 분리되었던 virtual-channel allocation과 switch allocation 단계를 하나의 단일 allocation(SA) 단계로 병합할 수 있다. 일반적으로 virtual channel은 출력 포트당 여러 개가 활성화될 수 있지만, cut-through 라우터는 각 출력 포트당 하나의 virtual channel만 활성화되도록 단순화할 수 있다. 이로 인해 virtual channel이 할당되면, 그 자체가 switch allocation도 유효함을 보장한다.

이 구조는 wormhole flow control에서는 virtual channel이 막힐 수 있어 부적합하지만, cut-through 방식에서는 downstream 라우터가 전체 패킷을 수용할 수 있는 충분한 buffer를 가지므로 blocking 없이 전달이 가능하다.

정밀한 타이밍 요구사항을 만족시키기 위해, switch allocation은 local arbiterglobal arbiter로 나뉘며 2단계로 구성된다.

  • SA1 단계: 각 입력 unit에서 local arbiter가 준비된 패킷 중 하나를 선택. 출력 포트가 사용 가능하고 downstream에 빈 패킷 버퍼가 있을 때 준비 상태로 간주된다.
  • RE 단계: 선택된 패킷의 header 정보가 읽혀서 해당 출력으로 전송된다.
  • SA2 단계: 여러 패킷이 하나의 출력 포트를 요청할 수 있으므로, global arbiter가 최종적으로 출력당 하나의 패킷을 선택해 할당한다.
  • ST1 단계: local arbiter에 의해 선택된 모든 패킷의 데이터는 speculative하게 출력으로 전송된다. 나중에 global arbiter 결과에 따라 승자만 유효하게 처리된다.
  • ST2 단계: 실제 전송이 완료됨
  • ECC 단계: 7비트의 오류 정정 코드가 phit에 추가되어 downstream 라우터로 전송됨

스펙 실행 결과는 backchannel을 통해 입력 unit으로 피드백되며, 성공하면 이후 phit은 계속 전송되고 실패 시 switch 내에서 폐기되며 재전송된다. 이와 같은 deep pipeline 설계와 speculative transfer 덕분에 Alpha 21364 라우터는 10.8ns의 매우 낮은 per-hop latency와 70~90%의 피크 처리량을 달성할 수 있다.


16.8 참고 문헌 비고

이 장에서 설명한 기본 virtual-channel router 구조는 Torus Routing Chip에서 유래되었다. 이후 Reliable Router, Cray T3D/T3E, IBM SP 시리즈, SGI SPIDER chip 등에서 개선되었으며, 특히 SPIDER는 한 단계 앞서 라우팅을 수행한 최초의 라우터였다. 라우터 latency를 줄이기 위한 speculation 기법은 Peh와 Dally가 처음 제안하였다.


16.9 연습문제

16.1 단일 virtual channel 사용 시의 단순화
물리 채널당 하나의 virtual channel만 있을 경우, 파이프라인과 global state는 어떻게 변하는가? 각 파이프라인 단계와 global state의 각 필드를 설명하라.

16.2 circuit switching 라우터의 아키텍처
Figure 12.6과 같은 circuit switching 라우터를 설계하라. global state는 무엇인가? 파이프라인은 어떻게 구성되는가? 각 circuit과 flit을 처리하는 단계는 무엇인가?

16.3 ack/nack 흐름 제어가 파이프라인에 미치는 영향
credit 기반 흐름 제어 대신 ack/nack 흐름 제어를 사용할 경우, 라우터 파이프라인은 어떻게 변하는가? credit stall은 어떻게 처리되는가?

16.4 공격적인 virtual-channel 재할당으로 인한 의존성
Duato의 프로토콜을 기반으로 한 2D mesh 네트워크의 최소 adaptive routing 알고리즘을 고려하자. VC 0은 dimension-order routing에, VC 1은 adaptive routing에 사용된다. Figure 16.7에 나온 재할당 전략 중 어떤 것이 이 알고리즘에서 deadlock-free한가?

16.5 좁은 채널에서의 flit 포맷 구성
Figure 16.13의 필드 요구사항이 다음과 같다고 하자: VC 필드 4비트, type 정보 2비트, credit 필드 8비트, route 정보 6비트. 입력 채널이 클럭 사이클당 8비트를 수신할 경우, 라우팅을 시작하기까지 몇 사이클이 필요한가? 필요한 경우 해당 flit 포맷을 제시하라. route lookahead를 사용할 경우, virtual-channel allocation은 첫 사이클에 시작할 수 있는가?

반응형

'System-on-Chip Design > NoC' 카테고리의 다른 글

Arbitration  (1) 2025.06.16
Router Datapath Components  (0) 2025.06.16
Quality of Service  (1) 2025.06.05
Deadlock and Livelock  (2) 2025.06.05
Buffered Flow Control  (1) 2025.06.05

+ Recent posts