/*
 * $Id$
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Generic/RegisterFile/RegisterFile_Multi_Banked/include/Parameters.h"
#include "Common/include/BitManipulation.h"

namespace morpheo {
namespace behavioural {
namespace generic {
namespace registerfile {
namespace registerfile_multi_banked {


  Parameters::Parameters (uint32_t    nb_port_read         ,
			  uint32_t    nb_port_write        ,
			  uint32_t    nb_word              ,
			  uint32_t    size_word            ,
			  uint32_t    nb_bank              ,
			  uint32_t    nb_port_read_by_bank ,
			  uint32_t    nb_port_write_by_bank,
			  Tcrossbar_t crossbar             ):
    _nb_port_read          (nb_port_read         ),
    _nb_port_write         (nb_port_write        ),
    _nb_word               (nb_word              ),
    _size_word             (size_word            ),
    _nb_bank               (nb_bank              ),
    _nb_port_read_by_bank  (nb_port_read_by_bank ),
    _nb_port_write_by_bank (nb_port_write_by_bank),
    _crossbar              (crossbar             ),
    _size_address          (static_cast<uint32_t>(ceil(log2(_nb_word)))),
    _size_address_by_bank  (_size_address - static_cast<uint32_t>(ceil(log2(_nb_bank)))),

    // Address : [....................]  [size_address-1:0]
    // Bank    : [....]                  [size_address-1:size_address-1-log2(nb_bank)]
    // num_reg :      ]...............]  [size_address-2-log2(nb_bank):0]
    _bank_shift            (_size_address_by_bank),
    _bank_mask             (gen_mask<Taddress_t>(static_cast<Taddress_t>(ceil(log2(_nb_bank))))),
    _num_reg_shift         (0),
    _num_reg_mask          (gen_mask<Taddress_t>(_size_address_by_bank)),
    _nb_word_by_bank       (_nb_word / _nb_bank),
    _have_port_address     (_size_address         != 0),
    _have_bank_port_address(_size_address_by_bank != 0)
  {
    log_printf(FUNC,RegisterFile_Multi_Banked,"Parameters","Begin");

    if (_crossbar == PARTIAL_CROSSBAR)
      {
	log_printf(TRACE,RegisterFile_Multi_Banked,"Parameters","Case : _crossbar == PARTIAL_CROSSBAR");

	// All port_src is connected with one port_dest on each bank
	
	_link_port_read_to_bank_read     = new uint32_t [_nb_port_read ];
	_link_port_write_to_bank_write   = new uint32_t [_nb_port_write];

	// init
	for (uint32_t i=0; i<_nb_port_read ;i++)
	  {
	    uint32_t x = i%_nb_port_read_by_bank;
	    _link_port_read_to_bank_read [i] = x;
	  }
	for (uint32_t i=0; i<_nb_port_write;i++)
	  {
	    uint32_t x = i%_nb_port_write_by_bank;
	    _link_port_write_to_bank_write   [i] = x;
	  }


	log_printf(TRACE,RegisterFile_Multi_Banked,"Parameters"," * _link_port_read_to_bank_read");
	for (uint32_t i=0; i<_nb_port_read         ;i++)
	  {
	    log_printf(TRACE,RegisterFile_Multi_Banked,"Parameters","   * Read  in  [%d] to out    [%d]",i,_link_port_read_to_bank_read          [i]);
	  }
	log_printf(TRACE,RegisterFile_Multi_Banked,"Parameters"," * _link_port_write_to_bank_write");
	for (uint32_t i=0; i<_nb_port_write        ;i++)
	  {
	    log_printf(TRACE,RegisterFile_Multi_Banked,"Parameters","   * Write in  [%d] to out    [%d]",i,_link_port_write_to_bank_write          [i]);
	  }
      }
    // else : don't allocate

    test();
    log_printf(FUNC,RegisterFile_Multi_Banked,"Parameters","End");
  };
  
  Parameters::Parameters (Parameters & param):
    _nb_port_read          (param._nb_port_read         ),
    _nb_port_write         (param._nb_port_write        ),
    _nb_word               (param._nb_word              ),
    _size_word             (param._size_word            ),
    _nb_bank               (param._nb_bank              ),
    _nb_port_read_by_bank  (param._nb_port_read_by_bank ),
    _nb_port_write_by_bank (param._nb_port_write_by_bank),
    _crossbar              (param._crossbar             ),
    _size_address          (param._size_address         ),
    _size_address_by_bank  (param._size_address_by_bank ),
    _bank_shift            (param._bank_shift           ),
    _bank_mask             (param._bank_mask            ),
    _num_reg_shift         (param._num_reg_shift        ),
    _num_reg_mask          (param._num_reg_mask         ),
    _nb_word_by_bank       (param._nb_word_by_bank      ),
    _have_port_address     (param._have_port_address     ),
    _have_bank_port_address(param._have_bank_port_address)
  {
    log_printf(FUNC,RegisterFile_Multi_Banked,"Parameters (copy)","Begin");

    if (_crossbar == PARTIAL_CROSSBAR)
      {
	// All port_src is connected with one port_dest on each bank
	
	_link_port_read_to_bank_read     = new uint32_t [_nb_port_read ];
// 	_link_port_read_to_num_bank         = new uint32_t [_nb_port_read ];
	_link_port_write_to_bank_write   = new uint32_t [_nb_port_write];
// 	_link_port_write_to_num_bank        = new uint32_t [_nb_port_write];

	for (uint32_t i=0; i<_nb_port_read         ;i++)
	  {
	    _link_port_read_to_bank_read   [i] = param._link_port_read_to_bank_read     [i];
// 	    _link_port_read_to_num_bank       [i] = param._link_port_read_to_num_bank    [i];
	  }
	for (uint32_t i=0; i<_nb_port_write        ;i++)
	  {
	    _link_port_write_to_bank_write [i] = param._link_port_write_to_bank_write    [i];
// 	    _link_port_write_to_num_bank      [i] = param._link_port_write_to_num_bank   [i];
	  }
      }

    test();
    log_printf(FUNC,RegisterFile_Multi_Banked,"Parameters (copy)","End");
  };

  Parameters::~Parameters () 
  {
    log_printf(FUNC,RegisterFile_Multi_Banked,"~Parameters","Begin");

    if (_crossbar == PARTIAL_CROSSBAR)
      {
	delete [] _link_port_read_to_bank_read    ;
// 	delete [] _link_port_read_to_num_bank   ;
	delete [] _link_port_write_to_bank_write   ;
// 	delete [] _link_port_write_to_num_bank  ;
      }
    log_printf(FUNC,RegisterFile_Multi_Banked,"~Parameters","End");
  };

}; // end namespace registerfile_multi_banked
}; // end namespace registerfile
}; // end namespace generic

}; // end namespace behavioural
}; // end namespace morpheo              
