Ajouts des différents programmes et ajout des fichiers readme.md
This commit is contained in:
48
README.md
48
README.md
@@ -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
59
lru/README.md
Normal 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
729
lru/cache.c
Normal file
File diff suppressed because it is too large
Load Diff
58
random/README.md
Normal file
58
random/README.md
Normal 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
417
random/cache.c
Normal 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
BIN
traces/.DS_Store
vendored
Normal file
Binary file not shown.
11
traces/README.md
Normal file
11
traces/README.md
Normal 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
1001
traces/sample
Normal file
File diff suppressed because it is too large
Load Diff
48
traces/sample1
Normal file
48
traces/sample1
Normal 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
832477
traces/sample2
Normal file
File diff suppressed because it is too large
Load Diff
38
traces_generator/README.md
Normal file
38
traces_generator/README.md
Normal 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
|
143
traces_generator/trace_generator.c
Normal file
143
traces_generator/trace_generator.c
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user