#ifndef L2CACHE_H_
#define L2CACHE_H_

#include <systemc.h>
#include "address.h"
#include "queue.h"
#include "processing_queue.h"
#include "cache_store.h"

SC_MODULE(L2Cache)
{
    // clock
    sc_in_clk clock;

    // signal request from l1
    sc_in <RawAddress> in_data;
    sc_in <bool> in_activate;

    sc_out <RawAddress> out_data;
    sc_out <bool> out_activate;

    // XXX temporary signal for out information (for monitoring)
    sc_out<bool> miss_info;
    sc_out<bool> hit_info;

    // Queue de sortie : pour limiter le nombre de requetes simultannées 
    Queue<Address> *output_queue;

    // CacheStore : contient les lignes actuellement stockées dans le cache
    CacheStore *cstore;

    // Processing queue : timeout interne pour l'envoi de données
    // qui sont chargées dans ce cache
    ProcessingQueue *processing_queue;

    // Latence : délai nécesaire pour temporiser l'envoi de données
    // chargées dans ce cache
    unsigned int latency;
    
    // methods for handling memory requests (systemc)
    void read();
    void write();

    L2Cache(sc_module_name name, 
            int cache_size, 
            int line_width, 
            t_assoc associativity,
            unsigned int latency) : sc_module(name)
    {
        this->cstore = new CacheStore(cache_size, line_width, associativity);
        this->latency = latency;
        this->output_queue = new Queue<Address>(10);
        this->processing_queue = new ProcessingQueue(10);

        SC_METHOD(read);
        dont_initialize();
        sensitive << clock.pos();

        SC_METHOD(write);
        dont_initialize();
        sensitive << clock.pos();
    };

    SC_HAS_PROCESS(L2Cache);

    ~L2Cache()
    {
        delete output_queue;
        delete processing_queue;
        delete cstore;
    }
};

#endif
