SAÉ 5A01 · S5 — 20/20

Émulateur RISC-V

Émulateur d'architecture RV32I en C — GPU X11, carte son ALSA, extension RV32M, Docker

C RISC-V RV32I + RV32M X11 / Xlib ALSA Docker Linux 20/20

Démo

Contexte

Projet phare du semestre 5, la SAÉ 5A01 consistait à implémenter un émulateur complet de l'architecture RISC-V RV32I en langage C. L'émulateur doit être capable d'exécuter du code binaire RISC-V compilé, en simulant le comportement d'un processeur réel : registres, mémoire, décodage d'instructions, gestion des exceptions.

Le projet a obtenu la note de 20/20. La démonstration finale incluait le rendu du film Bad Apple encodé en vidéo bitmap, affiché via X11 dans l'émulateur — une preuve de la robustesse du système.

Équipe

Projet réalisé en équipe de trois : Hadrien Milo, Cyprien Fréville et Cristobal Pinto.

Mes contributions

🏗️ Structure & Makefile

Mise en place de la structure du projet dès le premier jour, Makefile évolutif avec support debug, targets clean, compatibilité GCC 14.2+.

🖥️ GPU / X11

Implémentation complète de la carte graphique : framebuffer MMIO, double buffering, résolution 128×64 en RGB565, rendu via Xlib. "GPU WORKS" — commit du 24 novembre à des heures indues.

🔊 Carte son ALSA

Conception et implémentation de la carte son via FIFO Unix : le son brut est écrit dans un pipe, lu par aplay. 16 bits, 44,1 kHz — qualité CD. Pas de dépendance supplémentaire à la compilation.

✖️ Extension RV32M

Implémentation de l'extension multiplication/division RISC-V : MUL, MULH, MULHU, MULHSU, DIV, DIVU, REM, REMU.

🐳 Docker

Dockerfile pour les bonus : conteneur avec accès X11 et périphérique son de l'hôte via --device /dev/snd, pour une portabilité maximale.

🌍 Internationalisation

Traduction complète de l'interface et des messages (FR/EN/ES/AR/JP), mise en place de l'infrastructure i18n, traduction de cpu.c et de la fenêtre de configuration.

📁 File selector

Navigateur de fichiers intégré à l'interface graphique pour charger un binaire RISC-V sans ligne de commande.

🎬 Bad Apple

Convertisseur mp4 → binaire RISC-V pour encoder la vidéo image par image et la faire tourner de manière fluide sur l'émulateur. La démo finale, c'est ça.

Architecture de l'émulateur

L'émulateur suit le pipeline classique d'un processeur RISC, avec périphériques mappés en mémoire (MMIO) :

Fetch → Decode → Execute → Memory → Writeback
GPU MMIO @ 0x50000000 Son MMIO @ 0x60000000 ELF loader Syscalls Linux

La carte graphique expose un front buffer, un back buffer et un registre de swap en MMIO. La carte son écrit dans une FIFO Unix consommée par aplay — principe sans dépendance à PulseAudio ou JACK.

Ce que j'en retiens

Implémenter un GPU et une carte son from scratch en C, mappés en mémoire sur un processeur qu'on a soi-même émulé — c'est le genre de projet qui démystifie définitivement ce qui se passe "sous le capot" d'une machine. Chaque couche d'abstraction moderne fait sens différemment après ça.

💡

Le convertisseur mp4 → binaire RISC-V m'a obligé à traiter de la vidéo en C pur, image par image, avec contraintes de timing pour un rendu fluide sur l'émulateur. Un exercice d'optimisation bas niveau que je n'aurais pas imaginé faire dans un projet scolaire.

🔧

Gérer la compatibilité GCC 14.2+ (Debian 13+) tout en maintenant la portabilité sur les versions antérieures — les subtilités des standards C et des warnings stricts du compilateur n'ont plus de secrets après ça.

C11 RISC-V RV32I + RV32M X11 / Xlib ALSA / aplay ELF GCC / Make Docker / Podman Linux GitLab