목차:
1. 개요
2. Q01. Space Invader 게임을 알고 있을까?
3. Q02. 테스트벤치를 만들라!
4. Q04. 그래픽 화면을 보여다오!
5. Q05. SDL2를 써서 비디오 게임 시뮬레이션을 시각화 하라
6. Q06. 포탄 발사!
7. Q07. 대형 아케이드 게임으로 대대적 확장
8. Q08. 게임 재미를 위해 외계인 반격
9. Q09. 테스트벤치를 SystemC 로 바꾸자
과제1:
과제2:
10. Q09f. 오류를 시인하는 인공지능
11. Q09g. DPI-C 대 SystemC
12. FPGA 검증... (계속)
13. ETRI050 합성 및 검증... (계속)
-----------------------------------------------------------
주의:
- 이 글을 모두 이해하려 하지 말고 끝까지 읽을 것
- 실습(따라하기)는 능력껏 실시할 것
- 과제는 반드시 수행할 것
-----------------------------------------------------------
CC-BY-NC
by GoodKook
-----------------------------------------------------------
개요
요즘 인공지능이 뭐든 다 해준다고 말한다. 인공지능이 컴퓨터 이므로 컴퓨터로 할 수 있는 일은 아주 잘 해낸다. 그중 개발(소프트웨어는 물론 하드웨어 까지)에 초급 개발자는 필요 없다고 공공연하다. 기성세대에게는 인공지능이 제법 신통하게 보일 수 있겠지만 이제 막 공학도의 길에 들어선 입장에서 어떤 느낌이 들까? 설마 인공지능이 알아서 해주니 골치 아프게 공부할 필요 없다는 생각이 들지 않길 바란다. 과연 인공지능은 내 느낌(vibe) 만 듣고도 다 해줄까? 구글의 인공지능 제미니는 바이브 코딩(Vibe Coding)을 이렇게 설명한다.
이 강의는 세상에서 유일한 '내 칩(My Chip)'의 설계가 목표다. 설계는 나의 생각을 컴퓨팅 언어로 기술(묘사)하는 것이다. 결함이 없다고 판단된 묘사를 컴파일(또는 합성과 배치배선)하고 칩 제작용 도면을 생성하는 과정은 자동화 되어 있다. 전자회로 설계 자동화(EDA, Electronics Design Automation) 도구가 충분히 발달한 덕분이다. 이제 그 묘사하기(코딩) 조차 인공지능이 다 해준다고 하니 굳이 이 강의를 더 진행 할 필요도 없을 것 만 같다. 이 강의는 베릴로그(Verilog)라는 하드웨어 언어로 '내 생각'을 기술하고 '내 칩 제작 서비스'를 통해 세상에서 유일한 나의 칩을 얻는 것이다. 앞으로 강의에서 다룰 '내 생각'은 탁구 비디오 게임기다. 설계는 비디오 장치에 게임 화면을 그리고 게임을 수행하는 '알고리즘(탁구공의 움직임과 탁구채의 이동 제어 그리고 게임 규칙)'을 컴퓨팅 언어로 묘사하는 것으로 시작한다. 하드웨어를 묘사하는 컴퓨팅 언어(베릴로그라고 하는)를 배워야 하고 비디오 장치에 그림을 그리는 원리를 알고 있어야 한다. 당장 익혀야 할 사항들이 생겼다. 컴퓨팅 언어(베릴로그, C++), 비디오 장치 등등, 어쩌면 현대 전자공학의 산물들을 접하지 못했더라면 몰랐을 것들이다. 다행히 오늘을 사는 우리는 전자공학이 일궈낸 도구들을 상식으로 알고 질문을 제기하지 않는다[1주차 강의:'2. 상식에 기대어 보자']. 인공지능이 신통하다 하니 귀찮게(공부하기 싫다는 것을 우리는 귀찮다고 치부하고 있지는 않을까?) 한줄 한줄 코딩 할 것 없이 '느낌'을 전달하는 것으로 비디오 게임기 하드웨어 설계라는 목적 달성이 가능할 지 알아보기로 한다. 제니미(구글의 인공지능)에게 '탁구'보다는 조금 복잡한 '우주 침략자(Space Invader)'게임을 만들어 보라고 해봤다.
화면의 좌표에 침략자들(alien)과 방어 포대(cannon)가 점으로 찍힌다. 한 화면이 다 그려지면 그 표시로 frame_tick 가 한번 출력 된다. 위의 시뮬레이션은 겨우 한 화면 분량의 시뮬레이션이다. 발사 버튼이 눌리지 않아서 대포알(bullet)은 나타나지 않고있다.
요즘 인공지능이 뭐든 다 해준다고 말한다. 인공지능이 컴퓨터 이므로 컴퓨터로 할 수 있는 일은 아주 잘 해낸다. 그중 개발(소프트웨어는 물론 하드웨어 까지)에 초급 개발자는 필요 없다고 공공연하다. 기성세대에게는 인공지능이 제법 신통하게 보일 수 있겠지만 이제 막 공학도의 길에 들어선 입장에서 어떤 느낌이 들까? 설마 인공지능이 알아서 해주니 골치 아프게 공부할 필요 없다는 생각이 들지 않길 바란다. 과연 인공지능은 내 느낌(vibe) 만 듣고도 다 해줄까? 구글의 인공지능 제미니는 바이브 코딩(Vibe Coding)을 이렇게 설명한다.
"a software development approach where you build applications using plain natural language instead of writing manual syntax or code line by line."
"수동으로 구문을 작성하거나 코드를 한 줄씩 입력하는 대신, 평이한 '자연어'를 사용하여 애플리케이션을 구축하는 소프트웨어 개발 방식."
Q01. 인공지능은 Space Invader 게임을 알고 있을까?
첫 질문은 무턱대고 Space Invader 를 들이 대봤다.
Q1. Can you write Space Invader game in Verilog RTL? [문답 링크]
제미니는 Space Invader, 이 두 단어에서 무슨 게임 인지 알아낸다. 질문자는 게임의 규칙을 일일이 설명할 필요 없이 '느낌(의도)'를 전달 했을 뿐이다. 급기야 Verilog RTL 에서 질문자의 수준을 간파한다. 하드웨어로 만들려면 수천 줄의 구문을 써야 하고 여러 그래픽 기법(스프라이트)과 제어기(스테이트 머신), 오디오 드라이버 등 많은 자원이 들어 간다며 일단 게임의 기본기만 만들어 주겠단다. 아울러 FPGA로 동기식 디지털 하드웨어를 구현 할 수 있다고 한다. 몇가지 전문용어를 구사한 것을 보면서 질문자가 디지털 하드웨어와 컴퓨팅 시스템을 알고 있다고 판단한 것이 분명하다. 인공지능의 답을 들어보자.
Writing a full, arcade-perfect [Space Invaders](https://www.google.com/search?q=space+invaders&kgmid=/m/0jvd8) game requires thousands of lines of code, covering sprite memory, complex state machines, rendering logic, and audio drivers.
However, we can build a fully functional hardware architecture and the core game logic engine in Verilog RTL. This design implements standard synchronous design principles suitable for synthesis on an FPGA (like a Xilinx or Altera development board).
그러면서 일단 간단한 게임 규칙과 비디오 인터페이스만 구현된 코드를 생성해 주었다.
Below is the implementation of the core Game Logic & Video Interface Engine.
------------------------------
## 💻 Verilog RTL Implementation
space_invaders_engine.v [베릴로그 소스 링크]
소스 코드 중 입출력에 대하여 간단히 설명을 다음과 같이 덧붙였다.
------------------------------## 🛠️ Hardware Integration DetailsTo compile and execute this on physical hardware like an FPGA, wrap this core module with two external components:
* VGA Synchronization Driver: Generates the specific vga_x, vga_y, and video_on timing outputs using standard H-Sync and V-Sync timing specifications.* Sprite RAM Blocks: Rather than using blocky programmatic squares like the baseline code (cannon_draw, invader_draw), map an on-chip ROM file to standard bit-arrays to display pixelated spaceships and retro aliens. [1, 2]
더 도와 줄 수 있다면서 참고 링크도 알려 주었다.
Would you like help with:* Writing the accompanying VGA Sync Timing driver module?* Adding an on-chip ROM/RAM Sprite block to render retro alien textures?* Expanding the configuration for a fully functional score counter?[1] [https://github.com](https://github.com/nikkatsa7/SpaceInvadersFpgaGame)[2] [https://fpgaw0rld.wordpress.com](https://fpgaw0rld.wordpress.com/2016/05/20/space-invaders-fpga-game/)
Q02. 테스트벤치를 만들라!
제미니가 베릴로그 RTL을 제대로 만들었을까 싶어서 테스트 벤치를 요구 했다.
Q2. wrute testbench [문답 링크]
질문에 오타가 있었다. 영어에 서툴다고 판단 했는지 한글로 답변을 준다. 한국인 인줄은 어떻게 알았을까?
다음은 위에서 설계한 space_invaders_engine 모듈을 검증하기 위한 Verilog 테스트벤치(Testbench) 코드입니다. 실제 하드웨어 환경처럼 클럭(Clock)과 리셋(Reset)을 공급하고, 플레이어가 왼쪽/오른쪽으로 움직이거나 미사일을 발사하는 상황을 시뮬레이션합니다. 또한 VGA 컨트롤러가 화면을 스캔하듯 vga_x와 vga_y를 순차적으로 증가시켜 픽셀 출력이 정상적으로 나오는지 확인합니다.
------------------------------## 💻 Space Invaders Testbench Codetb_space_invaders_engine.v [테스트벤치 소스 링크]
자기가 만들어 놓은 테스트벤치이면서 시뮬레이션으로 무엇을 확인해야 하는지 지적까지 한다. 이쯤되면 약간 건방져 보이는데 인간으로서 자격지심이 들었을지도 모른다.
------------------------------## 🔍 시뮬레이션 확인 포인트1. 상태 천이(State Transition): 리셋이 해제되면 rgb가 파란색(3'b001)을 출력하다가, btn_fire가 입력된 직후 다음 화면 스캔부터 검은색 배경(3'b000)과 오브젝트들이 렌더링되는지 확인합니다.2. 미사일 이동: btn_fire를 누르면 bullet_active 신호(내부 레지스터)가 올라가고, 매 프레임마다 bullet_y 좌표가 감소하며 위로 올라가는지 파형(Waveform)으로 검증합니다.3. 픽셀 멀티플렉서: vga_x, vga_y가 외계인 좌표(invader_x, invader_y)나 플레이어 좌표(cannon_x)와 일치하는 구간에서 rgb 신호가 각각 빨간색(3'b100) 또는 초록색(3'b010)으로 정확히 변하는지 봅니다.이 테스트벤치를 구동하기 위해 ModelSim, Vivado Simulator, 또는 EDA Playground 중 어떤 툴을 사용하고 계신가요? 툴에 맞는 시뮬레이션 실행 방법이나 파형(Waveform) 분석에서 확인하고 싶은 특정 신호가 있다면 말씀해 주세요.
제미니가 만들어준 베릴로그 RTL과 테스트벤치를 사용하여 시뮬레이션을 해봤다. 소스 코드는 전혀 손대지 않았다.
$ cd ~/ETRI050_DesignKit/Project/MyChip_Games/space_invader_by_Gemini/Q.02_Space_Invaders_in_Verilog_TB$ make run
제미니는 상용 시뮬레이터를 언급 했지만 오픈-소스 베릴로그 시뮬레이터 Icarus 를 사용 했다. 다음과 같은 출력을 보여준다.
./tb_space_invaders_engineVCD info: dumpfile tb_space_invaders_engine.vcd opened for output.[STATUS] 시스템 리셋 해제 - START 상태 진입[STATUS] Fire 버튼 입력 - PLAY 상태로 전환 완료[ACTION] 오른쪽 이동 버튼(btn_right) 활성화[ACTION] 미사일 발사(btn_fire) 활성화[MONITOR] Time: 1602140000 | Coord: (50, 50) | RGB Output: 100 (Invader)[MONITOR] Time: 1602180000 | Coord: (52, 50) | RGB Output: 100 (Invader)[MONITOR] Time: 1602220000 | Coord: (52, 50) | RGB Output: 100 (Invader)[MONITOR] Time: 1602260000 | Coord: (54, 50) | RGB Output: 100 (Invader).....[MONITOR] Time: 14349220000 | Coord: (328, 448) | RGB Output: 010 (Cannon)[MONITOR] Time: 14349260000 | Coord: (328, 448) | RGB Output: 010 (Cannon)[MONITOR] Time: 14349300000 | Coord: (330, 448) | RGB Output: 010 (Cannon)....[MONITOR] Time: 18889300000 | Coord: (230, 65) | RGB Output: 100 (Invader)[MONITOR] Time: 18889340000 | Coord: (230, 65) | RGB Output: 100 (Invader)[STATUS] 테스트벤치 시뮬레이션 완료tb_space_invaders_engine.v:111: $finish called at 24006960000 (1ps)
게임에 등장하는 객체들(외계 침략자, 대포, 총알)이 그려질 화면의 좌표가 문자 메시지로 출력 되었다. 디지털 회로의 시뮬레이션 이므로 파형(waveform)을 볼 수 있다. 파형으로 제미니가 알려준 시뮬레이션 확인 포인트를 알 수 있나?
$ make wave
화면의 좌표에 침략자들(alien)과 방어 포대(cannon)가 점으로 찍힌다. 한 화면이 다 그려지면 그 표시로 frame_tick 가 한번 출력 된다. 위의 시뮬레이션은 겨우 한 화면 분량의 시뮬레이션이다. 발사 버튼이 눌리지 않아서 대포알(bullet)은 나타나지 않고있다.
Q04. 그래픽 화면을 보여다오!
명색이 비디오 게임인데 좌표나 디지털 파형으로는 무려 640x480 화소점 크기의 화면이 제대로 작동하는지 확인하기는 불가능하다. 점 한개를 찍는데 1클럭이 사용되고 있으므로 한 VGA 화면을 위해 30만개 이상의 클럭을 사용하고 있다.
Q4. Space Invader game is graphic arcade game. So the testbench must display graphic output. How do you recomend ? [문답 링크]
제미니는 이에 동의 한다면서 눈으로 확인 가능하려면 그래픽 출력을 추천한다.
하드웨어(Verilog RTL)나 시스템 모델(SystemC)로 게임을 설계할 때, 파형(Waveform)의 0과 1 신호만 보고 그래픽 게임이 정상 동작하는지 검증하는 것은 매우 어렵습니다.
[Space Invaders](https://www.google.com/search?q=space+invaders&kgmid=/m/0jvd8) 같은 그래픽 아케이드 게임을 검증할 때 시뮬레이션 도중 또는 종료 후 눈으로 그래픽 출력을 직접 확인할 수 있는 3가지 실무적 방법을 추천합니다.
시뮬레이션을 실시하는 컴퓨터는 이미 훌륭한 그래픽 장치와 여러 라이브러리(소프트웨어)를 갖추고 있으니 이를 활용하라면서 추천한 방법들은 아래와 같다.
------------------------------## 1. OpenCV 라이브러리 연동 (가장 추천 🌟)SystemC는 C++ 기반이므로, 강력한 이미지 처리 라이브러리인 OpenCV를 테스트벤치 코드에 직접 링크할 수 있습니다.* 동작 원리: SystemC 테스트벤치 내부에 화면 해상도(예: 128x64 또는 640x480) 크기의 cv::Mat 이미지 버퍼를 생성합니다. RTL이나 모델이 픽셀 데이터를 보낼 때마다 해당 버퍼의 픽셀 색상 값을 업데이트합니다.* 시각화 방식:* 실시간 확인: cv::imshow() 함수를 사용하면 시뮬레이션이 돌면서 실시간으로 외계인과 우주선이 움직이는 윈도우 창이 띄워집니다.* 녹화 확인: cv::VideoWriter를 사용하면 시뮬레이션 전체 과정을 .mp4나 .avi 동영상 파일로 저장하여 검증 보고서에 첨부할 수 있습니다.## 2. 가상 프레임 버퍼를 PPM/BMP 이미지 파일로 덤프 (단순함 🖼️)외부 라이브러리(OpenCV) 설치가 까다롭거나 제한된 환경(서버/터미널 환경)이라면, C++ 표준 파일 입출력(std::ofstream)만을 이용해 PPM(Portable Pixmap) 또는 BMP 파일로 저장하는 방법입니다.* 동작 원리: 테스트벤치 내부에 2차원 배열 배열(char frame_buffer[Y][X])을 잡고 프레임 데이터를 모읍니다.* 시각화 방식: VGA의 V-Sync(수직 동기화) 신호가 오거나 한 프레임 렌더링이 끝나는 시점에 해당 배열을 이미지 파일 포맷 헤더 규격에 맞게 파일로 출력합니다. (frame_001.ppm, frame_002.ppm 형태)* 시뮬레이션 종료 후 생성된 이미지들을 연결하면 애니메이션처럼 게임 진행 상황을 컷 단위로 확인할 수 있습니다.## 3. ModelSim / QuestaSim의 "Virtual Memory Window" 기능 활용 (EDA 전용 🛠️)깃허브 예제처럼 게임 내부에 **화면 데이터를 담는 비디오 RAM(VRAM)**을 별도의 레지스터 배열이나 메모리로 설계한 경우에 쓸 수 있는 방법입니다.* 동작 원리: EDA 시뮬레이터(ModelSim 등)는 시뮬레이션 내부의 2차원 메모리 배열을 이미지로 해석해 주는 자체 뷰어 기능을 제공합니다.* 시각화 방식: 시뮬레이터를 멈추어 둔 상태(Freeze)나 실행 중에 VRAM 배열을 우클릭한 뒤 "View as Image" 혹은 **"Memory Grid View"**를 선택하면, 현재 VRAM에 저장된 흑백/컬러 도트 맵이 시뮬레이터 내부 UI 창에 그대로 시각화됩니다.
세가지 방법과 동작원리 설명을 붙여 놓긴 했는데 낮설기 그지없다. 구체적인 예시를 보여주긴 했는데 OpenCV 라는 그래픽 라이브러리를 사용하는 경우다. OpenCV 라고?
------------------------------## 💡 구체적인 구현 예시 (OpenCV 연동 예제 소스코드)만약 1번(OpenCV) 방식을 사용한다면 SystemC 모니터 프로세스를 아래와 같이 직관적으로 확장할 수 있습니다.#include <opencv2/opencv.hpp>#include <systemc.h>// SystemC 모니터 모듈 내부의 일부 예시void tb_space_invaders::vga_display_vulkan() {// 128x64 해상도의 흑백(기본 8비트 1채널) 가상 스크린 생성cv::Mat virtual_screen = cv::Mat::zeros(64, 128, CV_8UC1);while(true) {wait(clk.pos());// 가상 GLCD 혹은 VGA 인터페이스 신호를 모니터링하여 픽셀 매핑if (lcd_write_en.read() == true) {int x = lcd_x_addr.read().to_int();int y = lcd_y_addr.read().to_int();// 픽셀이 켜지면 흰색(255), 꺼지면 검은색(0)virtual_screen.at<uchar>(y, x) = (lcd_data.read() == 1) ? 255 : 0;}// V-Sync 혹은 주기적 타이밍에 화면 리프레시 (예: 60Hz 마다)if (frame_tick.read() == true) {// 화면이 너무 작으면 눈에 안 보이므로 4배 확대하여 출력cv::Mat resized_screen;cv::resize(virtual_screen, resized_screen, cv::Size(), 4.0, 4.0, cv::INTER_NEAREST);cv::imshow("Space Invaders 하드웨어 시뮬레이션 창", resized_screen);cv::waitKey(1); // 1ms 대기하며 윈도우 이벤트 처리}}}
그러면서 어떤 방식을 선호하는지 묻는다. 여러 그래픽 방식 중 구체적으로 제시하지 않은 까닭에 제안만 했던 것이다. 그러면서 어느 뭔가 해줄 수 있다고 한다.
가장 시도해보고 싶으신 시각화 방식은 몇 번인가요?* 만약 1번이나 2번 C++ 그래픽 파일 출력 방식에 관심이 있으시다면, 참조하신 GoodKook 저장소 환경에 곧바로 붙여서 빌드할 수 있도록 Makefile 수정 팁과 구체적인 파일 저장 C++ 함수를 작성해 드릴 수 있습니다.
답변에 GoodKook의 깃허브 저장소에 있는 방식을 해주겠단다. 벌써부터 제미니는 질문자(GoodKook)를 이미 파악하고 있다.
Q05. SDL2를 써서 비디오 게임 시뮬레이션을 시각화 하라
여러 그래픽 처리 방법 중에서 SDL을 특정해서 요구했다.
SDL(Simple DirectMedia Layer)은 게임 및 멀티미디어 애플리케이션 개발을 위한 크로스 플랫폼 오픈소스 개발 라이브러리입니다. 운영체제(OS)마다 다른 로우 레벨 하드웨어 제어 방식을 하나로 추상화하여 API 형태로 제공합니다. 개발자가 코드를 한 번만 작성해도 Windows, macOS, Linux, iOS, Android 등 다양한 플랫폼에서 구동되는 프로그램을 쉽게 만들 수 있도록 돕습니다.
이제부터 한글로 질문을 해보겠다.
Q5. space_invaders_engine의 베릴로그 테스트벤치에 SDL을 사용하여 시각화 할 수 있도록 할 것 [문답 링크]
문법과 문장 실행 방식이 분명한 차이가 있으므로 이종 컴퓨팅 언어 사이에 소스 코드 수준에서 결합될 수 없다. 컴파일된 라이브러리의 함수(API)를 호출하도록 한다. 윈도우즈 시스템에서는 이를 DLL(Dynamic Linking Library), 리눅스는 so(shared object) 라고 한다. 하드웨어 시뮬레이션 테스트벤치에 외부의 C,C++등으로 제작된 라이브러리를 불러오기 위한 규정을 두고 있는데, 베릴로그는 PLI/VPI, 시스템베릴로그(SystemVerilog)는 DPI-C라고 한다. 설계 복잡도가 증가하면서 이미 구축된 라이브러리를 활용한 시스템 수준 테스트벤치 기법은 필수다. 제미니는 DPI-C를 추천하고 있다.
순수 Verilog 테스트벤치(RTL) 환경에서 실시간 그래픽을 시현하려면, Verilog의 DPI-C (Direct Programming Interface)를 사용하여 C/C++ 표준 라이브러리 및 SDL2 기능을 Verilog 함수처럼 직접 호출해야 합니다. 이 방식을 사용하면 SystemC를 거치지 않고도 ModelSim, QuestaSim, Vivado Simulator, VCS 또는 Verilator(C++ wrapper 형태) 등에서 Verilog 테스트벤치가 실행되는 동안 실시간으로 창이 뜨며 게임 화면이 시현됩니다. 이를 구현하기 위한 DPI-C 연동 C++ 모듈, 수정된 Verilog 테스트벤치, 그리고 Verilator 및 일반 시뮬레이터용 빌드 가이드입니다.
C++로 작성한 그래픽 라이브러리 구동용 소스코드다.
------------------------------## 💻 1. SDL2 구동용 DPI-C 소스 코드 (sim_display.cpp)Verilog 테스트벤치에서 픽셀 정보를 넘겨받아 SDL2 창에 실시간으로 매핑해 주는 C++ 인터페이스 파일입니다.
C++ 의 함수 호출이 포함된 베릴로그 테스트벤치다.
------------------------------## 💻 2. DPI-C 인터페이스가 적용된 Verilog 테스트벤치 (tb_space_invaders.v)테스트벤치 최상단에서 C++ 함수들을 임포트(Import)하여 사용합니다. space_invaders_engine의 lcd_x, lcd_y 주소와 lcd_write_en 신호 타이밍에 맞추어 C++ 픽셀 버퍼에 데이터를 기록하고, 전체 화면 스캔이 끝날 때마다 화면을 리프레시합니다.
이종 언어로 구성된 하드웨어 테스트벤치를 컴파일 하여 시뮬레이터를 빌드 하려면 다소 까다로운 절차가 필요하다. 베릴로그를 C++ 로 변환해 주는 오픈-소스 도구 Verilator를 사용하여 단일의 실행 파일을 만들 수 있다. 또는 상용 시뮬레이터(ModelSim / QuestaSim)는 단일 환경이지만 각각 별도 오브젝트(바이너리) 수준에서 상호 호출 하는 방식이다. 이종 언어를 결합하려면 컴파일러의 명령줄 옵션이 꽤나 복잡하고 길다. 제미니는 친절 하게도 두 도구를 사용한 명령줄 옵션을 알려 주었다.
------------------------------## 🛠️ 3. 빌드 및 컴파일 명령어 가이드Verilator를 사용하여 이 DPI-C 융합 Verilog 테스트벤치를 가동하고 단독 실행 바이너리로 뽑아내는 최적화 컴파일 명령어 세트입니다.# 1. Verilator를 사용하여 Verilog와 C++ DPI 소스를 결합하고 컴파일 환경 빌드# --binary 플래그는 Verilator가 스스로 main 소스를 생성하여 자체 바이너리를 뽑아내도록 유도합니다.verilator --binary -Wall -Wno-fatal \space_invaders_engine_glcd.v \tb_space_invaders.v \sim_display.cpp \-LDFLAGS "$(sdl2-config --libs)" \-CFLAGS "$(sdl2-config --cflags) -std=c++17" \--top-module tb_space_invaders \--Mdir obj_dir# 2. 빌드가 완료되면 생성된 독자 실행 파일을 실행합니다../obj_dir/Vtb_space_invaders** ModelSim / QuestaSim 유저인 경우 실행 방법:# C++ 코드를 공유 라이브러리(.so)로 빌드한 뒤 vlog/vsim에 링크해야 합니다.g++ -shared -fPIC -o sim_display.so sim_display.cpp $(sdl2-config --cflags --libs) -I$MODELSIM_HOME/includevlog space_invaders_engine_glcd.v tb_space_invaders.vvsim -sv_lib sim_display work.tb_space_invaders*
그리고 시뮬레이션에는 별 도움도 않될 말을 덧붙인다. 인공지능은 수다스럽다.
------------------------------## 🎨 실행 결과 아케이드 시현 검증 구조이 아키텍처를 가동하면 별도의 SystemC 래퍼 스케일 작업 없이 RTL 코어 내부의 무한 스캔 루프 주소(scan_x, scan_y)가 실시간으로 DPI 인터페이스에 수 밀리초 단위로 파이프라이닝되면서, 화면이 찢어지는 현상(Tearing) 없이 완벽히 동기화된 복고풍 하드웨어 도트 그래픽이 윈도우 스크린 상에 60Hz급 프레임으로 가볍고 부드럽게 연동 및 표출됩니다.이 DPI-C 통합 구조를 사용하면서 혹시 특정 에뮬레이션 상황을 연출하기 위해 키보드 인터럽트 입력 핸들러(SDL_PollEvent에서의 키 입력)를 역방향으로 RTL 버튼 입력(btn_left, btn_right)에 실시간 피드백 맵핑하는 고도화 과정도 추가해 드릴까요?
제미니가 작성해준 소스 코드와 명령으로 시뮬레이터를 빌드해보자. Verilator를 사용하여 시뮬레이터를 빌드하고 실행하는 쉘 스크립트 run.sh 아래와 같다.
# 1. Verilator를 사용하여 Verilog와 C++ DPI 소스를 결합하고 컴파일 환경 빌드# --binary 플래그는 Verilator가 스스로 main 소스를 생성하여 자체 바이너리를 뽑아내도록 유도합니다.verilator --binary -Wall -Wno-fatal \space_invaders_engine_glcd.v \tb_space_invaders.v \sim_display.cpp \-LDFLAGS "$(sdl2-config --libs)" \-CFLAGS "$(sdl2-config --cflags) -std=c++17" \--top-module tb_space_invaders \--Mdir obj_dir# 2. 빌드가 완료되면 생성된 독자 실행 파일을 실행합니다../obj_dir/Vtb_space_invaders
명령줄에서 쉘 스크립트를 실행한다. 게임 화면을 볼 수 있다! 그런데 외계 우주인과 대포가 민밋한 사각형이다. 첫 질문에서 제미니가 스프라이트(sprite ROM) 등 하드웨어 자원이 많이 들어가는 부분은 제외한 단순 게임 규칙을 기술한 RTL이었다는 점을 상기한다.
$ cd ~/ETRI050_DesignKit/Project/MyChip_Games/ \space_invader_by_Gemini/Q.05_Visulization_with_SDL2
$ source run.sh
Q06. 포탄 발사!
제미니가 우주 침략자 게임기를 이해한 줄 알았는데 정작 스페이스 바를 눌러도 포탄이 발사되지 않는다. '느낌' 전달이 안된 모양이다. 포탄을 발사하는 코드를 요구했다.
Q6a. 외계인의 공격을과 키보드를 사용하여 총알 발사를 구현하라. 베릴로그 테스트벤치를 보여달라 [문답a 링크]
베릴로그 RTL은 제대로 만들었지만 테스트벤치와 DPI-C 코드가 제대로 연결되지 않았다는 변명을 한다.
DPI-C 소스 코드(sim_display.cpp)에서 SDL2 키보드 이벤트 이웃풋을 Verilog 테스트벤치로 전달(Export)받아, 하드웨어 입력 핀(btn_left, btn_right, btn_fire)을 실시간 제어할 수 있도록 완전히 확장한 Verilog 테스트벤치(tb_space_invaders.v) 코드입니다. 추가로 외계인이 플레이어를 향해 무작위로 미사일을 투하하는 로직(외계인 공격)도 테스트벤치 레벨에서 모니터링하기 좋게 결합했습니다.------------------------------## 💻 DPI-C 양방향 제어가 적용된 Verilog 테스트벤치 (tb_space_invaders.v)
새 테스트벤치와 DPI-C를 연동 시키기 위해 C++ 함수를 수정 하라고 한다.
------------------------------## 💻 4. 연동을 위해 업데이트가 필요한 DPI-C 파일 (sim_display.cpp)위 테스트벤치에서 호출하는 dpi_poll_keyboard 함수가 실제 호스트 PC의 키보드 입력을 캐치할 수 있도록 C++ 소스에 아래의 키 이벤트 폴링 함수를 보완해 주어야 합니다.// sim_display.cpp 내부에 추가/수정해야 할 키보드 감지 함수 예시extern "C" void dpi_poll_keyboard(unsigned char* out_left, unsigned char* out_right, unsigned char* out_fire) {SDL_Event event;// 키 상태를 고정적으로 유지하기 위해 스태틱 변수 활용 또는 SDL_GetKeyboardState 사용 가능const Uint8* state = SDL_GetKeyboardState(NULL);// 기본 이벤트 큐 비우기 (창 닫기 이벤트 등의 안전장치)while (SDL_PollEvent(&event)) {if (event.type == SDL_QUIT) {SDL_Quit();exit(0);}}// SDL2 실제 키 매핑 상태를 Verilog 아웃풋 포인터에 다이렉트로 전달// 1이면 버튼 눌림(High), 0이면 버튼 뗌(Low)*out_left = state[SDL_SCANCODE_LEFT] ? 1 : 0;*out_right = state[SDL_SCANCODE_RIGHT] ? 1 : 0;*out_fire = state[SDL_SCANCODE_SPACE] ? 1 : 0;}
인공지능이 이래라 저래라 한다. 감히! DPI-C의 C++ 소스코드를 전부 보여달라고 주문했더니 그제서야 만들어준다.
Q6b. 이 테스트벤치와 연동되는 sim_display.cpp 전체 통합 소스 코드가 필요하다. [문답b 링크]
이쯤 되면 인공지능 의존도가 높아지기 시작한다.
Verilog 테스트벤치(tb_space_invaders.v)와 완벽하게 기계적으로 맞물려 돌아가는 sim_display.cpp 전체 통합 소스 코드입니다. 이 코드는 실시간으로 화면을 그려주는 그래픽 엔진 역할과 동시에, 호스트 PC의 키보드 입력(좌/우 방향키, 스페이스바) 상태를 낚채어 Verilog의 btn_left, btn_right, btn_fire 신호선으로 실시간 피드백해 주는 양방향 DPI-C 매커니즘이 구현되어 있습니다.------------------------------## 💻 sim_display.cpp 전체 통합 소스 코드
게다가 인공지능은 유혹까지 서슴지 않는다.
------------------------------## 🚀 컴파일 및 구동 최종 점검 명령어이제 프로젝트 디렉터리에 space_invaders_engine_glcd.v, tb_space_invaders.v, sim_display.cpp 파일 3개가 한 곳에 완비되었습니다. 리눅스 터미널(Ubuntu/WSL)에서 아래 명령어 묶음을 실행하면, C++ 컴파일러 플래그와 SDL2 동적 라이브러리가 Verilator 실행 파일 빌드 아티팩트에 하나로 묶여 컴파일되며 아케이드 에뮬레이터 바이너리가 완성됩니다.모든 설계 인프라가 구현되었습니다. 구동 중 환경 상의 문제로 빌드 에러가 나거나, 외계인 레이아웃의 마리 수 및 대형을 아케이드판 규격 수준인 5행 11열 격자로 대대적으로 확장하고 싶다면 어떤 방향으로 개선을 도와드릴까요?
시뮬레이터를 빌드하고 포탄 발사를 확인해본다. 위의 답변 중 space_invaders_engine_glcd.v는 이전(Q.05)에 생성했던 베릴로그 RTL이다.
$ cd ~/ETRI050_DesignKit/Project/MyChip_Games/\
space_invader_by_Gemini/Q.06_Bullet_Fire
$ source run.sh
verilator --binary -Wall -Wno-fatal \
../Q.05_Visulization_with_SDL2/space_invaders_engine_glcd.v \
tb_space_invaders.v \
sim_display.cpp \
-LDFLAGS "$(sdl2-config --libs)" \
-CFLAGS "$(sdl2-config --cflags) -std=c++17" \
--top-module tb_space_invaders \
--Mdir obj_dir
./obj_dir/Vtb_space_invaders
Q07. 대형 아케이드 게임으로 대대적 확장
대형 아케이드 게임 처럼 대대적 확장을 해주겠다는 제미니의 유혹에 넘어가 봤다.
Q7. 3마리로 배치된 외계인의 개수를 늘려 실제 오락실 게임처럼 외계인 부대 대형(예: 5행 5열 등)으로 Verilog 로직을 리팩토링하라 [문답 링크]
외계인 부대의 대형이 늘어 하드웨어 자원이 증가하는 것을 방지하는 대책까지 고려해 준다고 한다.
[Space Invaders](https://www.google.com/search?q=space+invaders&kgmid=/m/0jvd8)의 상징적인 요소인 외계인 부대 대형(5행 × 5열 = 총 25마리)을 하드웨어로 구현하기 위해 space_invaders_engine_glcd.v 코드를 리팩토링했습니다.하드웨어(Verilog)에서 25마리의 독립된 이동 좌표를 개별 레지스터로 만들면 FPGA 리소스를 엄청나게 낭비하게 됩니다. 따라서 아케이드 기기의 정석적인 설계 기법을 따라 외계인 무리 전체의 기준 좌표(group_x, group_y) 하나만 움직이고, 각 외계인의 생사 여부는 25비트 레지스터(invader_alive)의 비트 맵으로 효율적으로 관리하도록 구조를 대폭 개선했습니다.------------------------------## 💻 리팩토링된 space_invaders_engine_glcd.v (5행 5열 외계인 대형)
변경된 내용을 설명하고 그로부터 얻은 효과(하드웨어 자원 절약)까지 비교 설명 하고 있다.
------------------------------## 🔍 설계 변경 핵심 요약1. 25비트 레지스터 압축 기법: 외계인 25마리 각각의 X, Y 좌표 레지스터를 만들면 총 25 × 13비트 = 325비트의 플립플롭이 낭비되지만, 부대 기준점(group_x, group_y)과 상태 맵(invader_alive 25비트) 구조로 단 38비트만 사용하여 25마리를 완벽히 추적 및 제어합니다.2. 동적 격자 스캔 연단: 화면을 스캔하는 단계(always @(*))에서 현재 스캔 픽셀 좌표(scan_x, scan_y)가 5행 5열의 바운더리 내부인지 역산하여 데이터가 매핑되므로 하드웨어가 매우 가볍게 동작합니다.해당 space_invaders_engine_glcd.v 코드를 저장하신 뒤, 이전 단계에서 최종 빌드했던 verilator 스크립트를 통해 그대로 재컴파일하시면, 128x64 소형 화면에 정렬된 25마리의 외계인 대형 무리가 한 팀이 되어 일사불란하게 좌우로 이동하며 아래로 하강하는 장관을 실시간 SDL 창으로 조작·체험하실 수 있습니다!
외계인을 확장한 게임기를 시뮬레이션 해본다. 게임이 변경되었을 뿐 테스트벤치는 이전(Q.06) 과 동일하다.
$ cd ~/ETRI050_DesignKit/Project/MyChip_Games/\
space_invader_by_Gemini/Q.07_Alien_5x5
$ source run.sh
verilator --binary -Wall -Wno-fatal \
./space_invaders_engine_glcd.v \
../Q.06_Bullet_Fire/tb_space_invaders.v \
../Q.06_Bullet_Fire/sim_display.cpp \
-LDFLAGS "$(sdl2-config --libs)" \
-CFLAGS "$(sdl2-config --cflags) -std=c++17" \
--top-module tb_space_invaders \
--Mdir obj_dir
./obj_dir/Vtb_space_invaders
이제 게임 엔진의 레이아웃이 완성되었습니다. 여기서 더 확장하고 싶으신 부분이 있으신가요?* 외계인들이 무작위로 아래로 미사일을 하강 투하하는 적 공격 로직 추가* 아군 패들이 맞았을 때 차감되는 목숨(Life) 시스템과 점수 스코어 보드 연동* 단순 네모 도트가 아닌 실제 클래식 도트 그래픽을 입히는 Sprite ROM 매핑 설계
Q08. 게임 재미를 위해 외계인 반격
외계인 반격으로 게임하는 재미를 높여 주겠다고 한다.
외계인의 공격을 표현하기 위해 난수 발생기를 넣었다고 한다.
외계인 부대(5행 5열) 중 최하단에 있는 외계인들이 무작위로 아래 방향으로 적 미사일(Invader Bullet)을 투하하는 공격 로직을 추가했습니다. 하드웨어 내부에 외계인 전용 미사일 좌표 레지스터(inv_bullet_x, inv_bullet_y)와 활성화 플래그(inv_bullet_active)를 추가하고, 의사 난수 유도용 카운터를 결합하여 일정 주기마다 살아있는 외계인 위치에서 미사일이 떨어지도록 구현했습니다.------------------------------## 💻 외계인 공격 로직이 탑재된 space_invaders_engine_glcd.v기존 코드의2. 게임 메인 로직과3. 그리기 레이어 판정 부분에 외계인 공격 및 플레이어 피격 판정이 추가된 최종 버전입니다.
베릴로그 RTL로 의사 난수 발생기가 궁금하다. 카운터에 모듈로 연산(%)으로 '무작위'라니 어색하다.
// 💡 하드웨어 의사 난수용 자유 가동 카운터 (추가)
always @(posedge clk)
rand_counter <= rand_counter + 1'b1;
......
always @(posedge clk or negedge rst_n) begin// [D] 💡 외계인 공격 발사 생성 로직 (추가)
if (!inv_bullet_active && (rand_counter[4:0] == 5'h1F))
shoot_col = rand_counter[7:5] % 5; // 0~4열 무작위 선택
...
가장 아래에 위치한 외계인 만이 공격할 수 있도록 했다. 중간에 놓인 외계인이 미사일을 발사하면 팀 킬이 될 수 있다. 인공지능이 제법 똑똑한 척 한다.
### 🎮 추가된 연동 메커니즘1. **지능형 최하단 발사체 선정:** 5개의 열(`shoot_col`) 중 하나가 선택되면, 위에서부터가 아닌 아래 행(`r=4`)에서부터 역순으로 탐색하여 **그 시점에 살아있는 가장 최하단의 외계인** 손끝에서 미사일이 발사되도록 설계했습니다. 죽은 외계인의 공중에서 미사일이 생겨나는 버그를 완벽히 차단합니다.2. **피격 판정 연결:** 적 미사일이 플레이어 좌표(`cannon_x`) 영역 내에 침범하면, 상태 머신이 즉시 `STATE_OVER`로 변환되며 화면 전체가 테두리 모드로 변경(Game Over 스크린)됩니다.
새로 생성된 베릴로그 RTL로 시뮬레이션 해봤더니 외계인 공격을 볼 수 없었다. 이유를 따져 물었다.
Q8d. 외계인이 공격하지 않는다 [문답d 링크]
그 이유를 대면서 수정된 RTL를 만들어 준다.
외계인이 미사일을 공격(투하)하지 않는 이유는 rand_counter를 이용한 확률 조건문이 하드웨어(RTL) 루프 상에서 너무 엄격했거나, 25마리 외계인의 생사 조건을 판별하는 로직의 인덱싱 규칙이 맞지 않아 발사 기회를 계속 박탈당했기 때문입니다. Verilator linter 검증을 다시 한번 철저하게 수행하고, 외계인의 미사일 투하 빈도를 체감할 수 있도록 조건 확률을 완화(rand_counter[3:0] == 4'hF)하는 동시에, 5x5 외계인 배열 중 실제 하단에 배치된 외계인의 생존 플래그를 정교하게 트래킹하여 높은 빈도로 미사일을 투하하도록 수정한 완벽한 Verilog RTL 코드입니다.------------------------------## 💻 [수정완료] space_invaders_engine_glcd.v
앞선 코드에서 외계인 공격이 실패한 이유를 설명한다. 변명하는 혀가 길다.
### 🛠️ 공격 실패 요인 수정 포인트 명시* **배열 인덱스 하드웨어 매핑 고정:** `invader_alive[r*5 + shoot_col]` 구문에서 정수형 수식 연산 시 Verilator가 내부 비트 크기를 오인해 생존 비트를 0으로 오판하던 연산 결함을 `shoot_row`와 `shoot_col` 레지스터의 명시적 비트 유도 배정(`(shoot_row * 3'd5) + shoot_col`)으로 원천 교정했습니다.* **난수 모듈로(Modulo) 에러 수정:** `rand_counter` 상위 비트를 `5`로 나눌 때 범위가 튀던 현상을 차단하기 위해 삼항 연산 바운더리 마스킹을 삽입했습니다.
여전히 모듈로 연산이 쓰였다. '의사' 난수라지만 시원찮다. 차라리 LFSR(Linear Feedback Shift Register)는 어땠을까? 외계인 공격을 확인해 보자. 게임 RTL 만 변경되었을 뿐이므로 테스트벤치는 이전 Q.06의 것을 사용한다.
$ cd ~/ETRI050_DesignKit/Project/MyChip_Games/\space_invader_by_Gemini/Q.08d_Alien_Attack_Fix$ source run.shverilator --binary -Wall -Wno-fatal \./space_invaders_engine_glcd.v \../Q.06_Bullet_Fire/tb_space_invaders.v \../Q.06_Bullet_Fire/sim_display.cpp \-LDFLAGS "$(sdl2-config --libs)" \-CFLAGS "$(sdl2-config --cflags) -std=c++17" \--top-module tb_space_invaders \--Mdir obj_dir./obj_dir/Vtb_space_invaders
Q09. 테스트벤치를 SystemC 로 바꾸자
앞선 테스트벤치는 베릴로그 였다. 외부의 그래픽 라이브러리를 사용하기 위해 DPI-C 를 적용하였다. 이번에는 테스트벤치 환경 모두를 SystemC 와 C++ 체계로 옮겨와 본다.
Q9a. import space_invaders_engine.v into SystemC testbench [문답a 링크]
제미니는 베릴로그를 SystemC로 옮겨오는 방법을 알려줬다. Verilator를 사용하라고 한다.
Verilator 환경에서 SystemC 3.0(또는 이전 규격) 테스트벤치를 사용하여 Verilog 모듈인 space_invaders_engine을 인클루드하고 최상위에서 연결(Top-level Binding)하는 방법입니다. Verilator는 Verilog 파일을 컴파일할 때 --sc 옵션을 주면 해당 모듈을 SystemC sc_module을 상속받는 C++ 클래스로 자동 변환해 줍니다. 따라서 SystemC 소스 코드 안에서 외래 모듈(sc_foreign_module) 선언을 할 필요 없이, Verilator가 생성한 헤더 파일을 직접 인클루드(Import)하여 일반 SystemC 모듈처럼 선언하고 신호선을 바인딩하면 됩니다.------------------------------## 💻 1. SystemC 최상위 파일 (sc_main.cpp)Verilator가 변환해 줄 헤더 파일 Vspace_invaders_engine.h를 인클루드하여 가상 디스플레이 모듈(sc_glcd128x64_TLM)과 입력 자극 테스트벤치(sc_invaders_TB)를 유기적으로 연결합니다.
DPI-C에 비하여 테스트벤치 구성의 차이를 설명해줬다. SystemC를 사용하면 '강력한' ESL 검증 환경을 구축할 수 있다고 하는데 그 근거가 궁금하다.
------------------------------## 💡 아키텍처 상의 이점이렇게 SystemC 환경으로 space_invaders_engine.v를 가져오면(Import), 전반적인 하드웨어 설계는 검증된 Verilog RTL 내부 논리 구조를 100% 그대로 유지하면서, 디스플레이 연동이나 스코어 보드 연산, 호스트 인터페이스 같은 복잡한 소프트웨어 성향의 주변 장치들은 SystemC(C++ 기반 SDL2 함수 덩어리)를 통해 매우 자유롭고 가볍게 설계·확장할 수 있는 강력한 ESL(Electronic System-Level) 검증 환경 체계가 구축됩니다.
시뮬레이터 빌드에 필요한 모든 파일들을 만들라고 지시했다.
Q9b. 빌드에 필요한 파일들을 모두 보여달라 [문답b 링크]
필요한 C++ 소스 코드외에 Makefile 까지 작성해 준다. DPI-C에서 없던 가상 LCD 모델을 포함하고 있다는 점에 주목한다.
Verilator를 사용하여 SystemC 3.0 + SDL2 실시간 그래픽 시현 환경을 구축하는 데 필요한 모든 파일의 완성된 전체 소스 코드입니다.프로젝트 디렉터리에 아래 명시된 파일명으로 코드를 각각 저장한 후, 최종 안내해 드리는 Makefile을 이용해 make 명령어를 실행하면 즉시 빌드 및 조작이 가능한 아케이드 게임이 구동됩니다.------------------------------## 📂 1. space_invaders_engine_glcd.v (Verilog RTL 게임 코어)5x5 외계인 격자 대형과 적 미사일 투하 메커니즘, 그리고 128x64 해상도 래스터 스캔 인터페이스가 완벽히 검증된 하드웨어 소스입니다.------------------------------## 🖥️ 2. sc_glcd128x64_TLM.h (가상 LCD 디스플레이 헤더)------------------------------## 💻 3. sc_glcd128x64_TLM.cpp (가상 LCD 디스플레이 소스)1:1 오리지널 도트 매핑(128x64)으로 윈도우 창을 오픈하는 SDL2 구동 본체입니다.------------------------------## 📂 4. sc_invaders_TB.h (SystemC 테스트벤치 제어기 헤더)------------------------------## 💻 5. sc_invaders_TB.cpp (SystemC 테스트벤치 제어기 소스)호스트 PC의 키보드 입력을 비동기 감치하여 SystemC 및 RTL 엔진 포트로 주입해 주는 실시간 자극 드라이버입니다.------------------------------## 🏛️ 6. sc_main.cpp (최상위 연결 스크립트)------------------------------## 🛠️ 7. Makefile (SystemC 3.0 전용 빌드 파일)SystemC 3.0 경로와 C++17 표준 가이드라인을 반영한 통합 자동화 메이크파일입니다.
시뮬레이터 빌드 및 실행은 Makefile.mk,
$ cd ~/ETRI050_DesignKit/Projects/MyChip_Games/\
space_invader_by_Gemini/Q.09b_Import_into_SystemC_All
$ make -f Makefile.mk
......
./obj_dir/Vspace_invaders_engine_glcd: error while loading shared libraries: libsystemc.so.3.0: cannot open shared object file: No such file or directory
시뮬레이터 빌드는 성공 했으나 실행을 위해 libsystemc.so.3.0 를 찾지 못했다고 한다. SystemC 의 실행 라이브러리 경로를 환경변수 LD_LIBRARY_PATH에 추가해 준다.
$ export LD_LIBRARY_PATH=/opt/systemc/lib:$LD_LIBRARY_PATH
$ make -f Makefile.mk
Q9e. 키보드 입력을 처리해 줄 sc_invaders_TB.cpp 의 SystemC 입력 자극 시나리오를 작성하고 임베디드 그래픽 LCD 연동을 완성할 sc_glcd128x64_TLM.cpp 의 SDL2 연동 시현 스레드 보완한 온전한 파일들과 Makefile을 모두 보여달라 [문답e 링크]
테스트벤치의 구성 모듈을 보완한 C++ 다.
호스트 PC의 키보드 조작과 실시간 60Hz 그래픽 디스플레이(128x64 오리지널 해상도), 그리고 Verilator 환경 하에서의 SystemC 3.0 빌드 규칙이 완벽하게 반영된 sc_invaders_TB.cpp, sc_glcd128x64_TLM.cpp 전체 소스 코드와 통합 Makefile입니다. 문법적인 오류나 누락(end 오타 해결, 클래스 구조 정상 매핑)을 완벽하게 해결하고, OS 윈도우 프리징과 키보드 동기화 병목 현상을 방지하도록 정밀하게 보완했습니다.------------------------------## 💻 1. sc_invaders_TB.cpp (완성형 입력 자극 제어)SDL_PumpEvents()를 통해 가상 윈도우 커널로부터 비동기식 하드웨어 키 상태를 읽어와, 매 주기에 맞춰 정확히 SystemC 및 Verilog 핀으로 강제 드라이브하는 완성형 테스트벤치 소스입니다.------------------------------## 💻 2. sc_glcd128x64_TLM.cpp (완성형 그래픽 시현 및 이벤트 보완)Verilog RTL이 밀어내는 래스터 주소 버스를 파이프라이닝하여 수신하고, OS의 창 관리 이벤트 가동 및 조기 종료 처리를 연동해 하얗게 창이 굳어버리는 병목을 완전히 제거한 그래픽 렌더링 소스입니다.------------------------------## 🛠️ 3. Makefile (SystemC 3.0 + Verilator 통합 빌드 파일)최신 2026년 기준 널리 사용되는 현대적인 SystemC 3.0.0 표준 명세 라이브러리 패스와 연동되도록 빌드 플래그를 정비했습니다. C++ 표준 요구 조건인 C++17 옵션을 컴파일러 아티팩트(-CFLAGS)에 엄격하게 지정하여 빌드 누락을 전면 봉쇄한 통합 빌드 자동화 스크립트입니다.
과제1: 개선된 내용을 비교해본다. 두 텍스트 파일을 비교하는 명령은 diff 다.
$ diff -y -W 128 \../Q.09c_Enhance_Keyboard_Stim/sc_invaders_TB.cpp \
./sc_invaders_TB.cpp | less
그리고,
$ diff -y -W 128 \../Q.09d_Enhance_GLCD_TLM/sc_glcd128x64_TLM.cpp \./sc_glcd128x64_TLM.cpp | less
제미니가 생성해준 소스코드는 문법적으로 그리고 논리적으로 완벽하다. 우리는 인공지능이 만들어준 소스 코드 내용을 이해할 수 있을까? 없다면 인공지능의 도움을 받아 개발 생산성을 높인다는 주장에 동의할 수 있을지 생각해볼 일이다. '바이브 코딩'의 효용에 대한 의문이 다양하게 제기되었다. 아래 링크를 읽어보자.
바이브 코딩이 뭔 소용이야, 결국엔 고치려고 개발자한테 돈 줘야 하는데? [보기 링크]
Astra로 코딩하기: 우리는 대체 왜 이러고 있는 걸까? [보기 링크]
우리는 Space Invader 게임을 제작하고자 제미니를 이용하는 중이다. 이 인공지능이 내놓은 소스 코드들은 '완벽' 하다. 문법적 오류가 없으며 논리적 문제도 없다. 간략하지만 자신이 생성한 소스 코드 해설까지 곁들여 준다. 위의 링크를 살펴보고 논의를 시작해 보자. Space Invader 라는 게임의 '느낌'을 가졌다는 것으로 개발(설계) 했다고 할 수 있을까?
$ cd ~/ETRI050_DesignKit/Project/MyChip_Games/space_invader_by_Gemini/\Q.09e_SystemC_Env_Quiz
$ make -f Makefile.mk[BUILD STAGE 1] Verilator 가동 -> Verilog 하드웨어를 SystemC 3.0 C++ 소스로 코딩 이식 복사verilator --sc --exe -Wall -Wno-fatal \-I. \sc_main.cpp sc_glcd128x64_TLM.cpp sc_invaders_TB.cpp space_invaders_engine_glcd.v \-LDFLAGS "-L/usr/local/lib -Wl,-rpath,/usr/local/lib -Wl,--enable-new-dtags -lSDL2 -L/usr/local/systemc-3.0.0/lib-linux64 -lsystemc" \-CFLAGS "-std=c++17 -I/usr/local/include/SDL2 -D_REENTRANT -I/usr/local/systemc-3.0.0/include" \--Mdir obj_dir%Error: Cannot find file containing module: 'space_invaders_engine_glcd.v'... See the manual at https://verilator.org/verilator_doc.html?v=5.051 for more assistance.... Looked in:space_invaders_engine_glcd.vspace_invaders_engine_glcd.v.vspace_invaders_engine_glcd.v.svobj_dir/space_invaders_engine_glcd.vobj_dir/space_invaders_engine_glcd.v.vobj_dir/space_invaders_engine_glcd.v.sv... With current working directory%Error: Exiting due to 1 error(s)make: *** [Makefile.mk:24: compile_and_run] Error 1
시뮬레이터를 빌드하고 실행할 수 있도록 Makefile.mk를 수정하라.
Q09f. 오류를 시인하는 인공지능
인공지능은 약게도 오류를 지적하면 바로 인정하며 사과한다.
Q9f. Verilator 명령줄 아규먼트에 --pins-sc-uint 를 넣어야 한다 [문답f 링크]
마치 오류를 지적해 주어서 고맙다며 인간을 치켜세우는 듯하다. 떠나지 않도록...
맞습니다!--pins-sc-uint 아규먼트는 Verilator가 Verilog의 다중 비트 버스 신호를 SystemC로 번역할 때 매우 중요한 옵션입니다. 이 옵션을 생략하면 Verilator는 7비트나 6비트 버스 신호(lcd_x, lcd_y)를 SystemC 표준 포트 타입인 sc_in<sc_uint<W>> 대신 C++ 기본 자료형인 sc_in<uint32_t>(또는 vluint32_t) 형태로 내보내게 됩니다. 그 결과 앞서 작성했던 sc_main.cpp나 헤더 파일의 sc_signal<sc_uint<7>> 선언과 타입 불일치(Type Mismatch)가 발생하여 심각한 C++ 컴파일 에러가 유발됩니다. 따라서 --pins-sc-uint 옵션을 Verilator 명령줄에 반드시 추가해야 우리가 의도한 정석적인 SystemC 3.0 포트 구조(sc_uint 맵핑)로 빌드가 정상 완료됩니다.------------------------------## 🛠️ --pins-sc-uint가 반영된 최종 수정형 MakefileVERILATOR_FLAGS 변수에 해당 옵션을 확실하게 포함하여 교정한 Makefile 본문입니다.
------------------------------이 중요한 옵션(--pins-sc-uint)까지 적용함으로써 드디어 오류 없는 완벽한 SystemC 3.0 컴파일 인프라가 구축되었습니다! 수정된 Makefile을 통해 툴을 구동했을 때 C++ 빌드가 완벽히 성공하고 실시간 128x64 해상도 게임 창이 정상적으로 팝업되는지 결과가 궁금합니다. 성공적으로 구동이 완료되셨나요?
Q09g. DPI-C 대 SystemC
설계는 목표에 접근하는 과정이다. 설계자는 수많은 방법 중 하나의 선택을 강요받는다. 하드웨어 시뮬레이션 결과의 가시화(visualization)을 위한 그래픽 라이브러리를 들여오기 위해 처음에는 DPI-C를 사용했다. 인공지능이 권했기 때문이다. 문제는 없었지만 굳이 다른 방법 SystemC로 전환한 이유를 찾아보자.
Q9g. 성공적으로 구동이 완료되었다. 이제 앞서 했던 DPI 와 SystemC 방법을 비교하고 장단점에 대하여 논하라
인공지능의 답을 들어보자. 아부부터 시작한다.
성공적으로 빌드가 완료되고 실시간 게임 창이 정상 구동된다니 기쁩니다!하드웨어(Verilog)와 소프트웨어(C++/SDL2) 세계가 정상적으로 결합한 의미 있는 이정표입니다. 이번 프로젝트를 진행하며 직접 빌드하고 조작해 보신 DPI-C 방식과 SystemC 3.0 방식의 구조적 특징을 바탕으로, 실무적 관점에서의 장단점을 일목요연하게 비교 분석해 드립니다.
'일목요연'하게 라니! 인간을 가지고 노는 태도가 여간 아니다. 마치 다 알고 있었다는 투다.
------------------------------## 🏛️ 아키텍처 관점에서의 근본적 차이* DPI-C 방식: Verilog가 주체입니다. 시뮬레이션의 시간 축과 마스터 스케줄링을 Verilog 시뮬레이터가 쥐고 있으며, 그래픽 출력이나 키보드 폴링이 필요할 때만 C 함수를 '플러그인'처럼 찌르는 구조입니다.* SystemC 방식: C++ 커널이 주체입니다. 최상위(sc_main)와 테스트벤치(sc_invaders_TB)가 주가 되어 하드웨어의 클럭 신호선까지 직접 흔들고, Verilog 엔진은 SystemC 생태계 내부의 하나의 '소프트웨어 객체(컴포넌트)'처럼 이식되어 동작합니다.------------------------------## 📊 DPI-C vs SystemC 장단점 요약 비교DPI-C (Direct Programming Interface)장점 (Pros)- 매우 가볍고 직관적임- 빌드 속도가 빠르고 툴 체인이 단순함- Verilog 코드 내에서 제어가 직관적임단점 (Cons)- 시스템이 커지면 유지보수가 난해함- 핀 레벨(Pin-level) 제어에 갇힘- 다중 비동기 입력 처리가 까다로움SystemC 3.0 기반 통합 환경 (ESL,Electronic System-Level)장점 (Pros)- 완벽한 객체 지향 모듈화 (TB, LCD 분리)- 하이레벨 시스템 설계 및 TLM(Transaction Level Modeling) 확장 가능- 하드웨어-소프트웨어 동시 검증에 최적화단점 (Cons)- 초기 환경 구축(Makefile, 옵션 설정)이 복잡함- SystemC 고유 문법 및 스레드 학습이 필요함- 컴파일 시간 오버헤드가 존재함------------------------------## 🔍 1. DPI-C 방식의 실실무적 평가## 👍 장점* 압도적인 가벼움과 단순함: 별도의 수많은 파일(*.h, *.cpp)을 분할 선언하고 신호 채널(sc_signal)을 일일이 바인딩하는 보일러플레이트 코드가 필요 없습니다. Verilog 소스 내에서 import 한 줄로 끝납니다.* 빠른 프로토타이핑: 단순히 "현재 RTL 내부 좌표의 색상을 윈도우 창에 점으로 찍어라"와 같은 단방향 데이터 브로드캐스트나 모니터링 모듈을 빠르게 붙여볼 때 가장 효율적입니다.## 👎 단점* 동기화 타이밍의 한계: 호스트 PC의 키보드 비동기 입력을 RTL 내부 클럭과 정확히 맞추려면, Verilog 테스트벤치 내에서 특정 좌표 스캔 완료 시점(127, 63)을 노려 수동으로 C 함수를 폴링해야 하는 타이밍 종속성이 생깁니다.* 확장성 부재: 나중에 게임 기기에 사운드 칩셋(Audio 코어)이나 가상 로더(ROM 버스 컨트롤러)를 추가하려 할 때, 이를 Verilog 테스트벤치 안에서 DPI 함수 호출 체인만으로 엮어 내기는 구조적으로 매우 지저분해집니다.------------------------------## 🔍 2. SystemC 3.0 방식의 실실무적 평가## 👍 장점* 완벽한 시스템 레벨 검증 (ESL): 입력 장치(sc_invaders_TB)와 디스플레이 출력 장치(sc_glcd128x64_TLM)가 완전히 독립된 하드웨어 칩셋처럼 모듈화됩니다. 하드웨어(Verilog)가 개발되기 전에 C++ 모델만으로 시스템을 미리 가동해 볼 수 있는 가상 프로토타이핑 환경의 핵심입니다.* 현대적 컴파일러 최적화 호환: 특히 SystemC 3.0 표준은 최신 C++17/20 규격을 활용하므로 스마트 포인터, 멀티스레딩 등 최신 호스트 PC의 리소스를 안전하고 빠르게 활용할 수 있어, 시뮬레이터 창이 버벅이거나 굳어버리는 윈도우 프리징 현상을 원천 방지합니다.* 버스를 통한 트랜잭션(TLM) 확장: 핀 하나하나를 0과 1로 쪼개어 매 클럭 스캔하지 않고, "한 프레임 버퍼 통째로 패킷 전송(Transaction)" 하듯이 고속 검증 모델로 업그레이드할 수 있는 인프라를 제공합니다.## 👎 단점* 높은 빌드 복잡도: 사용자가 직접 경험하셨듯, 다중 비트 버스 처리를 위해 --pins-sc-uint 같은 Verilator 전용 숨은 아규먼트를 정확히 챙겨야 하고, 라이브러리 링크 패스(LD_LIBRARY_PATH)나 C++ 컴파일러 표준 버전을 완벽하게 맞춰야만 컴파일러 에러의 늪에서 벗어날 수 있습니다.
인공지능이 알려주는 엔지니어의 선택에 동의 할 수 있을까?
------------------------------## 💡 엔지니어의 선택 요약* DPI-C는 개발 중인 "RTL 코어 내부 로직 자체가 메인"이며, 주변 장치는 단순히 동작 확인용 임시 도구(Stub)로 가볍게 붙이고 싶을 때 선택하는 숏컷(Shortcut)입니다.* SystemC 3.0은 프로세서(RISC-V 등)와 다양한 주변 장치(LCD, 오디오, 키패드)가 버스로 묶여 유기적으로 돌아가는 "SoC(System on Chip) 시스템 전체 아키텍처 및 하드웨어/펌웨어 통합 정합성"을 철저히 검증해야 하는 거대 공학 프로젝트에서 반드시 도입해야 하는 정석적인 정답입니다.128x64 해상도 게임 인프라와 검증 환경이 완벽하게 가동되었습니다. 이제 이 고도화된 SystemC 3.0 환경 위에서 다음으로 시도해보고 싶으신 기능이 있으신가요?
처음에는 DPI-C와 OpenCV를 추천 하더니 SystemC가 정석이라며 질문자의 편에 서는 듯하다. 인공지능은 약았다.
댓글 없음:
댓글 쓰기