#ifndef ADDRESS_H_
#define ADDRESS_H_

#include <systemc.h>
#include <iomanip>
#include <iostream>
#include "raw_address.h"

class Address {
    public:
        unsigned int block_size;
        unsigned int block;
        unsigned int displacement;

        // default constructor
        Address (const unsigned int block = 0, const unsigned long displacement = 0, const unsigned int block_size = 0) {
            this->block = block;
            this->displacement = displacement;
            this->block_size = block_size;
        }

        Address (const RawAddress req, const int block_size)
        {
            this->block = req.address / block_size;
            this->displacement = req.address % block_size;
            this->block_size = block_size;
        }

        inline bool operator == (const Address & rhs) const {
            return (rhs.block * rhs.block_size + rhs.displacement == block * block_size + displacement );
        }

        inline Address& operator = (const Address& rhs) {
            block = rhs.block;
            block_size = rhs.block_size;
            displacement = rhs.displacement;
            return *this;
        }

        inline friend void sc_trace(sc_trace_file *tf, const Address & v, const std::string & NAME ) {
            // FIXME
            //  sc_trace(tf,v.block, NAME + ".info");
            //  sc_trace(tf,v.displacement, NAME + ".flag");
        }

        inline friend ostream& operator << ( ostream& os,  Address const & v ) {
            os << "0x" << hex << std::setfill('0') << std::setw(8) <<  (v.block * v.block_size + v.displacement) ;
            return os;
        }

        inline bool operator < (const Address & rhs) const {
            return (rhs.block * rhs.block_size + rhs.displacement < block * block_size + displacement); 
        }

        inline const unsigned int as_absolute() {
            return (block * block_size + displacement);
        }

};
#endif


