#ifndef CACHE_STORE_H
#define CACHE_STORE_H
#include <list>
#include "address.h"

using namespace std;

typedef enum associativity {
    FULLY_ASSOCIATIVE = 0,
    DIRECT_MAPPING = 1,
    WAY_2 = 2,
    WAY_4 = 4,
    WAY_8 = 8
} t_assoc;

class CacheStore {

    private:
        unsigned int cache_size;
        unsigned int line_width;
        t_assoc associativity;
        unsigned int num_lines;
        unsigned int num_sets;

        // loaded cache lines : stores  
        list<int> *cache_lines;

    public:
        CacheStore( int cache_size, 
                    int line_width, 
                    t_assoc associativity ) {

            // attributes initialization
            this->cache_size = cache_size;
            this->line_width = line_width;
            this->associativity = associativity;

            this->num_lines = cache_size / line_width;
            if (associativity != FULLY_ASSOCIATIVE)
                this->num_sets = num_lines / associativity;
            else
                this->num_sets = 1;
            this->cache_lines = new list<int>[num_sets];

            // cache lines array initialization
            for (unsigned int i=0; i < num_sets; i++) {
                cache_lines[i] = list<int>();
            }

            // Print parameters
            cout << ">>> parameters:" << endl;
            cout << "       cache_size = " << cache_size << endl;
            cout << "       line_width = " << line_width << endl;
            cout << "       associativity = " << associativity << endl;
            cout << "       number of lines = " << num_lines << endl << endl;
        }

        //bool is_loaded(list<int> *lines, int line);
        bool is_loaded(Address address);

        //void do_load(list<int> *lines, int line);
        void do_load(Address address);

        int get_line_width();

        ~CacheStore() {
            delete [] cache_lines;
        }
};

#endif
