Lors de l’étude du fonctionnement des processseurs, il peut être utile de voir cycle par cycle comment évolue une exécution afin de comprendre l’impact des différents mécanismes. Cela s’applique aussi bien pour l’étude de la microarchitecture des processeurs, que pour d’autres expérimentations comme par exemple pour de la sécurité matérielle. Ainsi, un simulateur de microarchitectures est mis à disposition sur GitLab: https://gitlab.com/escou64-emmk/riscv-sim.git. Il permet de simuler l’exécution de différents programmes sur des processeurs implémentant le jeu d’instructions RISC-V. Les différents modèles de simulation sont en fait des exécutables générés directement à partir de description RTL de processeurs.

Pré-requis

Cette étape n’est pas nécessaire si vous utilisez une machine de l’école. Vous pouvez alors directement passer à l’étape d’installation.

Le simulateur de microarchitecture utilise plusieurs outils pour compiler les programmes et visualiser les résultats. Notamment, les logiciels suivants doivent être installés:

  • La suite de compilation RISC-V qui permet de compiler les programmes pour des processeurs utilisant l’ISA RISC-V. Il existe plusieurs moyens d’installer cette suite selon votre machine et votre système d’exploitation.
  • Les paquets Python 3 pyelftools et click sont utilisés par les différents scripts internes pour la génération de fichiers intermédiares (notamment les fichier .hex pour initialiser les contenus des mémoires). La méthode la plus simple pour les installer est d’utiliser le gestionnaire de paquets pip.
  • Enfin, GtkWave est un outil permettant de visualiser des chronogrammes, notamment ceux générés ici au format .vcd.

Installation

Une fois les différentes dépendances installées, il suffit alors de télécharger le répertoire du simulateur disponible sur GitLab: https://gitlab.com/escou64-emmk/riscv-sim.git.

Téléchargement Ces commandes ne sont à effectuer qu’une seule fois au tout début des expérimentations:

  # Déplacez-vous dans le répertoire "<my_dir>" de votre choix.
  # Puis clonez le répertoire de travail avant de vous déplacez à l'intérieur.
  cd "<my_dir>"
  git clone https://gitlab.com/escou64-emmk/riscv-sim.git
  cd riscv-sim

Configuration de l’environnement

La commande source utilisée ci-dessous ne fonctionne que sur les machines de l’école. Ainsi, si vous utilisez votre propre machine, vous devez simplement vous assurez que les outils installés précédemment dans la partie installation sont disponibles dans votre environnement.

Tout d’abord, ouvrez l’ensemble du répertoire de simulation riscv-sim avec Visual Studio Code. Ensuite, dans le terminal de Visual Studio Code, lancez la commande:

  source /net/npers/mescoutelou/share/env/HWDES/setup.sh

Cette commande doit être lancée à chaque ouverture de terminal.

Ensuite, vous devez vous déplacez dans un des répertoires de travail. Par exemple, pour réaliser les expérimentations illustrant l’exécution d’un programme, déplacez-vous dans le répertoire sw/uarch/exec:

  cd sw/uarch/exec

Fonctionnalités

Dans chaque répertoire de travail, vous retrouverez un fichier Makefile simplifiant le lancement de simulation. Généralement, vous aurez besoin des deux commandes suivantes:

  # Compile et exécute le programme
  make exec
  # Affiche le chronogramme
  make view

La première compile votre programme et génère les fichiers nécessaires à la simulation. Ensuite, elle utilise un modèle exécutable du processeur ciblé pour effectuer la simulation en elle-même. La seconde commande permet ensuite d’ouvrir l’outil GtkWave pour visualiser le chronogramme généré.

La commande make view ouvre à chaque fois une nouvelle fenêtre avec le chronogramme. Cependant, il n’est pas nécessaire de la relancer après chaque lancement de make exec. Si vous ciblez toujours le même processeur, vous pouvez simplement mettre à jour le chronogramme directement depuis la fenêtre de GtkWave: cela vous permet de garder la mise en forme des signaux entre plusieurs exécutions ! Pour cela, il suffit de cliquer sur l’icône Reload.

Pour certaines expériementations, il peut être nécessaire de simuler le code sur différents processeurs afin de comparer les exécutions. Pour cela, l’option CORE_NAME permet de choisir le processeur de votre choix:

  # Compile et exécute le programme avec le processeur core_0
  make exec CORE_NAME=core_0
  # Affiche le chronogramme généré avec le processeur core_0
  make view CORE_NAME=core_0

La durée de simulation maximale (en nombre de cycles) est fixée par défaut dans le Makefile à l’aide de l’option NTRIGGER. Ainsi, si vous souhaitez rallonger / raccourcir cette durée, il est possible de changer la valeur au lancement de la commande:

  # Compile et exécute le programme maximum durant 100 cycles
  make exec NTRIGGER=100
  # Affiche le chronogramme généré
  make view

La plupart des processeurs simulés sont basés sur l’architecture RISC-V. Celle-ci s’organise en plusieurs parties: une base commune d’instructions et registres pour manipuler des entiers (32 ou 64 bits), à laquelle peuvent être ajouter une ou plusieurs extensions. Par exemple, l’extension M permet d’ajouter des instructions dédiées aux opérations de multiplication et division. Les différents Makefile mis à disposition permettent de compiler en choisissant les extensions utilisées à la compilation à l’aide de l’option SIM_ISA. Par exemple, la commande suivante permet de compiler du code 32-bit avec l’extension M:

  # Compile avec l'extension M et exécute le programme
  make exec SIM_ISA=rv32i_m
Implémentation des extensions Du point de vue compilation, toutes les extensions officielles peuvent être librement activées ou désactivées. En revanche, seules certaines d’entre elles sont actuellement implémentées dans les processeurs simulés ici.

Lors de la compilation d’un programme, il est possible de donner des directives au compilateur. L’une des plus courantes est le niveau d’optimisation attendu. Un code code compilé optimisé s’exécutera généralement plus rapidement, mais sera moins facilement lisible en utilisant des séquences d’instructions bien spécifiques. Pour la simulation, il est possible d’indiquer le niveau d’optimisations avec l’option OPT_LVL (0 pour aucune optimisation, 3 pour toutes les optimisations possibles):

  # Compile avec toutes les optimisations et exécute le programme
  make exec OPT_LVL=3