Translate

2021년 8월 29일 일요일

2장. 요약: HLS 도구의 흐름(Tool Flow)

2장. 요약: HLS 도구의 흐름(Tool Flow)

[이 글은 자일링스의 Vitis HLS 도구의 흐름을 요약해 본다. 이 도구를 사용하면서 콘솔에 표시되는 로그 메시지를 바탕으로 작성 되었다. 내용 중 추리와 상상으로 인해 오류가 포함되었을 것이다. 읽는 이의 아량을 바라며 활용은 재량에 맞긴다.]

전자 설계 자동화(EDA) 도구 들의 중간 파일들을 너무나 많다. 추상화 단계를 낮추는 정도가 큰 만큼 깊게 들어가는 하위 폴더들과 중간 파일들의 정체를 좀처럼 알기 어렵다. 다행히 대부분 문자 문서 파일들이라 쉽게 열어볼 수 있지만 툴 들끼리 주고받는 형식이기에 이해 불가다. 그렇더라도 툴이 진행되는 과정에서 생성되는 폴더들의 구조와 중간 파일들을 눈에 익혀 두면 설계 자동화 과정을 이해 하는데 도움이 된다. 설계 자동화 도구가 내 뱉는 오류와 경고 메시지에 바르게 대처할 수 있어서 설계자의 부담을 덜고 최적의 결과를 얻기 용이하다. HLS 설계 흐름은 C/C++ 컴파일러 정도의 툴 성숙도에 이르지 못했고 추상화 전이의 간격이 매우 넓다. HLS 의 목표가 RTL 인데 소프트웨어 개발로 치면 추상성이 기계어 코드에 가깝다. 대부분 EDA 툴의 튜토리얼 초반에 폴더 구조를 먼저 설명하는 이유이기도 하다.

1. C 소스 파일

C 기반 설계를 시작은 C로 작성된 설계물과 이를 시험하기 위한 테스트 벤치가 있어야 한다. 시험에 사용할 C 소스 파일은 자일링스의 문서 UG871: Vivado HLS Tutorial 의 2장 실습에서 가져왔다.

2. C 시뮬레이션 (C Simulation)

HLS 프로젝트를 생성 하면 가장 먼저 할 일은 C 시뮬레이션이다. C 디자인 파일 fir.c 과 테스트 벤치 파일 fir_test.c 을 컴파일 하여 실행 파일을 만들고 실행시킨다.  테스트 벤치는 DUT(Design Under Test)인 C 함수 fir()을 main()에 불러온다. 시험용 테스트 입력을 생성하고 출력을 파일에 저장해 두었다가 참조 파일과 비교하여 검증 한다. 오류가 있다면 디버거를 활용하여 문제를 해결한다. 일반적인 C 어플리케이션 제작 과정과 같다. 자일링스 HLS는 C 컴파일러로 자체 C 컴파일러 툴을 사용한다.

HLS 고위 합성기를 한마디로 표현 하면 C 언어를 RTL 언어(Verilog 나 VHDL)로 변환 해주는 언어 변환기다. 자일링스 HLS 툴은 'apcc' 다. 자유 소프트웨어로서 공개 되어 있는 GCC를 기반으로 C/C++ 코드를 읽어 HDL 을 목표로 변환하는 C 컴파일러 인 셈이다.  apcc는 C 구문을 분석하면서 매우 복잡한 중간 파일들을 생성한다. 이 중간 파일들은 이어지는 C 합성(C Synthesis)에 활용된다.


C 시뮬레이션을 실시하면서 만들어진 중간 파일 중에 C 코드 파일도 있다.

    ....... /csim/build/apcc_db/fir.c
    ...... /csim/build/apcc_db/fir_test.c

C 설계를 읽어서 구문 분석후 재생산된 C 파일이므로 읽을 수 있겠으나 내용을 파악하기는 어렵다. 이 파일들의 이름이 C 설계 소스와 동일하므로 주의해야 한다. C 설계 와 테스트 벤치를 컴파일하여 얻은 csim/build/csim.exe 를 실행 시키는 것으로 C 시뮬레이션을 수행한다.

3. C 합성 (C Synthesis)

C 설계 파일을 읽어 RTL의 Verilog와 VHDL 코드들을 합성해 낸다. C/C++ 와 HDL은 컴퓨팅 언어의 면에서 추상성의 차이는 비슷하다. 둘다 현대 최신 컴퓨팅 언어가 갖춰야 할 다양한 요구, 특히 객체 지향성이 반영되었기 때문이다. 

두 언어는 목적에서 큰 차이가 있다. C 언어의 목표는 구축된 하드웨어에 절차를 제어하는 일련의 기계코드 생산이 목표지만 HDL은 하드웨어 구조를 건설하는 것이 목표다. 하드웨어는 작동방식에 있어서 병렬성이 기본이다. 여기에 전자회로의 물리적 지연특성을 교묘히 응용하고 클럭의 개념을 동원하여 순차 작동 회로를 꾸밀 수 있다.

종류를 막론하고 최신 컴퓨팅언어는 규칙이 강직한 문서 작성 도구다. 프로그램이라는 이 문서는 이 추상성을 이해한 인간이 읽고 쓰기 수월하도록 절차적으로 기술된다. 추상성이 높을 수록 언어의 강직성이 높아지는 경향이 있다. LLVM 이라는 컴퓨팅 언어 컴파일러의 프론트 엔드를 이용하면 컴퓨터 언어간의 변환을 수월케 해준다.

HLS/C 합성기도 LLVM을 활용한 프론트엔드에서 반복문을 찾아내고 하드웨어 구조를 만든어 낸다.  반복문(for-loop)을 푸는 과정(loop un-rolling)에서 자료 의존성(data dependency)을 검사하여 파이프라인 구조(pipeline architecture)를 추론해 내고 이를 제어할 FSM을 작성한다. 변수의 수명특성(variable life time)을 고려해 와이어(wire)로 할 것인지 레지스터(register)로 한것인지 결정한다. 모든 연산자가 하드웨어로 만들어지면 하드웨어의 크기가 너무 증가한다. 연산기 입출력에 와이어 혹은 레지스터가 연결됨에 따라 연산기 하드웨어를 공유할 수도 있으므로 자원 최적화를 실시하고 이를 제어할 FSM도 작성한다. 이런 일련의 과정이 하드웨어를 목표로 한 런-타임 최적화(run-time optimization)다. 하드웨어를 위한 런-타임 최적화는 최소 인터벌(interval minimization)이 되도록 하는 것이다.

