Ajouts des différents programmes et ajout des fichiers readme.md

This commit is contained in:
2024-10-04 15:54:19 +02:00
parent f5db552558
commit ef90364a97
12 changed files with 835027 additions and 2 deletions

View File

@@ -1,3 +1,47 @@
# SimulateurCache
# Simulateur de Cache
Mini projet n°1 - Simulateur de cache en C avec les algorithmes LRU, FIFO et Random
Ce projet contient des simulations de comportements de cache utilisant deux stratégies de remplacement : **Least Recently Used (LRU)** et **Random**. Chaque stratégie est implémentée dans son propre répertoire avec des fichiers de code source et de documentation.
## Table des matières
- [📖 Description Générale](#-description-générale)
- [🗂️ LRU](#-lru)
- [🎲 Random](#-random)
- [📁 Traces](#-traces)
- [🛠️ Générateur de Traces](#-générateur-de-traces)
## 📖 Description Générale
Le simulateur de cache permet d'analyser le comportement de deux stratégies de remplacement de cache : LRU et Random. Chaque méthode a ses propres principes de fonctionnement, avantages et inconvénients, qui sont détaillés dans leurs respectifs fichiers README.
## **[🗂 LRU](./lru)**
Le répertoire **lru** contient l'implémentation de la stratégie **Least Recently Used**. Cette méthode vise à conserver dans le cache les lignes qui ont été les plus récemment utilisées.
- **Fichiers**:
- `README.md`: Documentation détaillée sur la stratégie LRU.
- `cache.c`: Code source pour la simulation du cache utilisant LRU.
## **[🎲 Random](./random)**
Le répertoire **random** contient l'implémentation de la stratégie **Random**. Cette méthode choisit aléatoirement une ligne de cache à remplacer lorsque le cache est plein.
- **Fichiers**:
- `README.md`: Documentation détaillée sur la stratégie Random.
- `cache.c`: Code source pour la simulation du cache utilisant Random.
## **[📁 Traces](./traces)**
Le répertoire **traces** contient des fichiers de traces utilisés pour tester les simulations de cache. Chaque fichier de traces simule des accès mémoire pour évaluer les performances des différentes stratégies.
- **Fichiers**:
- `README.md`: Documentation sur les fichiers traces.
- `sample`, `sample1`, `sample2`: Exemples de fichiers de traces.
## **[🛠️ Générateur de Traces](./traces_generator)**
Le répertoire **traces_generator** contient des outils pour générer des fichiers de traces aléatoires pour tester le simulateur de cache.
- **Fichiers**:
- `README.md`: Documentation sur l'utilisation du générateur de traces.
- `trace_generator.c`: Code source pour générer des traces de manière aléatoire.

59
lru/README.md Normal file
View File

@@ -0,0 +1,59 @@
# Simulateur de Cache - Version LRU
## 📖 Description
Le programme `cache.c` simule le comportement d'un cache de processeur. Il permet de suivre les hits et les misses ainsi que d'analyser les performances du cache en fonction des références mémoire fournies.
## 📦 Compilation
Pour compiler le programme, utilisez la commande suivante :
```bash
gcc -o cache_simulator cache.c -lm
```
## ⚙️ Exécution
Pour exécuter le programme, utilisez la ligne de commande suivante :
```c
./cache_simulator -s <cache_size(KB)> -l <line_size> -a <associativity> [-c] [-W] < <trace_file>
```
## 📝 Arguments
* `-s <cache_size(KB)>` : Taille du cache en kilooctets. (Obligatoire)
Exemple : -s 64 -> taille du cache de 64 KB
* `-l <line_size>` : Taille de la ligne de cache en octets. (Obligatoire)
Exemple : -l 16 -> taille de ligne de 16 octets
* `-a <associativity>` : Associativité du cache (nombre de lignes par ensemble). (Obligatoire)
Exemple : -a 4 -> associativité de 4 lignes
* `-c` : Activer l'écriture en mode Write Back. (Optionnel)
Exemple : -c -> active le mode Write Back
* `-W` : Activer la stratégie d'allocation d'écriture (Write Allocate). (Optionnel)
Exemple : -W -> active l'allocation d'écriture
## 📚 Fonctionnement de LRU (Least Recently Used)
La politique de remplacement **Least Recently Used (LRU)** est une méthode utilisée pour gérer les lignes de cache lorsque le cache est plein et qu'il est nécessaire de remplacer une ligne. L'objectif principal de LRU est de garder dans le cache les données qui ont été utilisées le plus récemment, en supposant que les données utilisées récemment seront également utilisées à nouveau dans un avenir proche.
### Principe de Fonctionnement
1. **Gestion de l'Usage**: Chaque fois qu'une ligne de cache est accédée (que ce soit une lecture ou une écriture), la ligne est marquée comme la plus récemment utilisée. Cela est effectué en mettant à jour une valeur associée à la ligne, qui indique le temps ou le nombre d'accès récents.
2. **Incrémentation de Valeurs LRU**: Lorsque l'une des lignes de cache est accédée, sa valeur LRU est réinitialisée à zéro, tandis que les autres lignes de l'ensemble voient leurs valeurs LRU incrémentées. Cela signifie que plus la valeur LRU d'une ligne est élevée, plus il a été longtemps depuis qu'elle a été utilisée.
3. **Remplacement**: Lorsque le cache atteint sa capacité maximale et qu'un nouvel accès nécessite l'allocation d'une ligne de cache, LRU remplace la ligne ayant la valeur LRU la plus élevée (la moins récemment utilisée). Cela garantit que les lignes de cache qui sont les plus susceptibles d'être utilisées à nouveau restent disponibles.
### Avantages et Inconvénients
- **Avantages**:
- LRU tend à offrir un bon taux de hit dans de nombreuses applications, car il prend en compte l'historique des accès.
- La méthode est relativement simple à comprendre et à mettre en œuvre.
- **Inconvénients**:
- La mise à jour des valeurs LRU peut nécessiter un temps supplémentaire, en particulier pour les caches avec une grande associativité.
- Si la charge de travail a une taille de référence plus grande que le cache, cela peut conduire à un comportement inefficace, car de nombreuses lignes seront remplacées.
## 🛠️ Auteur
- Moncef STITI

729
lru/cache.c Normal file

File diff suppressed because it is too large Load Diff

58
random/README.md Normal file
View File

@@ -0,0 +1,58 @@
# Simulateur de Cache - Version Random
## 📖 Description
Le programme `cache.c` simule le comportement d'un cache de processeur. Il permet de suivre les hits et les misses ainsi que d'analyser les performances du cache en fonction des références mémoire fournies.
## 📦 Compilation
Pour compiler le programme, utilisez la commande suivante :
```bash
gcc -o cache_simulator cache.c -lm
```
## ⚙️ Exécution
Pour exécuter le programme, utilisez la ligne de commande suivante :
```c
./cache_simulator -s <cache_size(KB)> -l <line_size> -a <associativity> [-c] [-W] < <trace_file>
```
## 📝 Arguments
* `-s <cache_size(KB)>` : Taille du cache en kilooctets. (Obligatoire)
Exemple : -s 64 -> taille du cache de 64 KB
* `-l <line_size>` : Taille de la ligne de cache en octets. (Obligatoire)
Exemple : -l 16 -> taille de ligne de 16 octets
* `-a <associativity>` : Associativité du cache (nombre de lignes par ensemble). (Obligatoire)
Exemple : -a 4 -> associativité de 4 lignes
* `-c` : Activer l'écriture en mode Write Back. (Optionnel)
Exemple : -c -> active le mode Write Back
* `-W` : Activer la stratégie d'allocation d'écriture (Write Allocate). (Optionnel)
Exemple : -W -> active l'allocation d'écriture
## 📚 Fonctionnement de la Stratégie Random
La stratégie de remplacement **Random** est une méthode simple pour gérer les lignes de cache lorsque le cache est plein. Contrairement à d'autres méthodes comme LRU, où les décisions sont basées sur l'historique d'accès, Random choisit simplement une ligne à remplacer au hasard parmi celles qui sont présentes dans le cache.
### Principe de Fonctionnement
1. **Choix Aléatoire**: Lorsqu'un nouvel accès à la mémoire doit être effectué et que le cache est plein, une ligne de cache est choisie de manière aléatoire pour être remplacée. Ce choix ne dépend d'aucun critère de fréquence ou de récence.
2. **Remplacement**: La ligne choisie est invalidée et remplacée par la nouvelle ligne de données, qui est ensuite chargée dans le cache.
### Avantages et Inconvénients
- **Avantages**:
- La simplicité de l'algorithme rend son implémentation facile.
- En tant que méthode probabiliste, elle peut parfois donner de bons résultats dans des cas spécifiques, où le comportement d'accès est imprévisible.
- **Inconvénients**:
- Random n'utilise pas d'historique d'accès, ce qui peut entraîner un taux de hit inférieur par rapport à des stratégies comme LRU ou FIFO.
- Dans certains scénarios, elle peut remplacer des lignes de cache qui auraient pu être utilisées à nouveau dans un futur proche, entraînant ainsi des misses fréquentes.
## 🛠️ Auteur
- Moncef STITI

417
random/cache.c Normal file
View File

@@ -0,0 +1,417 @@
/*
* Fichier : cache.c
* Auteur : Moncef STITI
* Date : 02/11/2024
* Version : 1.0
* Description : Ce programme permet de simuler une mémoire cache avec comme algorithme d'éviction d'une ligne "Random" (Aléatoire).
* Compilation : Pour compiler le programme, on utilise la commande suivante : gcc cache.c -o simulateur_cache -lm -Wall
*/
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h> // Pour les options en argument
#include <time.h> // Pour les mesures de temps
// Différentes couleurs pour l'affichage des résultats
#define RESET "\x1b[0m" // Couleur de base du terminal
#define GREEN "\x1b[32m" // Vert
#define YELLOW "\x1b[33m" // Jaune
#define RED "\x1b[31m" // Rouge
#define CYAN "\033[36m" // Cyan
#define MAGENTA "\x1b[35m" // Violet/Magenta
#define WHITE "\x1b[37m" // Blanc
#define COULEUR_BORDURE CYAN // Cyan
// Structure représentant une ligne de cache.
struct line
{
unsigned int valid; // Indicateur de validité
unsigned int dirty; // Indicateur de "saleté" (dirty)
unsigned int tag; // Tag de la ligne de cache
}; typedef struct line line;
// Structure représentant un ensemble de lignes de cache.
struct Set
{
struct line *lines;
}; typedef struct Set Set;
// Structure représentant le cache lui-même.
struct Cache
{
struct Set *sets;
}; typedef struct Cache Cache;
/*
* Fonction : ecrire_ligne_en_memoire
* Description : Cette fonction simule l'écriture d'une ligne de cache évincée
* dans la mémoire principale. Dans le contexte de la simulation,
* la fonction n'effectue pas d'écriture réelle, mais elle peut
* être utilisée pour afficher des informations de débogage concernant
* l'éviction d'une ligne "dirty" (modifiée).
*
* Paramètre :
* - line *evictedLine : Pointeur vers la ligne de cache qui a été évincée.
*
* Retour :
* - void : Cette fonction ne retourne rien, car elle est conçue pour
* effectuer une action (écriture dans la mémoire) plutôt que de
* fournir une valeur de retour.
*/
void ecrire_ligne_en_memoire(line *evictedLine)
{
// Comme il s'agit d'une simulation, nous ne faisons pas d'écriture réelle ici.
// Mais voici comment afficher la ligne :
// printf("Ecriture de la ligne %d dans la mémoire centrale\n", evictedLine->tag);
}
/*
* Fonction : creer_struct_cache
* Description : Cette fonction initialise une structure de cache en allouant
* dynamiquement la mémoire pour les ensembles et les lignes de cache.
* Chaque ligne est initialisée avec des valeurs par défaut pour
* les indicateurs de validité, de saleté (dirty) et le tag.
*
* Paramètres :
* - Cache *cache : Pointeur vers la structure de cache à initialiser.
* - int numSets : Nombre d'ensembles dans la cache. C'est le nombre total
* de groupes de lignes de cache.
* - int associativite : Le degré d'associativité de la mémoire cache.
*
* Retour :
* - void : Cette fonction ne retourne rien, car elle modifie directement
* la structure de cache passée en paramètre.
*/
void creer_struct_cache(Cache *cache, int numSets, int associativite)
{
cache->sets = (Set *)malloc(numSets * sizeof(Set));
for (int i = 0; i < numSets; i++) {
cache->sets[i].lines = (line *)malloc(associativite * sizeof(line));
for (int j = 0; j < associativite; j++) {
cache->sets[i].lines[j].valid = 0;
cache->sets[i].lines[j].dirty = 0;
cache->sets[i].lines[j].tag = -1;
}
}
}
/*
* Fonction : acceder_cache
* Description : Cette fonction simule l'accès à un cache à partir d'une
* adresse mémoire donnée. Elle détermine si l'accès est un hit ou
* un miss, met à jour les statistiques en conséquence, et gère
* l'éviction de lignes de cache si nécessaire.
*
* Paramètres :
* - Cache *cache : Pointeur vers la structure de cache dans laquelle l'accès
* est effectué.
* - int adresse : Adresse mémoire à laquelle on souhaite accéder.
* - int associativite : Degré d'associativité de la mémoire cache.
* - int writeBack : Indicateur de la politique d'écriture (Write Back ou Write Through).
* - int writeAllocate : Indicateur de la stratégie d'allocation lors des écritures
* (Write Allocate ou No Write Allocate).
* - int numSets : Nombre d'ensembles dans la mémoire cache.
* - int accessType : Type d'accès (0 pour lecture, 1 pour écriture).
* - int* memoryAccesses : Pointeur vers un entier qui suit le nombre total
* d'accès mémoire effectués.
* - int* hitsLecture : Pointeur vers un entier qui suit le nombre de hits en lecture.
* - int* missesLecture : Pointeur vers un entier qui suit le nombre de misses en lecture.
* - int* hitsEcriture : Pointeur vers un entier qui suit le nombre de hits en écriture.
* - int* missesEcriture : Pointeur vers un entier qui suit le nombre de misses en écriture.
*
* Retour :
* - void : Cette fonction ne retourne rien, mais met à jour les statistiques de cache
* en fonction de l'accès effectué.
*/
void acceder_cache(Cache *cache, int adresse, int associativite, int writeBack, int writeAllocate, int numSets, int accessType, int* memoryAccesses, int* hitsLecture, int* missesLecture, int* hitsEcriture, int* missesEcriture)
{
int setIndex = adresse % numSets;
// Recherche de l'adresse dans le set correspondant
int found = 0;
for (int i = 0; i < associativite; i++) {
line *currentLine = &cache->sets[setIndex].lines[i];
if (currentLine->valid && currentLine->tag == (adresse / numSets)) {
found = 1;
if (accessType == 0 || accessType == 2) {
// C'est un hit en lecture
(*hitsLecture)++;
} else {
// C'est un hit en écriture
(*hitsEcriture)++;
if (writeBack) {
currentLine->dirty = 1;
}
}
// Marquer la ligne comme valide
currentLine->valid = 1;
}
}
if (!found) {
// C'est un miss, mettre à jour les statistiques
if (accessType == 0 || accessType == 2) {
// C'est un miss en lecture
(*missesLecture)++;
} else {
// C'est un miss en écriture
(*missesEcriture)++;
}
// Choisir aléatoirement une ligne pour l'éviction
int evictionIndex = rand() % associativite;
line *evictedLine = &cache->sets[setIndex].lines[evictionIndex];
// Si la ligne évincée est "dirty" et si la stratégie = write-back, alors écrire dans la mémoire centrale
if (writeBack && evictedLine->dirty) {
ecrire_ligne_en_memoire(evictedLine);
}
// Mettez à jour la ligne évincée avec la nouvelle adresse
evictedLine->tag = adresse / numSets;
evictedLine->valid = 1;
if (accessType == 1) {
evictedLine->dirty = 1;
}
(*memoryAccesses)++;
}
}
/*
* Fonction : get_hits_color
* Description : Cette fonction détermine la couleur d'affichage basée sur le pourcentage
* de hits pour une performance de cache donnée. Elle renvoie une constante
* représentant une couleur en fonction du niveau de performance.
*
* Paramètre :
* - float percentage : Pourcentage de hits, exprimé en tant que valeur
* flottante. Ce pourcentage est utilisé pour évaluer
* la performance de la mémoire cache.
*
* Retour :
* - const char* : Retourne une constante de chaîne de caractères représentant
* la couleur correspondant à la performance de la mémoire cache :
* - GREEN pour une bonne performance (≥ 80 %)
* - YELLOW pour une performance moyenne (≥ 50 % et < 80 %)
* - RED pour une mauvaise performance (< 50 %)
*
* Potentiel erreur :
* - La fonction ne gère pas les valeurs de pourcentage en dehors de la
* plage normale (0 à 100). Les entrées négatives ou supérieures à 100
* pourraient donner des résultats inattendus.
*/
const char* get_hits_color(float percentage)
{
if (percentage >= 80.0) {
return GREEN; // Bonne performance
} else if (percentage >= 50.0) {
return YELLOW; // Moyenne performance
} else {
return RED; // Mauvais performance
}
}
/*
* Fonction : get_misses_color
* Description : Cette fonction détermine la couleur d'affichage basée sur le pourcentage
* de misses pour une performance de cache donnée. Elle renvoie une constante
* représentant une couleur en fonction du niveau de performance.
*
* Paramètre :
* - float percentage : Pourcentage de misses, exprimé en tant que valeur
* flottante. Ce pourcentage est utilisé pour évaluer
* la performance de la mémoire cache.
*
* Retour :
* - const char* : Retourne une constante de chaîne de caractères représentant
* la couleur correspondant à la performance de la mémoire cache :
* - GREEN pour une bonne performance (< 8 % de misses)
* - YELLOW pour une performance acceptable (≥ 8 % et < 16 %)
* - RED pour une mauvaise performance (≥ 16 % de misses)
*
* Potentiel erreur :
* - La fonction ne gère pas les valeurs de pourcentage en dehors de la
* plage normale (0 à 100). Les entrées négatives ou supérieures à 100
* pourraient donner des résultats inattendus.
*/
const char* get_misses_color(float percentage)
{
if (percentage < 8.0) {
return GREEN; // Bonne performance
} else if (percentage < 16.0) {
return YELLOW; // Acceptable
} else {
return RED; // Mauvais performance
}
}
void afficher_hits_miss(int nbTotalAcces, int nbAccesLecture, int nbAccesEcriture, int memoryAccesses, int hitsLecture, int hitsEcriture, int missesLecture, int missesEcriture, double cpu_time_used) {
// Calculs des pourcentages
float pourcentAccLecture = (double) nbAccesLecture / nbTotalAcces * 100;
float pourcentAccEcriture = (double) nbAccesEcriture / nbTotalAcces * 100;
int totalHits = hitsLecture + hitsEcriture;
float pourcentHits = (double) totalHits / nbTotalAcces * 100;
float pourcentHitsLecture = (double) hitsLecture / nbAccesLecture * 100;
float pourcentHitsEcriture = (double) hitsEcriture / nbAccesEcriture * 100;
int totalMisses = missesLecture + missesEcriture;
float pourcentMisses = (double) totalMisses / nbTotalAcces * 100;
float pourcentMissesLecture = (double) missesLecture / nbAccesLecture * 100;
float pourcentMissesEcriture = (double) missesEcriture / nbAccesEcriture * 100;
// Affichage avec bordures et couleurs
printf("%s----------------------------------------------------\n", COULEUR_BORDURE);
printf("| %sStatistiques de Cache%s |\n", WHITE, COULEUR_BORDURE);
printf("----------------------------------------------------\n");
printf("| %sTotal Accès%s | %s%6d %s|\n", MAGENTA, COULEUR_BORDURE, WHITE, nbTotalAcces, COULEUR_BORDURE);
printf("----------------------------------------------------\n");
printf("| %sAccès en Lecture%s | %s%6d (%.2f%%)%s |\n", WHITE, COULEUR_BORDURE, WHITE, nbAccesLecture, pourcentAccLecture, COULEUR_BORDURE);
printf("| %sAccès en Écriture%s | %s%6d (%.2f%%)%s |\n", WHITE, COULEUR_BORDURE, WHITE, nbAccesEcriture, pourcentAccEcriture, COULEUR_BORDURE);
printf("----------------------------------------------------\n");
printf("| %sTotal Hits :%s | %s%6d (%.2f%%) %s|\n", MAGENTA, COULEUR_BORDURE, get_hits_color(pourcentHits), totalHits, pourcentHits, COULEUR_BORDURE);
printf("|%s - Hits en Lecture %s | %s%6d (%.2f%%)%s |\n", WHITE, COULEUR_BORDURE, get_hits_color(pourcentHits), hitsLecture, pourcentHitsLecture, COULEUR_BORDURE);
printf("|%s - Hits en Écriture %s | %s%6d (%.2f%%)%s |\n", WHITE, COULEUR_BORDURE, get_hits_color(pourcentHits), hitsEcriture, pourcentHitsEcriture, COULEUR_BORDURE);
printf("----------------------------------------------------\n");
printf("| %sTotal Misses :%s | %s%6d (%.2f%%) %s|\n", MAGENTA, COULEUR_BORDURE, get_misses_color(pourcentMisses), totalMisses, pourcentMisses, COULEUR_BORDURE);
printf("|%s - Misses en Lecture%s | %s%6d (%.2f%%) %s|\n", WHITE, COULEUR_BORDURE, get_misses_color(pourcentMisses), missesLecture, pourcentMissesLecture, COULEUR_BORDURE);
printf("|%s - Misses en Écriture%s | %s%6d (%.2f%%) %s|\n", WHITE, COULEUR_BORDURE, get_misses_color(pourcentMisses), missesEcriture, pourcentMissesEcriture, COULEUR_BORDURE);
printf("----------------------------------------------------\n");
printf("|%s Accès Mémoire%s | %s%6d %s|\n", WHITE, COULEUR_BORDURE, WHITE, memoryAccesses, COULEUR_BORDURE);
printf("----------------------------------------------------\n");
printf("| %sTemps total d'accès au cache : %.6f secondes%s |\n", MAGENTA, cpu_time_used, COULEUR_BORDURE);
printf("----------------------------------------------------%s\n", RESET);
}
/*
* Fonction : afficher_aide
* Description : Cette fonction affiche un message d'aide détaillant comment utiliser le programme
* de simulation de cache. Elle fournit des informations sur les options disponibles
* et la syntaxe correcte pour exécuter le programme.
*
* Fonctionnalités :
* - Indique l'utilisation générale du programme.
* - Liste les options possibles avec des descriptions pour chacune, y compris
* les paramètres de taille de cache, de taille de ligne, d'associativité,
* et les options de politique d'écriture.
* - Fournit un exemple de ligne de commande illustrant l'utilisation des options.
*
* Comportement :
* - Appelle `printf` pour afficher chaque ligne d'information à l'utilisateur.
* - Utilise `exit(EXIT_SUCCESS)` pour quitter le programme après l'affichage de l'aide,
* garantissant que le programme ne continue pas à s'exécuter après avoir fourni
* les informations nécessaires.
*/
void afficher_aide()
{
printf("Usage: ./cache [options] < fichier\n");
printf("Options :\n");
printf(" -h : Affiche cette aide et quitte le programme\n");
printf(" -s <taille_cache> : Spécifie la taille du cache en Ko\n");
printf(" -l <taille_ligne> : Spécifie la taille d'une ligne de cache en octets\n");
printf(" -a <associativite>: Spécifie l'associativité de la mémoire cache (ex: 1, 2, 4, 8...)\n");
printf(" -c : Active le Write Back (par défaut, Write Through est activé)\n");
printf(" -W : Active le Write Allocate (par défaut, No Write Allocate est activé)\n");
printf("\nExemple :\n");
printf(" ./cache -s 1 -l 8 -W -c -a 1 < sample\n");
printf("\n");
exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
{
if (argc < 7 || argc > 9)
{
afficher_aide();
}
Cache cache;
// def Arguments
int tailleCache;
int tailleLigne;
int associativite;
int writeBack = 0;
int writeAllocate = 0;
// Suivi des statistiques
int nbTotalAcces = 0;
int nbAccesLecture = 0;
int nbAccesEcriture = 0;
int memoryAccesses = 0;
int hitsLecture = 0;
int hitsEcriture = 0;
int missesLecture = 0;
int missesEcriture = 0;
int numSets;
int accessType;
int adresse;
// Variables pour le temps
clock_t start_time, end_time;
double cpu_time_used;
// Arguments
int opt;
while ((opt = getopt(argc, argv, "s:l:a:Wch:")) != -1) {
switch (opt) {
case 's':
tailleCache = atoi(optarg);
break;
case 'l':
tailleLigne = atoi(optarg);
break;
case 'a':
associativite = atoi(optarg);
break;
case 'W':
writeAllocate = 1;
break;
case 'c':
writeBack = 1;
break;
case 'h':
afficher_aide();
break;
default:
printf("Usage: %s -s <cache_size> -l <line_size> -a <associativite> -[W] -[c] < fichier_trace\n", argv[0]);
exit(1);
}
}
numSets = tailleCache * 1024 / (tailleLigne * associativite);
// Initialiser le générateur aléatoire une seule fois
srand(time(NULL));
// Initialiser le cache
creer_struct_cache(&cache, numSets, associativite);
// Démarrer le chrono
start_time = clock();
// Boucle de simulation d'accès au cache
while (scanf("%d %x", &accessType, &adresse) != EOF) {
nbTotalAcces++;
if (accessType == 0 || accessType == 2) {
nbAccesLecture++;
} else {
nbAccesEcriture++;
}
acceder_cache(&cache, adresse, associativite, writeBack, writeAllocate, numSets, accessType, &memoryAccesses, &hitsLecture, &hitsEcriture, &missesLecture, &missesEcriture);
}
// Arrêter le chronomètre
end_time = clock();
cpu_time_used = ((double) (end_time - start_time)) / CLOCKS_PER_SEC; // Calcule le temps écoulé
// Afficher les statistiques du cache
afficher_hits_miss(nbTotalAcces, nbAccesLecture, nbAccesEcriture, memoryAccesses, hitsLecture, hitsEcriture, missesLecture, missesEcriture, cpu_time_used);
// Libérer la mémoire allouée
for (int i = 0; i < numSets; i++) {
free(cache.sets[i].lines);
}
free(cache.sets);
return 0;
}

BIN
traces/.DS_Store vendored Normal file

Binary file not shown.

11
traces/README.md Normal file
View File

@@ -0,0 +1,11 @@
# 📁 Traces
Ce répertoire contient des exemples de fichiers trace utilisés pour le simulateur de cache. Ces fichiers sont essentiels pour tester et valider les performances du simulateur, en fournissant des données d'accès en mémoire.
## 📝 Contenu
- **Fichiers Trace** : Divers fichiers d'exemple générés, qui simulent des accès en mémoire (lectures, écritures et instructions).
## 🛠️ Auteur des fichiers traces
- Denis MONNERAT (Professeur à l'IUT de Fontainebleau)

1001
traces/sample Normal file

File diff suppressed because it is too large Load Diff

48
traces/sample1 Normal file
View File

@@ -0,0 +1,48 @@
0 20d
0 211
0 1fc780
1 7fffccb0
0 213
0 217
0 1fc77c
1 7fffccac
0 219
0 21d
0 1fc778
1 7fffcca8
0 21f
0 223
0 220
1 7fffcca4
0 54
1 7fffcca0
1 7fffcc9c
1 7fffcc98
1 7fffcc94
1 7fffcc90
0 56
0 6a
0 58
0 7fffccb0
1 7fffcc8c
0 5b
0 7fffccac
1 7fffcc88
0 5e
0 7fffcca8
1 7fffcc84
0 61
0 65
0 62
1 7fffcc80
0 531d0
1 7fffcc7c
1 7fffcc78
1 7fffcc74
1 7fffcc70
1 7fffcc6c
0 531d2
0 531d3
0 531d5
0 531d9
0 7fffcc84

832477
traces/sample2 Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
# Générateur de fichiers traces
## 📖 Description
Le programme `trace_generator.c` permet de générer des fichiers de traces d'accès en mémoire, ce qui est utile pour des projets de simulation de cache. Il crée des lignes de traces représentant des lectures et des écritures en mémoire.
## 📦 Compilation
Pour compiler le programme, utilisez la commande suivante :
```bash
gcc -o trace_generator trace_generator.c
```
## ⚙️ Exécution
Pour exécuter le programme, utilisez la ligne de commande suivante :
```bash
./trace_generator -l <total_lines> [-r <read_data_lines>] [-w <write_data_lines>] [-i <read_instruction_lines>] -o <output_file>
```
## 📝 Arguments
* `-l <total_lines>` : **Nombre total de lignes** dans le fichier de trace. (Obligatoire)
Exemple : `-l 100000` -> 100000 lignes de traces
* `-r <read_data_lines>` : **Nombre de lignes de données lues** (type 0). (Optionnel)
Exemple : `-r 30000` -> 30000 lignes de données lues
* `-w <write_data_lines>` : **Nombre de lignes de données écrites** (type 1). (Optionnel)
Exemple : `-w 50000` -> 50000 lignes de données écrites
* `-i <read_instruction_lines>` : **Nombre de lignes d'instructions lues** (type 2). (Optionnel)
Exemple : `-i 20000` -> 20000 lignes d'instructions
* `-o <output_file>` : **Nom du fichier de sortie** où les traces seront écrites. (Obligatoire)
Exemple : `-o trace_file` -> crée le fichier `trace_file`
## 🛠️ Auteur
- Moncef STITI

View File

@@ -0,0 +1,143 @@
/*
* Fichier : trace_generator.c
* Auteur : Moncef STITI
* Date : 04/11/2024
* Version : 1.1
* Description : Ce programme permet de générer des fichiers traces d'accès en mémoire pour un projet de simulation de cache.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#define MAX_LINES 100000000
// Fonction pour générer une adresse mémoire aléatoire
unsigned int generer_adresse() {
// Générer un nombre aléatoire pour l'adresse
// Utiliser un mélange de courtes et longues adresses
if (rand() % 2 == 0) {
return rand() % 0xFFFF; // Adresse courte
} else {
return rand() % 0xFFFFFFFF; // Adresse longue
}
}
void generer_trace(FILE *file, int total_lines, int read_data_lines, int write_data_lines, int read_instruction_lines) {
int line_count = 0;
int type;
unsigned int address;
// Aléatoire pour les adresses
srand(time(NULL));
// Continue jusqu'à ce que nous atteignons total_lines
while (line_count < total_lines) {
// Déterminer le type d'accès à faire
if (read_data_lines > 0 && (rand() % (read_data_lines + write_data_lines + read_instruction_lines)) < read_data_lines) {
type = 0; // Read data
address = generer_adresse(); // Adresse aléatoire
fprintf(file, "%d %x\n", type, address);
read_data_lines--;
} else if (write_data_lines > 0 && (rand() % (read_data_lines + write_data_lines + read_instruction_lines)) < (read_data_lines + write_data_lines)) {
type = 1; // Write data
address = generer_adresse(); // Adresse aléatoire
fprintf(file, "%d %x\n", type, address);
write_data_lines--;
} else if (read_instruction_lines > 0) {
type = 2; // Read instruction
address = generer_adresse(); // Adresse aléatoire
fprintf(file, "%d %x\n", type, address);
read_instruction_lines--;
} else {
// Si tous les types d'accès ont été utilisés, on arrête la génération
break;
}
line_count++;
}
// Si nous avons moins de lignes que total_lines, complétons avec des lignes aléatoires
while (line_count < total_lines) {
type = rand() % 3; // Choisir un type aléatoire
address = generer_adresse(); // Adresse aléatoire
fprintf(file, "%d %x\n", type, address);
line_count++;
}
}
void afficher_usage() {
printf("Utilisation : trace_generator -l <total_lines> [-r <read_data_lines>] [-w <write_data_lines>] [-i <read_instruction_lines>] -o <output_file>\n");
printf(" -l <total_lines> Nombre total de lignes dans le fichier de trace\n");
printf(" -r <read_data_lines> Nombre de lignes de données lues (type 0) [optionnel]\n");
printf(" -w <write_data_lines> Nombre de lignes de données écrites (type 1) [optionnel]\n");
printf(" -i <read_instruction_lines> Nombre de lignes d'instructions lues (type 2) [optionnel]\n");
printf(" -o <output_file> Nom du fichier de sortie\n");
}
int main(int argc, char *argv[]) {
int total_lines = 0;
int read_data_lines = 0;
int write_data_lines = 0;
int read_instruction_lines = 0;
char *output_file = NULL;
int opt;
while ((opt = getopt(argc, argv, "l:r:w:i:o:")) != -1) {
switch (opt) {
case 'l':
total_lines = atoi(optarg);
break;
case 'r':
read_data_lines = atoi(optarg);
break;
case 'w':
write_data_lines = atoi(optarg);
break;
case 'i':
read_instruction_lines = atoi(optarg);
break;
case 'o':
output_file = optarg;
break;
default:
afficher_usage();
return EXIT_FAILURE;
}
}
// Vérification de la validité des arguments
if (total_lines <= 0 || output_file == NULL) {
afficher_usage();
return EXIT_FAILURE;
}
// Vérification que le nombre total de lignes demandées est correct
int total_requested_lines = read_data_lines + write_data_lines + read_instruction_lines;
if (total_requested_lines > total_lines) {
fprintf(stderr, "Erreur : La somme des lignes de données lues (%d), écrites (%d) et d'instructions lues (%d) dépasse le nombre total de lignes (%d).\n",
read_data_lines, write_data_lines, read_instruction_lines, total_lines);
return EXIT_FAILURE;
}
// Si aucun type de ligne n'est précisé, générons une distribution par défaut
if (total_requested_lines == 0) {
// Exemple de distribution : 50% de lectures, 30% d'écritures, 20% d'instructions
read_data_lines = total_lines * 0.5;
write_data_lines = total_lines * 0.3;
read_instruction_lines = total_lines * 0.2;
}
FILE *file = fopen(output_file, "w");
if (file == NULL) {
perror("Erreur : Impossible d'ouvrir le fichier d'output.");
return EXIT_FAILURE;
}
generer_trace(file, total_lines, read_data_lines, write_data_lines, read_instruction_lines);
fclose(file);
printf("Le fichier trace '%s' avec %d lignes a été généré avec succès.\n", output_file, total_lines);
return EXIT_SUCCESS;
}