#include "l1cache.h"

// TODO il manque un signal pour faire des requetes au L2

void L1Cache::read()
{
    // On donne la priorité aux éléments en attente :
    //      - si des éléments sont présents dans la file d'attente
    //          on les envoie
    //      - TODO on doit pouvoir les packer pour pouvoir les envoyer par deux
    //      - si aucun élément n'est présent dans la liste, on arrête d'envoyer (in_activate = false)
    // indépendemment,
    //      - si on recoit un élement, on regarde s'il est chargé dans le cache:
    //          - si il est chargé, on le place dans la liste des addresses à envoyer,
    //              on attend un moment timeout avant de l'envoyer
    //          - si il n'est pas chargé, on envoit une requete au cache L2,
    //              on le place dans la liste des addresses à envoyer.
    //      - XXX le timeout devrait peut etre etre effectué, meme pour les données non présentes dans le L1

    miss_info = false;
    hit_info = false;
    out_activate = false;
    
   
    // Est-ce que des élements sont chargés dans ce cache, et prêts à être envoyés ? 
    Address *head = processing_queue->get_next_ready(); 
    if (head != NULL) // oui
    {
        cout << "has ready elements  : " << *head <<  endl;
        cstore->do_load(*head);

        // Envoi de la réponse au processeur
        RawAddress req(head->as_absolute());
        out_activate = true;
        out_data = req;

    // Sinon, est-ce qu'on est en train de faire une requête ?
    } else if (in_activate) {

        // Retrieves the address
        RawAddress req = in_data;
        Address element(req, cstore->get_line_width());

        //  rappel : processing queue c'est le chargement interne. Si un élement
        //  est déjà chargé dans le cache, il va dans la processing queue,
        //  sinon, il part en requete dans le L2
        //
        //
        // Si la donnée est chargée dans le cache
        if (cstore->is_loaded(element)) {
            processing_queue->insert(element, latency);
            hit_info = true;

            // affichage de l'action
            cout << sc_time_stamp() << " L1Cache : access to data [" << element << "]  -> hit ... [start loading]" << endl;

        } else {
            // XXX requete a un module exterieur

            // affichage de l'action
            cout << sc_time_stamp() << " L1Cache : access to data [" << element << "]  -> miss" << endl; 

            out_data = in_data;
            miss_info = true;
        }
    }

    
    if (!in_activate && processing_queue->is_empty()) {
        out_activate = false;
    }

    processing_queue->update_time();
    
}


void L1Cache::write()
{
    // cout << sc_time_stamp() << " L1Cache.write()" << endl;
}