3. 혼합 시뮬레이션(Co-Simulation)

C 에서 자동화 도구로 만들어진 RTL 을 검증하려고 원래 C 와 동일한 데이터를 내는지 확인해 보고자 한다.

두 설계물은 앞서 살펴본 대로 실행 방식이 완전히 다르다. RTL은 클럭(clock)이라는 시간 관리 기작에 따라 작동되는 반면 C 는 시점 이라는 개념도 없다. 유효한 출력을 내는 시점도 다르다.

C 테스트 프로그램에서 생성한 테스트 입력 파일을 HDL 시뮬레이션에 공유하여 각각의 출력을 비교한다. HDL 테스트 벤치는 HLS 툴을 이용해 C에서 자동으로 생성된다.

HLS 툴이 C에서 HDL로 변환하는 툴을 기반으로 하므로 C의 테스트 프로그램도 HDL 테스트 벤치로 자동변환 시킨다. 결국 HLS 설계 흐름에서 사람이 손댈 부분은 설계와 테스트용으로 C 코드 뿐이다. 과연 이 흐름에서 검증은 완전했을까?

---------------------------------------------------------------------------------
고위 합성 튜토리얼(High-Level Synthesis Tutorial)
[목차][이전][다음]


2장. 실습 1/단계 5: IP 제작 (IP Creation)

 2장. 실습 1/단계 5: IP 제작 (IP Creation)

[검증이 끝난 RTL을 자일링스의 다른 툴에서 사용할 수 있도록 패키징하는 방법을 실습한다. 별거 없으니 생략함.]

IEEE 1685-2009 (IP-XACT) : Standard Structure for Packaging, Integrating, and Reusing IP within Tool Flows

검증이 끝난 설계물을 다른 툴에서 사용할 수 있도록 패키지(라이브러리)화 하는 표준. [참조]

---------------------------------------------------------------------------------
고위 합성 튜토리얼(High-Level Synthesis Tutorial)

2장. 실습 1/단계 4: RTL 검증 (RTL Verification)

2장. 실습 1/단계 4: RTL 검증 (RTL Verification)

[자일링스 Co-Simulation 이 맘에 안들어서 생략]

어짜피 HLS가 C-to-HDL 변환기를 가지고 있으니 내친김에 main()를 포함한 C 테스트 코드에서 자동으로 HDL 테스트 벤치를 생성 시키는 '테스트 벤치 자동화'. 너무나 복잡해서 굳이 그래야 하나 싶을 정도 임. 사실 Co-Simulation 이라고 하기도 부족함.

---------------------------------------------------------------------------------

고위 합성 튜토리얼(High-Level Synthesis Tutorial)

2021년 8월 23일 월요일

2장. 실습 1/단계 3: 고위합성 (High-Level Synthesis)

2장. 실습 1/단계 3: 고위합성 (High-Level Synthesis)

HLS를 이용하여 C 설계를 RTL로 합성 해내고 그 결과물을 평가해 본다.

1. 플로우 탐색창에서 'C Synthesis'를 클릭 하여 고위합성을 실시한다. 이어서 합성 결과를 검토한다.

고위합성이 완료되면 합성 가능한 RTL 수준의 HDL(Hardware Description Language) Verilog와 VHDL을 생성하고 정보창에 결과 보고서를 보여준다. 결과 보고서는 요약본(Summary)과 상세본(Detail)이 있다.

2. 합성된 RTL 설계물의 성능 예측(Performance estimate)을 보기 위해 요약본(Summary)을 열어보자. 합성된 RTL의 성능은 클럭의 주기(동작 속도)와 면적(하드웨어의 량)으로 평가 된다. RTL 단계에서 성능은 실제로 반도체 위에 배치와 배선이 이루어지기 전 이므로 예측된 평가(estimate) 라고 한다.

실제로 반도체 평면에 회로의 배치와 배선(Place & Route)을 마치면 지연이 있게 된다. 따라서 안전한 레지스터 간 전송을 위해 클럭의 주기 시간 간격을 늘려야 한다. 아울러 회로가 차지하는 반도체 평면도 증가한다. 따라서 고위합성의 결과로 보여주는 성능은 예측치가 된다. 

성능예측 보고서의 요약본은 다음과 같은 항목들을 포함한다.

- 시간 예측(Timing Estimation): 합성기에 가해지는 가장 중요한 조건(constraint)이다. 물리적 지연시간을 의미한다. 

합성기는 주어진 지연 목표치(target)에서 불안정 구간(uncertainty)을 뺀 시간을 조합회로의 합성 지연 조건으로 삼는다. 위의 예는 합성의 목표(target)를 10ns 으로 주었다. 향후 배치와 배선(Place & Route)을 위해 여유시간을 2.7ns 로 잡았다. 이 여유시간은 별도 값을 주지 않을 경우 합성기가 목표로 하는 FPGA의 기술 문서에 근거하여 잡는다. [자일링스의 문서상으로 주기의 12.5%로 나와 있으나 그보다 크게 잡는다.] 위의 예는 10.00ns 에서 2.7ns 를 뺀 7.3ns 가 레지스터 사이의 조합 회로에 허용되는 지연조건이 된다. 합성 후 예측된 지연은 6.912ns로 조건 범위내에 있다.

- 성능과 자원 예측(Performance & Resource Estimation):

예측 성능은 레이턴시(latency)와 인터벌(interval)로 평가된다. 레이턴시는 기능을 수행하는데 소요되는 클럭의 갯수다. C 소스에서 for 반복문에 라벨을 Shift_Accum_Loop로 붙여 놓았다. 이 반복문을 수행 하는데 25개의 클럭이 소요되는 것으로 보고 되었다. 함수 fir()을 완료하는데 27개의 클럭을 소모한다. 반복문 탈출에 2개의 클럭이 더 필요했음을 뜻한다. 인터벌(interval)은 설계 모듈이 입력을 받아 계산을 완료하고 출력을 내기까지 소요되는 클럭의 개수다. 예제의 인터벌은 28개다. 레지스터 출력(registered-out)을 위해 1개의 클럭을 더 소모한 것으로 보인다.

