Ce chapitre est votre cahier des charges. Les exercices des quatre premières parties ne sont pas des à-côtés : ce sont littéralement les briques de ce que vous allez construire ici. Vous gardez une grande liberté sur le thème.
Concevoir et réaliser, en groupe de 2 ou 3, un DSL (domain-specific language, votre propre petit langage) dont l'exécution exploite le matériel (mémoire, ASM, SIMD), puis le mettre en scène dans une démo au thème libre.
L'architecture d'exécution est un choix qui vous appartient : VM à registres pilotée par un assembleur maison (l'option la plus guidée par le cours), VM à pile, interpréteur AST dont les opérations coûteuses sont accélérées à la main, JIT, ou une combinaison — voir 5.2.
| Thème | Ce que votre DSL exécute | Pourquoi c'est intéressant |
|---|---|---|
| Particules scriptables | un « kernel » par particule (gravité, forces, couleur) | batch mode SoA + SIMD, rendu visuel immédiat |
| DSL audio | oscillateurs, filtres, enveloppes, traités par blocs | traitement par blocs = batch, denormals |
| Fantasy console (façon CHIP-8 / PICO-8) | un jeu écrit dans votre DSL | le langage et son moteur d'exécution sont au centre, framebuffer, input |
| Shaders CPU / post-process | un programme par pixel | SIMD évident, comparaison possible avec un vrai shader |
| Boids / IA de foule | règles de comportement par agent | vec4 natif, voisinage, SoA |
| Génération procédurale | bruit (Perlin/Simplex), terrain, donjon | calcul flottant intensif |
| Scripts de gameplay | logique d'entités, événements | appels de fonctions, hot reload |
Un DSL (votre propre langage, même minimal)
if et/ou while), et des appels de
fonction ;Un moteur d'exécution qui exploite le matériel, au choix du groupe — une seule brique suffit comme cœur, combiner plusieurs est encouragé :
Quel que soit le choix : documentez la représentation interne retenue, et sachez justifier vos décisions de layout (taille des valeurs, alignement).
Au moins un chemin SIMD réellement exploité :
registres vec4 + opcodes SSE, ou mode
batch sur N entités, ou noyaux SIMD appelés par votre
moteur (mixage audio, culling...).
Mesures
Démo en lien avec le thème choisi.
README : architecture choisie et pourquoi, format de la représentation interne, résultats de mesure, répartition du travail.
switch vs
[[msvc::musttail]] (VS 2026) vs computed goto
(clang-cl)./W4 conseillé).CMakeLists.txt à la racine, ouverture directe dans VS via
File → Open → Folder.6 séances de 4 h, les deux dernières empiétant sur la semaine 2 :
| Séance | Contenu | Exercices (briques) |
|---|---|---|
| S1 Mémoire | Partie 1, sections 1.1 à 1.6 : histoire, hiérarchie, caches, alignement, DOD | Défis 1, 2, 3 |
| S2 ASM 1 | Partie 2, sections 2.1 à 2.3 et 2.6 : modèle d'exécution, registres,
instructions, lecture de /Od et /O2 |
Défis 1, 2 (début) |
| S3 ASM 2 | Partie 2, sections 2.4, 2.5, 2.7, 2.8 : pile, convention d'appel, unwind, jump tables, encodage, ARM64 | Défis 3, 4 |
| S4 SIMD 1 | Partie 3, sections 3.1 à 3.4 : histoire, auto-vectorisation, SSE, masques, tail | (exercices distribués en cours) |
| S5 SIMD 2 | Partie 3, sections 3.5 à 3.8 : AVX2, lanes, AVX-512, dispatch, benchmarks | (exercices distribués en cours) |
| S6 Interpréteur | Partie 4, sections 4.1 à 4.8 : chaîne, Pratt, stack vs registres, dispatch, batch | Défi 1 ; lancement du projet (groupes, thèmes) |
Chaque séance combine une courte capsule théorique (20-30 min) au moment où vous en avez besoin, puis du travail en groupe. Les capsules ci-dessous suivent par défaut le chemin le plus guidé (VM à registres) — si votre groupe a choisi une autre architecture (5.2, point 2), adaptez-en l'esprit : par exemple « allocation de registres » devient « disposition des nœuds/valeurs de votre AST » pour un tree-walker.
| Moment | Capsule | Jalon attendu |
|---|---|---|
| S2-J1 | Format d'instruction, X-macro, allocation de registres (4.9) | choix du thème et de l'architecture, représentation interne écrite |
| S2-J2 | Assembleur deux passes (Défi 4) | Jalon 1 : premier moteur d'exécution minimal (VM, interpréteur...) + boucle qui tourne |
| S2-J3 | Fenêtres d'appel, stack overflow, tests d'aller-retour | fonctions et appels |
| S2-J4 | Mesurer proprement : Release, benchmark anti-optimisation, VTune (1.9, 3.10) | Jalon 2 : premiers benchmarks, chemin SIMD commencé |
| S3-J1 | Pratt, sema, compilation (Défis 1, 3) | langage plus riche (sucre syntaxique, plus de constructions) |
| S3-J2 | Dispatch (Défi 5), superinstructions (Défi 6) | optimisations mesurées |
| S3-J3 | Batch mode (Défi 7), CPU dispatch | Jalon 3 : démo jouable, gel des fonctionnalités |
| S3-J4 | - | Soutenance : 15 min + démo + questions individuelles |
| Critère | Points | Ce qu'on regarde |
|---|---|---|
| Moteur d'exécution (VM, interpréteur, JIT...) | 7 | justesse, représentation interne documentée, outillage de vérification (désassembleur, dump, test aller-retour...), appels de fonctions, choix architectural justifié |
| Exploitation du matériel (SIMD, mémoire) | 4 | chemin SIMD réel, alignement, SoA, justification |
| Mesures et analyse | 3 | protocole (Release, répétitions), avant/après, explication matérielle correcte |
| Langage haut niveau | 3 | lexer, parser, sema, allocation de registres |
| Qualité : code, README, git | 2 | lisibilité, tests, historique git réparti |
| Soutenance et démo | 1 | clarté, démo qui fonctionne |
| Bonus | +2 max | voir la liste en 5.2 |
Note individuelle : pondérée selon les questions individuelles de la soutenance (« explique ce handler », « pourquoi ce registre est non-volatile ») et l'historique git.
À chaque jalon, attendez-vous à devoir justifier vos choix à voix haute, pas seulement montrer que « ça marche ». Les exemples ci-dessous supposent une VM à registres (l'architecture la plus guidée par le cours) — adaptez l'esprit de chaque question à ce que vous avez réellement construit (VM à pile, AST, JIT...) :
Jalon 1 (moteur d'exécution + assembleur/outillage)
Jalon 2 (fonctions, premiers benchmarks)
f appelle g, où sont les arguments
? Qu'est-ce qui empêche g d'écraser les registres de
f ? »Jalon 3 (optimisations, démo)
/Qvec-report:2 ? »| Symptôme | Cause probable | Piste |
|---|---|---|
| Le moteur d'exécution plante « au hasard » | lecture hors bornes (registres, pile, buffer AST...), fenêtre d'appel mal calculée, état mal initialisé | assertions en Debug sur les accès ; ASan (MSVC
/fsanitize=address) |
| Le SIMD est plus lent | mesure en Debug, loadu/storeu sur des
données non alignées dans une boucle trop courte, dispatch par
élément |
batch mode ; mesurer en Release |
Crash movaps |
constantes vec4 ou registres non alignés |
alignas(16), operator new aligné |
| Résultats flottants différents entre SSE et AVX2 | FMA, ordre des additions | tolérance dans les tests ; déterminisme discuté en 3.2 |
| Envie de sauter directement à l'architecture la plus ambitieuse (JIT...) sans rien de simple qui tourne encore | enthousiasme, compréhensible | un JIT est un choix légitime dès le départ (5.2), mais faites d'abord tourner un chemin simple de bout en bout avant d'optimiser l'architecture elle-même |
| Le parser mange tout le temps | langage trop ambitieux (classes, closures, chaînes) | réduire : pas de GC, types valeur, pas de chaînes dynamiques |
| Un membre du groupe ne code que la démo | répartition du travail | exiger une brique du moteur d'exécution ou une optimisation mesurée par membre |
Certains fichiers de Vektor (l'interpréteur de référence complet,
voir partie 4) vous sont distribués par morceaux, comme
corrigés, au fil des exercices de la partie 4 :
lexer.cpp et Parser::expression après le défi
1, asm.cpp après le défi 4, showdown.cpp après
les défis 2 et 5. Utilisez-les pour comparer votre approche, pas pour
copier — le but est de comprendre pourquoi vos choix diffèrent, pas
d'obtenir le même code.
Vektor suit spécifiquement le chemin VM à registres
décrit en 5.2 : asm.cpp (l'assembleur maison) et
showdown.cpp (stack vs registres) n'ont de sens directement
transposable que si vous avez choisi cette même architecture.
lexer.cpp et Parser::expression, en revanche,
sont utiles quel que soit votre choix — un front-end (lexer/parser) est
nécessaire pour n'importe quel DSL, indépendamment de comment vous
l'exécutez ensuite.
Vektor a aussi des limites volontaires, qui peuvent
vous inspirer pour délimiter le périmètre de votre propre projet : pas
de tableaux, pas de chaînes, pas de variables globales, pas
d'affectation de composante (v.x = 1.0), pas de batch mode
intégré (c'est une démo séparée), constantes rechargées dans les boucles
(un exercice, pas un défaut assumé). Rien ne vous oblige à couvrir plus
que ça pour un socle solide.