/* -*- c++ -*-
 *
 * SOCLIB_LGPL_HEADER_BEGIN
 * 
 * This file is part of SoCLib, GNU LGPLv2.1.
 * 
 * SoCLib is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; version 2.1 of the License.
 * 
 * SoCLib is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with SoCLib; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * SOCLIB_LGPL_HEADER_END
 *
 * Copyright (c) UPMC, Lip6, Asim
 *         Nicolas Pouillon <nipo@ssji.net>, 2006
 *
 * Maintainers: nipo
 */
#ifndef SOCLIB_CABA_MULTI_SECBUS_RAM_H
#define SOCLIB_CABA_MULTI_SECBUS_RAM_H

#include <systemc>
#include "vci_target_fsm.h"
#include "caba_base_module.h"
#include "mapping_table.h"
#include "loader.h"
#include <iostream>
#include <fstream>
#include <iomanip>
#include "../../../../vci_secbus/caba/source/include/global.h"
#include "../../../../vci_secbus/caba/source/include/types.h"
#include "../../../../vci_secbus/caba/source/include/secbus_lib.h"
namespace soclib {
namespace caba {

using namespace sc_core;

template<typename vci_param>
class VciSecbusRam
	: public soclib::caba::BaseModule
{
    soclib::caba::VciTargetFsm<vci_param,true,true> m_vci_fsm;
    soclib::common::Loader m_loader;
	typedef unsigned int ram_t;
    ram_t **m_contents;

protected:
	SC_HAS_PROCESS(VciSecbusRam);

public:
    typedef typename vci_param::addr_t vci_addr_t;
    typedef typename vci_param::data_t vci_data_t;

    sc_in<bool> p_resetn;
    sc_in<bool> p_clk;
    soclib::caba::VciTarget<vci_param> p_vci;

    VciSecbusRam(
        sc_module_name insname,
        const IntTab &index,
        const MappingTable &mt,
        const soclib::common::Loader &loader = soclib::common::Loader(),
        int sp_index = 0);
    ~VciSecbusRam();
    void print_stats();



private:
    bool on_write(size_t seg, vci_addr_t addr, vci_data_t data, int be);
    bool on_read( size_t seg, vci_addr_t addr, vci_data_t &data );
    void transition();
    void genMoore();
	void reload();
	void reset();

  int sp_index;
	//master block segment
	unsigned int mb_segment;
	//Security policies number
	unsigned int SP_nbr;
	//Array containing all policies
	int **SP;
	//Array containing all cipher policies
	int *cipherSP;
	//mac/hash
	int *reference;
	//DES block
	int *block;
	//hash/mac set
	int *set;
	//pspe
	int *pspe;
	//pspe
	int *tmp;
	//addresses
	addr_t pspe_address, set_address, parent_address, free_mac_page, free_hash_page; 

  int count_w;
  int count_r;
  int count_h;

	void dump(char W, size_t seg, addr_t addr, int data, int be);
	
	std::ofstream dumper;

	void sp_init();
	void mbht_init();
  void mbht_init2(addr_t first_addr, bool isMasterBlock, PageSize_e ht_page_size, unsigned int n_elems);

	void page_init(size_t segment, addr_t address, int *sp, unsigned int sp_index);
  void page_first_init(size_t segment, addr_t address, unsigned int boundary);
	void cipher_init(size_t segment, addr_t address, unsigned int size_in_bytes, int *key, confidentiality_mode_e confidentiality);
	void mac_init(size_t segment, addr_t address, unsigned int size_in_bytes, int* key);
	void ht_init(size_t segment, addr_t address, unsigned int size_in_bytes);
	void pspe_init(PageSize_e size, unsigned int sp_index, addr_t base_address, PSPEtype_e type, bool);
  void pspe_first_init(PageSize_e size, PSPEtype_e type, addr_t base_address);
	void on_write_debug(size_t segment, addr_t address, int *data, unsigned int size);
	void on_read_debug(size_t segment, addr_t address, int *data, unsigned int size);
	void ht_update(addr_t ht_start_address, PageSize_e ht_page_size, bool master_tree);
	void bc_debug(int * input, int *output, int * key);
	void otp_debug(addr_t address, int * input, int *output, int * key);
	void mac_debug(addr_t address, int * input, int *output, int * key);
	void hash_debug(addr_t address, int * input, int *output, unsigned int size);
  bool isRowOpened(addr_t address);
    void setRLatencies(addr_t address);
    void setWLatencies(addr_t address);

    // Activity counters
    uint64_t m_cpt_read;            // Count READ access
    uint64_t m_cpt_write;           // Count WRITE access
    uint64_t m_cpt_idle;            // Count IDLE Cycles
    uint64_t m_write_latency_cpt;   // Count write latencies in cycles
    uint64_t m_read_latency_cpt;    // Count read latencies in cycles

    addr_t  previous_row;
	//latency parameters
	//delay between registration of READ command and the avaibility of the first piece of data
	int tCAS;
	//delay used to close a row
	int tPRECHARGE;
	//delay used to open a row
	int tACTIVE;
};

}}

#endif /* SOCLIB_CABA_MULTI_RAM_H */

// Local Variables:
// tab-width: 4
// c-basic-offset: 4
// c-file-offsets:((innamespace . 0)(inline-open . 0))
// indent-tabs-mode: nil
// End:

// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4