자원 예측은 C 설계를 RTL로 구현하면서 사용된 회로의 요소들의 사용량이다. 구현할 목표 하드웨어는 자일링스의 FPGA 다. 자일링스 FPGA의 회로 구성 요소의 단위로는 내장 메모리(BRAM), 곱셈과 누산에 특화된 DSP, 논리식을 구현하는 LUT(Look-Up Table) 그리고 플립플롭 FF 가 있다. C 설계의 for 반목문 내에 곱셈과 덧셈이 DSP 자원으로 구현 됐음을 짐작 할 수 있다. 또한 for 반복문을 풀면서 쉬프트 레지스터를 구현하기 위해 상당량의 FF 가 소요되었다. 그외 for 반복문의 시작과 끝을 제어하기 위한 컨트롤 FSM과 대규모 멀티플렉서 MUX의 구현에 상당량의 LUT 들이 사용되었을 것으로 보인다.

구현된 하드웨어의 구조에 따라 달라지는 레이턴시와 인터벌. 완전한 파이프라인 구조의 하드웨어는 인터벌이 1로 매우 빠른 성능을 보여준다. 실시간 스트림 라인 처리(streamlined processing)에 유리 하지만 엄청난 량의 하드웨어를 필요로 한다. 당연히 전력소모도 많다. 행렬 곱셈처럼 동일한 연산구조를 반복 수행하는 그래픽 처리, 인공지능 분야에 매우 유리한 구조다. 최초 유효 입력 이후 유효 출력이 나오기 시작하기 까지 소요되는 클럭의 개수가 레이턴시다. 성능은 레이턴시 보다 인터벌의 수에 의존한다.

- 하드웨어 인터페이스(HW Interface)

C 에서 고위합성된 RTL 하드웨어가 인접 모듈과 연결되는 입출력 데이터 포트와 컨트롤 포트들을 나열한다. RTL 은 비트폭 및 클럭 상세 수준이다.

하드웨어 모듈이 인접 모듈과 데이터를 주고 받으려면 시스템의 규약에 따른 제어신호가 필요하다. 데이터를 포함해 일련의 제어신호와 절차를 인터페이스(interface)라 한다.

설계의 추상화 수준이 높을 수록 자료 흐름(data flow)에 집중되며 흐름 제어(flow control)는 규약(protocol)으로 정의 되고 겉으로 드러나지 않게 된다. 제어는 하드웨어로 구현될 때 선택이 매우 다양하다. 별도의 제어가 필요없는 고성능 스트림라인(streamlined I/O), 능동(request) 또는 수동(ready) 핸드 쉐이크, 시스템 버스(on-chip bus) 등 적용될 시스템의 규정을 따른다.

C 에서 고위합성된 RTL 설계물은 전자회로로 구현되기 직전의 하드웨어를 기술한 것으로 비트폭(bit-width) 및 클럭(clock) 상세로 기술 되어 있다. 따라서 C의 설계에서 드러나지 않는 핸드 쉐이크용 제어 신호를 가지게 된다. 가장 단순한 메모리 접근에도 두단계 절차가 필요하다. 주소지정이 먼저 선행 되어야 데이터를 읽기 또는 쓸 수 있다.

실제로 C 언어의 배열 변수에 읽기와 쓰기도 한 문장으로 표현 되지만 작동에는 주소 지정이 먼저 있어야 한다. 추상화 수준이 높을 수록 데이터 흐름에 집중하며 실제 작동 절차는 드러나지 않고 규칙되어 있다. 설계자는 높은 추상화 수준에서 문서화 하며 실제 구현은 이 규칙들을 작동절차로 풀어 내는데 바로 컴파일러나 합성기 같은 자동화 도구들이 수행할 몫이다.

합성 보고서의 하드웨어 인터페이스(HW Interface) 항목에는 비트폭 상세 입출력 데이터 및 입출력 제어 신호를 보여준다. 인터페이스 방식을 따로 지시하지 않을 경우 단순 핸드 쉐이크 방식의 규약에 따라 인터페이스를 생성한다.

- 소프트웨어 입출력 정보(SW I/O Information)

C 모델(SW)과 합성된 RTL 모델(HW)의 대응 관계(SW-to-HW Mapping) 관계를 보여 준다. HW 쪽에 제어신호 들이 추가 되었다. 필터 계수 c는 메모리로 구현 되었으므로 데이터 포트 c_q0와 함께c_address0(주소), c_ce0(칩 셀렉트)가 있다. 출력 y에 유효한 값이 실렸다는 표시는 y_ap_vld 로 나타낸다. 인터벌이 1이 아니므로 y 에 유효값이 되는 때를 표시해 주어야 한다.

- 연산자 대조표(Bind Op Report)

고위합성 과정에서 C 모델의 연산자가 어떤 하드웨어로 구현 되었는지 보여준다. 32 비트 곱셈기(mul_ln69)와 누산기(acc_1) 그리고 두개의 가산기(add_ln66, add_ln61)가 사용되었다. 두 변수 입력의 32비트 곱셈기와 누산기는 상당한 규모의 하드웨어를 필요로 할 뿐만 아니라 지연도 크다. 연산을 위해 특별히 마련된 DSP 블럭으로 구현되었다. 두개의 가산기는 C 설계의 반복 구문(for-loop)의 1가감산과 쉬프트 레지스터의 인덱스 가감산을 위한 것이다. 증감량이 고정된 상수와 변수 가감산기로 구현되었다. 반복문이 어떻게 풀려(loop un-rolling) 어느정도 규모의 하드웨어가 되었는지 알 수 있다. 이를 확인해 보기 위해 각 연산기가 C 소스의 어느 문장에서 변환되었는지 대조해 볼 수 있는 기능을 제공한다. 향후 최적 합성 결과를 얻기 위한 합성 조건을 세울때 유용하다.   

[이 기능에 약간의 오류가 있다. 시뮬레이션 용 테스트 벡터를 자동생성을 위해 중간 C 파일이 생성한다. 이때 C 설계 파일과 동일한 이름을 가진 파일이 생성 되는데, 이 파일을 잘못 불러 온다. 엉뚱한 파일을 불러놓고 연산자와 대조하면 69번줄을 지시하고 있다. 이 문제는 'csim' 폴더를 삭제하면 해결된다. 중간 파일들은 C Simulation을 실시하면 다시 생성된다.]

- 저장소 대조표(Bind Storage Report)

C 설계 소스에 일반적으로 저장이 필요한 변수는 레지스터(플립플롭, FF)로 변환된다. 하지만 배열형이 있을 경우 고위합성기는 고집적 메모리로 변환 한다. 메모리는 고집적 저장 장치로서 실리콘 면적을 줄일 수 있으나 속도가 느리고 주소를 먼저 지정해야 하기 때문에 한개 이상의 레이턴시를 소모한다. 이 예제에서는 쉬프트 레지스터에 32비트 레지스터가 11개가 필요했다. 레이턴시 클럭을 1개 더 사용하더라도 1포트 램(ram_1p)으로 구현되었음을 알 수 있다. 인터벌을 줄이기 위한 최적화 조건을 주면 다른 결과를 얻을 수도 있다.

---------------------------------------------------------------------------------

고위 합성 튜토리얼(High-Level Synthesis Tutorial)


2장. 실습1/단계 2: C 소스코드 검증 (Validate the C Source Code)

2장. 실습1/단계 2:  C 소스코드 검증 (Validate the C Source Code)

이 단계에서는 C 코드를 컴파일하고 실행시켜 무결성을 검증한다.  C 검증(C Validation) 또는 C 모의실험(C Simulation) 이라 한다. 검증 기법은 다양하나 이번 프로젝트는 설계된 C 코드 출력과 검증을 위해 준비한 기준값(golden reference)을 비교한다.

1. 설계 탐색창에서 'Test Bench' 항목을 내려 테스트벤치 파일 fir_test.c 을 더블 클릭 하면 정보창에 편집이 가능한 상태로 파일 내용을 보여준다.

2. 디자인 소스 파일이 열리면 부가 창(Auxiliary pane)에 해당 소스 파일에 포함된 디자인 모듈(C의 경우 함수)들을 나열해 주어서 여러 모듈들을 포함하는 경우 쉽게 검색할 수 있다.

설계 모듈의 탐색 뿐만 아니라 모듈에서 사용되고 있는 자원들을(resources) 나열해 준다. 모듈의 자원 으로는 입출력(in-output), 정적 자료(statics), 라벨이 붙은 제어 블럭(labeled control block)들을 보여준다. 합성 결과를 분석하고 생성된 RTL 과 비교할 때 매우 유용하다.

아울러 각 자원들에 합성 지정자(synthesis directives)를 설정해 주는 경우에 매우 유용하다.

3. 테스트 벤치 fir_test.c 의 최상위 모듈 명은 main() 이다. 설계 모듈 fir() 을 테스트 하기 위해,
    - 환경을 구축: 필터계수를 배열 변수 tabs[N] 로 구현
    - 테스트 입력 발생: 단순증감 형태로 주어지는 시험 입력신호 signal
    - 설계 모듈을 호출: for-loop 내에서 스트림 형식의 테스트 입력에 대하여 반복적으로 호출
    - 설계 모듈 fir()이 반환하는 출력을 파일 out.dat 에 기록
    - 테스트 완료 후 표준 파일 out.gold.dat 과 비교
    - 검증 결과를 성공 또는 실패로 판단하여 결과 메시지 출력

C 로 작성된 테스트 벤치 fir_test.c 의 내용은 다음과 같다.

C 로 작성된 테스트 벤치는 향후 RTL 검증을 위한 시뮬레이션에서도 재사용된다. 위의 C 테스트 벤치의 예 처럼 실행중 검증의 성패를 자체 검사(self-checking) 할 수 있도록 작성되었다면 RTL 시뮬레이션에서도 자동 검사 될 것이다.

비바도 HLS 검증 툴은 검증이 성공한 경우 main()은 0을 반환하며 그 외 값이나 반환 값이 없을 경우 검증 실패 했음을 알리는 것으로 정했다.

비바도 HLS 도구는 C 로부터 RTL 테스트 벤치를 자동생성 해주는 툴을 가지고 있다. C 테스트 벤치가 위의 작성요건을 갖춘다면 다른 수고 없이 RTL 테스트 벤치를 자동생성 해준다. 따라서 C 시뮬레이션과 RTL 시뮬레이션이 일치하게 된다. 아주 탄탄 하면서 생산적인 검증 환경이라고 할 만 하다.

GCC 의 디버그 옵션을 주고 컴파일 하면 여러가지 일을 수행 할 수 있다. 시험 대상이 되는  DUT (Design Under Test)인 fir()과 테스트 환경 사이에 주고받는(transaction) 모든 인수 값을 캡춰해서 파일로 저장해 두고 이를 RTL 시뮬레이션 수행용 시험 벡터로 활용한다. 이런 테스트 벡터 자동 생성 기법(Automatic Test Pattern/Vector Generation)을 통하면 RTL 시뮬레이션에 필요한 테스트 벡터 생성시 오류가 끼어들 여지가 없다. 하지만 진정한 Co-Simulation이라고 할 수 없다.

4. 설계 플로우 탐색창(Flow Explore)에서 'C Simulation' 을 클릭 하여 C 코드 검증을 실시한다.

GCC 컴파일러로 C 소스 파일과 테스트 벤치를 컴파일 하여 실행 파일을 생성하고 실행 하여 결과를 보여줄 것이다.

만일 C 시뮬레이션 실패 메시지를 보게 된다면 디버거를 띄워 오류를 추적 해 볼 수 있다. 컴파일 후 디버거 실행을 하려면 'Launch Debugger' 옵션을 선택 한다. [주의: GNU GCC 디버거 GDB는 사용 방법이 매우 어렵다.]

---------------------------------------------------------------------------------
고위 합성 튜토리얼(High-Level Synthesis Tutorial)

2장. 실습1/단계 1: HLS 프로젝트 생성 (Create HLS Project)

2장. 실습1/단계 1: HLS 프로젝트 생성 (Create HLS Project)

비바도 디자인 스위트(Vivado Design Suite 2021.1)에서 Vitis HLS 2021.1을 실행 한다.

1. 시작 화면에서 'Create Project' 선택. (기존의 프로젝트를 선택 할 수 있음)

2. 새 프로젝트 대화창에서,

    (1) '작업할 폴더 위치'를 지정: '작업할 폴더 위치'로는 실습용 압축 파일을 풀어 놓은 폴더를 지정하자.

    (2) '프로젝트명'을 입력: 폴더 'Introduction'에 C 디자인 파일과 테스트 벤치 파일들이 있다. '프로젝트 명'으로 'fir_prj'로 했다.

    (3) '다음'

3. C 설계 파일 'fir.c' 을 추가한다. (테스트벤치용 C 파일은 포함시키지 말것)

4. 디자인이 계층화 되어 있을 경우 가장 상위 모듈(Top Function)을 지정해 주어야 한다.

    (1) 이번 실습에서는 디자인 파일이 한개, 함수도 1개이더라도 상위 모듈을 지정해 준다.

    (2) 'Browse' 버튼을 누르면 디자인 파일에 포함한 함수 목록이 나타날 것이다.

    (3) 가장 상위 모듈이 될 함수 'fir'을 선택 한다.

    (4) '다음'

5. 테스트벤치용 C 파일 추가

6. C 에서 하드웨어로 합성하기 위한 물리적 조건(physical constraints)을 준다.

    - 클럭 주기(Period): RTL은 레지스터와 레지스터 사이의 전송이다. 전송은 플립-플롭의 클럭 주기내에 이뤄진다.
    - 불안정성(Uncertainty): 
시작 플립-플롭의 출력단에서 시작한 신호가 조합회로들을 통과하여 다음 플립-플롭의 입력단 까지 동일한 시간에 도착한다면 매우 이상적(Ideal) 일 것이다. 하지만 실제(Actual)는 전기 신호가 각종 게이트 들의 조합으로 구성된 회로를 통과 할 때 지연이 발생한다. 다음 플립-플롭의 입력에 도착하는 신호가 모두 안정화 될 때 비로서 전송에 유효한 신호가 된다. 불안정성(uncertainty)은 합성기가 가질 수 있는 지연시간 조건의 마진이다. 합성기로 하여금 지연 경로 사이에 허용할 수 있는 조합회로의 최대 지연 경로(maximum delay path)를 제한 하는 것과 같다. 불확정 값을 주지 않은 경우 클럭 주기의 12.5%가 기본 값으로 주어진다.

7. 설계가 구현될 하드웨어를 선택한다. ASIC의 경우 구현을 목표로 하는 반도체 공장의 공정 기술을 선택하는 것과 같다. 보통 테크놀로지(technology)라고 하는데 해당 공정에서 제공하는 라이브러리와 소자의 지연등 물리적 특성이 제시된다. 우리는 자일링스사의 FPGA에서 고르기로 한다.

8. GUI로 구현된 HLS 설계환경을 보여준다.

'디자인 탐색(Design Explore)' 창은 여느 소프트웨어 개발 도구와 같다. 설계에 관여된 모든 파일들의 목록을 볼 수 있다. 하드웨어 합성이 필요한 제한조건들(constraints)도 여기에 기술되어 있다. 설계가 구현될 FPGA와 합성을 위한 물리적 조건들이다. GUI는 편의성을 위한 환경일 뿐이며 실제로 컴파일과 합성은 이 Tcl 스크립트를 읽어 수행된다. 대부분 전자 설계 도구(EDA Tools)는 Tcl 스크립트를  활용한다.

'디자인 흐름(Design Flow)'창은 프로젝트 생성후 합성과 검증까지 이어질 각 단계를 보여준다.

---------------------------------------------------------------------------------
고위 합성 튜토리얼(High-Level Synthesis Tutorial)

2021년 8월 22일 일요일

2장. 실습 1: 고위합성 프로젝트

2장. 실습 1: 고위합성 프로젝트
(Lab 1: Creating a High-Level Synthesis Project)

자일링스 비비도 HLS 설계 툴의 사용법(Design Flow)을 익혀본다. C 코드 검증, HLS로 RTL 생성 그리고 생성된 RTL을 검증 한다. 비바도 디자인 스위트를 설치하면 GCC 컴파일러와 고위합성기High-Level Synthesizer 그리고 RTL 시뮬레이터 XSim 이 포함 되어있다.

실습에 사용될 소프트웨어 및 디자인 파일

1. 비바도 디자인 스위트(Vivado Design Suite 2021.1) [다운로드]
    비바도 디자인 스위트(Vivado Design Suite 2021.1)는 두가지 도구가 포함되어 있다.
    - Vivado 2021.1: 자일링스 FPGA 구현 도구 (HDL 시뮬레이터와 합성기 포함)
    - Vitis HLS 2021.1: 고위합성기 및 GCC 컴파일러, Vivado HLS 에서 개명됨

2. 모델심 알테라 FPGA 에디션(The ModelSim*-Intel® FPGA edition) [다운로드]
    자일링스의 HDL 시뮬레이터 XSim 외에 모델심 사용을 원하는 경우 인텔 알테라 모델심(또는 퀘스타심 QuestaSim)의 스탠다드 버젼을 설치한다.

3. 실습에 사용된 설계 파일 [다운로드]
    - 위 링크를 통해 받은 압축파일을 풀어 놓는다. 이번 실습에 사용할 파일은 'Introduction' 폴더에 있다.


단계 1: HLS 프로젝트 생성 (Create HLS Project)

단계 2:  C 소스코드 검증 (Validate the C Source Code)

단계 3: 고위합성 (High-Level Synthesis)

단계 4: RTL 검증 (RTL Verification)

단계 5: IP 제작 (IP Creation)

---------------------------------------------------------------------------------
고위 합성 튜토리얼(High-Level Synthesis Tutorial)


2021년 8월 20일 금요일

2장. 고위 합성 맛보기(High-Level Synthesis Introduction)

2장. 고위 합성 맛보기(High-Level Synthesis Introduction)

자일링스의 비바도 HLS 툴의 사용법을 간략하게 살펴본다. GUI 와 Tcl 환경에서 HLS 가 어떻게 이뤄지는지 배운다. 실습할 내용은 다음과 같다.

실습 1. HLS의 설계 절차(design flow) 익히기
프로젝트를 생성하고 다음과 같은 HLS의 설계 절차(design flow)를 수행해본다.
    - C 코드의 검증(Validate the C code)
    - 합성 수행(Create and synthesize a solution)
    - 생성된 RTL 코드의 검증 및 재사용 IP 화(Verify the RTL and package the IP.

실습 2. Tcl 활용법

실습 3. HLS 설계 최적화
지시자(directives)를 적용하여 설계물 최적화 시키는 방법을 배운다. 한 C 코드에 다양한 지시자를 주어 합성하면 하드웨어의 크기와 소요 클럭 수가 상이한 여러 종류의 RTL 결과를 얻을 수 있다는 것을 보게 될 것이다.

실습에 사용될 C 코드
C로 작성된 간단한 FIR 필터다.
    - 함수로 기술된 fir()은 세개의 인수를 갖는다.
    - 포인터로 정의된 y 인수는 출력에 해당한다.
    - 필터 계수 C[N]은 외부의 메모리로 부터 제공된다.
    - 입력 x 가 유효할 때마다 fir() 함수가 호출된다.
    - 필터 계산이 수행되는 for-반복문은 병렬성 하드웨어로 변환될 것이다.
    - 함수가 되돌려 지더라도 그 값을 유지해야 하는 shift_reg는 정적 선언되었다.
    - 하드웨어 구조 변경이 달라질 수 있는 부분에 라벨을 붙여두면 디버깅과 분석에 유리하다.
    - 곱셈과 덧셈이 반복되는 연산의 결과를 담을 출력 y의 비트폭에 유의한다.
    - 재사용성을 높이기 위해 임의의 자료형과 필터 탭의 수를 임의로 선택할 수 있게 했다. 이들은 헤더파일에 정의 되었다.

입출력 데이터와 누산기(accumulator)의 자료형은 모두 정수형(int)로 형 정의 되어 있다. 적용될 응용의 필요에 따라 형변환을 수월케 할 수 있다. 이는 설계 재사용성(re-usability)을 높인다.

합성의 목표
    - 최적의 계산성능(highest throughput)을 갖는 하드웨어를 생성 한다.

입출력 방식
    - 입력 데이터는 유효신호 rdy 와 함께 제공된다.
    - 출력 데이타는 유효신호 valid 로 표시한다.

외부 메모리 사용
    - FIR 필터의 계수들은 외부의 단일 포트 RAM에 저장 되었다.

---------------------------------------------------------------------------------
고위 합성 튜토리얼(High-Level Synthesis Tutorial)

1장. 고위합성 튜토리얼 개요 (Tutorial Description)

1장. 고위합성 튜토리얼 개요 (Tutorial Description)

요약

HLS 튜토리얼은 C, C++ 그리고 SystemC 등 높은 추상화 수준으로 기술된 코드(알고리즘)을 RTL(Register-Transfer Level: 데이터 전송의 클럭 단위 상세 수준) 하드웨어로 변환(transform)을 다룬다. C 코드에서 RTL로의 변환을 고위합성 High-Level Synthesis(HLS)이라 한다.

높은 추상화 수준의 C 코드(C++를 포함하여 통상적으로 이렇게 부른다)에서 낮은 클럭 단위 수준 RTL 로 변환할 때는 두가지 선택이 있다. 하드웨어의 크기(area)와 출력 성능(throughput; 계산에 소요되는 클럭의 갯수)이다. 이 선택을 기초로 변환 과정에서 최적화(optimization)가 이뤄진다. 합성(synthesis)은 높은 수준의 코드로부터 하드웨어(논리회로)를 추론(infer)해 내고 이를 최적화(optimize)하는 과정을 포함 한다.

자동화된 HLS 이전에는 원하는 하드웨어를 얻기 위해 C 코드에 인위적 수정이 불가피 했었다. 수정을 가하면 오류가 끼어드는 것을 피할 수 없다. 진정한 고위 합성은 원래의 C 코드를 변경하지 않고도 원하는 하드웨어를 합성해 내야 한다. 이 튜토리얼은 단지 합성 지시자(directives, 혹은 합성 옵션)만을 삽입 하므로서 어떻게 원하는 목적을 달성하는지 보게될 것이다.

이 튜토리얼에서 다루게 될 내용은 다음과 같다.

1. 고위합성 소개(High-Level Synthesis Introduction)

이 튜토리얼은 자일링스(Xilinx)사의 비바도 HLS 도구(Vivado HLS Tool)의 그래픽 개발 환경 Graphical User Interface (GUI)과 티클 Tcl 스크립트가 활용될 것이다.

2. C 코드의 유효성 평가 (C Validation)

HLS 설계는 높은 수준의 C, C++ (SystemC는 C++를 하드웨어 설계에 적합하도록 확장된 라이브러리 모음이다.)에서 시작한다. 합성하기 전에 이 코드들은 테스트 벤치(test-bench)에서 충분히 검증되어야 한다. 테스트 벤치는 설계와 동일한 추상화 수준의 언어 환경에서 작성하므로서 효과적으로 검증을 수행 할 수 있다. 이때 사용되는 기본적인 디버깅 기법은 소프트웨어 개발 과정에서의 그것과 동일하다.

아울러 임의 정밀도 자료형(arbitrary precision data types)과 그 디버깅을 다룬다. 알고리즘을 기술 할 때 필요이상으로 높은 정밀도를 갖는 자료형을 사용할 경우 하드웨어를 낭비하게 된다. 알고리즘이 적용될 시스템에서 규정된 정밀도에 따라 응용 분야에 맞도록 임의 정밀도를 갖도록 선언해 주는 것이 좋다. 고위합성 전에 이에 대한 충분한 검토 역시 테스트 벤치를 통해 실시한다.

합성 지시자(옵션)로 알고리즘의 자료형을 임의 변경 할 수 없다. 합성 지시자는 계산기의 구조(파이프라인 같은 병렬구조는 하드웨어의 크기를 좌우한다)와 제어기의 최적화(소요 클럭 수 및 지연)를 지시할 수 있다.

고수준 코드에서 채용된 자료형은 곧 데이터 패스(data-path)의 비트 폭(bit-width)을 지정하는 것과 같다. 하드웨어의 성능(크기, 지연 등)에 직접 영향을 준다. RTL은 클럭 상세 뿐만 아니라 데이터 패스의 비트폭 상세를 모두 포함하는 수준의 하드웨어 기술이다.

3. 인터페이스  합성(Interface Synthesis)

고수준 컴퓨터 프로그랙밍 언어에서 설계물은 함수로 기술된다. 함수의 호출과 반환 그리고 지역 및 전역 변수의 운용은 해당 언어에서 정해진 규칙을 따른다. C 언어에서 합성해낸 RTL 설계물 역시 작동의 시작과 끝이 있다. 입력으로 유효한 데이터가 제공되는 시점과 유효한 출력의 시점을 클럭 단위로 표시한다. 이를 핸드 쉐이크(hand-shake) 절차라 한다. 외부의 설계 모듈과 데이터를 주고받을 준비(ready)가 되어 있음을 수동적으로 표시하거나 능동적으로 요청(request) 하는 특별한 신호가 필요하다. 입출력 데이터와 교환방식의 규정을 인터페이스(interface) 라한다.

인터페이스 합성은 RTL 설계물이 인접 모듈과 데이터 및 주고 받는 절차(프로토콜 protocol)에 필요한 제어 신호를 포함한 입출력 포트들을 생성해 낸다. 블럭 수준의 입출력 프로토콜, 포트 입출력 프로토콜의 제어방법을 배우게 된다. 가령 외부의 메모리에 접근 하려면 데이터 외에 제어신호가 필요하다. 데이터를 가져오기 위해 주소를 미롯한 읽기 및 쓰기 제어 신호가 선행 되어야 한다. 선입선출(FIFO) 방식이나 AXI4-스트림은 저마다 표준화된 접근 절차를 가지고 있다. 인터페이스 합성은 어떤 입출력 방식을 사용할 것인지 정해 주기만 하면 함수의 데이터 패스와 함께 최적화된 입출력 프로토콜을 생성해 준다.

4. 임의 정밀도 자료형(Arbitrary Precision Types)

HLS 도구들은 C 언어에서 규정된 고유 자료형 이외에 비트 단위로 비트폭을 선언하고 고정 소수점 비트 위치를 지정할 수 있는 임의 정밀도  자료형을 제공한다. 

C 언어는 고유한 자료형을 사용한다. 고유 자료형들은 저마다 표현할 수 있는 값의 범위, 표현 방법들이 언어의 표준으로 고정되어 있다. 예를 들어 문자형, 단정도 정수형, 배정도 부동 소숫점 형은 각각 8, 16, 64 비트폭을 가지며 비트 위치 마다 의미가 규정되어 있다. 이런 규정은 높은 추상화 수준에서 자료형을 일일이 지정하는 번거로움을 덜어주고 오버플로우 같은 계산상 오류를 표준화 해줌 으로써 적절한 자료형의 선택을 수월케 한다. 이에 비해 RTL의 하드웨어 기술은 자료형의 표준은 없다. 다만 2진수 비트 단위의 상세만 있을 뿐이다. C 코드 알고리즘이 적용될 분야에 따라 최적의 비트폭을 갖는 자료형이 선택해야 한다. 실수 연산에 높은 추상화 수준의 부동 소숫점 자료형을 선택할 수 있으나 이를 바로 RTL에 적용하기에는 지나치게  정교하다. 따라서 알고리즘을 C 코드로 검증 하는 단계에서 부터 적절한 자료형을 적용하여 최적의 RTL 하드웨어를 얻을 수 있도록 한다.

임의 정밀도 자료형을 사용하면 C 고유 자료형에 비해 정밀도를 희생 하게 되므로 충분한 검증이 이뤄져야 한다. 적용된 분야에서 규정된 정밀도 허용범위를 만족하면서 하드웨어의 크기와 계산에 소요될 시간(클럭 수)을 최적화 시킬 수 있다.

5. 설계물 분석(Design Analysis)

단번에 C 코드에서 원하는 최적 RTL 결과를 얻는 경우는 매우 드물다. HLS 도구들은 매우 복잡한 하드웨어 합성을 수행하기 때문이다. 

높은 추상화 수준에서 가장 낮은 추상화 수준으로 변환은 매우 다양한 결과를 낼 수 있다. 추상화 수준 변환기의 한 예로 C 컴파일러가 있다. GCC 컴파일러의 옵션을 나열한 문서만 해도 수십쪽이 넘는다. [GCC compiler options summary] 동일한 실행방식인 소프트웨어의 추상화 수준 변환에도 이렇게 다양한 옵션이 있으며 변환된 결과에 커다란 영향을 미친다.

C 컴파일러는 인간이 읽을 수 있는 C 문서에서 기계가 읽을 수 있는 2진 코드로 변환한다. 2진 기계코드의 실행방식은 C 언어와 같은 순차적 실행이다. 하물며 실행 방식이 완전히 다른  RTL은 단순치 않다. RTL은 병렬 실행을 원칙으로 코딩 스타일에 따라 순차 실행 부분을 기술할 수 있다. 인간의 문서(human readable)'에서 '기계의 문서(machine readable)'로 변환을 '구문 통역(translation)'이라 한다면 실행방식의 변경이 동반되는 경우 '합성(synthesis)'이라 한다. '합성'은 더 많은 추론이 필요하며 숨겨진 코드를 생성한다. 높은 추상화 문서에서 함수의 호출과 반환을 구체적으로 기술되지 않지만 이를 수행하기 위해 컴파일러에 의해 추가되는 기계 코드들(push-pop 과 call-return 같은)이 있다. 인터페이스 합성기는 외부의 모듈과 데이터를 주고받기 위한 핸드 쉐이크 프로토콜(handshake protocol)을 생성하여 설계물에 포함 시킨다.

최적의 고위 합성의 결과를 얻으려면 생성된 RTL 설계물을 분석하여 효과적인 옵션을 찾아야 한다. 이때 고려할 사항으로 소요된 하드웨어 자원의 규모(size 또는 area), 가장긴 지연 경로(delay path), 소요된 클럭의 갯수(clock latency)들이 포함 된다. 이는 기능(functional)의 유효성과는 다른 물리적(physical) 수준의 검증이다.

C로 기술된 이산 코사인 변환 discrete cosine transform(DCT)을 가지고 RTL 합성 후 생성된 하드웨어를 분석해 보기로 한다. 분석을 바탕으로 합성 옵션을 달리하여 상이한 병렬 구조를 갖는 하드웨어가 생성될 수 있음을 보게 될 것이다. 이 과정에서 최적의 결과를 찾도록 한다.

C 컴파일러의 경우 엄청난 종류의 옵션이 있으나 대부분 표준 기본값이 정해져 있다. 특별한 경우가 아니면 대부분 조정하지 않는다. RTL 합성기는 옵션의 종류가 다양하지 않지만 각각이 결과에 미치는 영향이 매우 크므로 정확한 분석과 적용이 요구된다. 일단 C 수준에서 기능은 검증 되었으므로 이 단계의 설계 분석은 생성된 하드웨어의 분석(크기와 지연)에 집중 한다.

6. 설계물 최적화(Design Optimization)

행렬 곱셈기를 예제로 삼아 두가지 최적화 기법을 다뤄본다. 행렬 곱셈은 디지털 신호처리, 영상처리, 인공 지능등 여러 방면에 두루 사용되는 수학적 도구로서 매우 많은 곱셈과 덧셈 계산을 포함한다. 다행히도 단위 계산이 반복적인 특징을 가지고 있어서 병렬처리 구조로 꾸미기 수월하다. 설계 최적화는 설계물의 하드웨어 구조를 선택하는 기법을 다룬다. 고위 언어에서 가장 빈번한 반복 구문(for-loop 같은)을 다수의 동일 구조의 연산기를 직렬로 배치하는 파이프라인(pipeline) 병렬처리로 할 것인가 아니면 단일 연산기를 반복 사용하는 FSM(Finite State Machine) 제어기로 할 것인지 결정 한다. 이 결정에는 설계분석 후 설계요구도(specification)를 만족하는지 여부에 달렸다. 설계분석 후 합성 옵션의 변경에도 요구사양을 맞추지 못한다면 최초 C 코드의 수정이 불가피 할 때도 있을 것이다. 합성으로 얻은 RTL과 원 C코드를 비교하여 수정 위치를 정확하게 특정 함으로써 설계시간을 줄이고 수정으로 인한 오류를 최소화 할 수 있다.

7. RTL 검증(RTL Verification)

C 코드로 부터 생성된 RTL 설계물을 검증한다. 자동화된 합성기의 무결성을 믿고 싶지만 버그 없는 소프트웨어는 없다. 게다가 버그로 발생한 피해를 책임지는 툴 벤더도 없다. 그렇다고 의심만 할 수는 없으므로 검증이 필요하다. 다행히 자동화된 검증 도구들은 C 코드를 검증할 때 사용된 시험환경을 그대로 들여와 생성된 RTL을 시험할 수 있게 되었다. 추상화 수준 뿐만 아니라 언어와 구문 실행방식 조차 서로다른 설계물을 한 시뮬레이션 환경에서 수행 가능하다. 이를 CoSimulation 이라한다. 이 단계 실습은 C 로 작성된 테스트 벤치로 부터 자동화된 RTL 검증 절차를 보게될 것이다. 시뮬레이션 도구로 자일링스 비바도 시뮬레이터 XSim 과 멘토 그래픽스 사의 ModelSim을 사용 할 수 있다.

인터페이스 시뮬레이션은 파형을 살펴봐야 하겠으나 기능 검증은 대규모 기준값(golden-value)이 동원된다. 대규모 계산 입출력 값을 수동으로 비교하고 확인 하는 절차는 반드시 자동화 되어야 한다.

시스템 수준 설계라면 버스 규격 또한 만만치 않게 복잡하다. 특히 멀티 마스터 시스템 버스는 더욱 그렇다. 설계물이 이런 시스템의 한 부분을 차지할 목적이라면 인터페이스 검증시 파형을 살펴보는 경우는 거의 없을 것이다. 버스 기능 모델 BFM (Bus-Functio Model)이 제공되고 검증 상태를 메시지로 보는 표명 기반 검증(Assertion-Based Verification)이 효과적이다.

8. HLS IP 통합(Using HLS IP in IP Integrator)

고위 합성을 통해 생성된 RTL 설계물을 IP로서 패키지화 하는 방법을 다룬다. 패키지화 된 IP는 다른 시스템 설계 도구에서 라이브러리로 재사용 될 수 있다. 비바도 IP 카탈로그에 추가되어 비바도 디자인 스위트(Vivado Design Suite) 내에서 사용될 수 있다.

9. HLS IP 를 Zynq SoC 설계에 적용 하기 (Using HLS IP in a Zynq SoC Design)

HLS IP블럭은 Zynq®-7000 SoC 설계에 활용된다. 고위 합성으로 생성된 하드웨어 설계 블럭을 Zynq 시스템 프로세서에 통합하고 C 언어로 구동 소프트웨어(device driver)를 생성 시키는 법을 다룬다.

SoC 설계는 고성능 프로세서를 포함한다. IP화된 HLS 설계 블럭은 프로세서의 주변장치로 시스템에 통합 될 것이다. 아울러 주변장치 하드웨어를 구동하기 위한 소프트웨어가 필요하다. 시스템 프로세서의 버스의 프로토콜이 표준화 되어 있으므로 이를 구동하기 위한 구동 소프트웨어의 기본 구동 루틴은 자동 생성된다.

10. Using HLS IP in System Generator for DSP

고위합성으로 생성된 RTL 설계물을 자일링스 시스템 제네레이터(System Generator for DSP)에서 사용될 수 있도록 패키지화 하는 법을 배운다.

튜토리얼에 사용된 소프트웨어

이 튜토리얼은 자일링스 비바도 디자인 스위트 2017.1 이후 버젼을 적용한다.

튜토리얼을 수행할 컴퓨터의 요구사항

자일링스 비바도 디자인 스위트를 사용하려는 컴퓨터는 적어도 2GB 이상의 메모리 용량이 필요하다.

튜토리얼의 예제 파일들을 얻을 수 있는 곳

튜토리얼에 사용할 디자인 파일은 자일링스 웹 사이트를 통해 얻을 수 있다.

Vivado Design Suite Tutorial High-Level Synthesis UG871 (v2020.1) August 7, 2020
PDF / Design Files

--------------------------------------------------------------------------------------------
고위 합성 튜토리얼(High-Level Synthesis Tutorial)