/* -*- 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
 *
 *
 */

#ifndef SOCLIB_CRYPTO_H
#define SOCLIB_CRYPTO_H

#include <systemc>

#include "caba_base_module.h"
#include "vci_target_fsm.h"
#include "vci_target.h"
#include "mapping_table.h"
#include "vci_initiator_fsm.h"
#include "crypto_regs.h"
#include <openssl/aes.h>

#define ecb 0 
#define cbc 1 
#define AES_ENGINE_COUNT 50 
#define AES_ENGINE_WIDTH 16 

namespace soclib {
	namespace caba {

using namespace sc_core;

template<typename vci_param>
class Crypto : public soclib::caba::BaseModule
{
protected:
  SC_HAS_PROCESS(Crypto);

private:
  soclib::caba::VciTargetFsm<vci_param, true> vci_target_fsm;
  soclib::caba::VciInitiatorFsm<vci_param> vci_init_fsm;
  typedef typename soclib::caba::VciInitiatorReq<vci_param> req_t;

  bool on_write(int seg, typename vci_param::addr_t addr, typename vci_param::data_t data, int be);
  bool on_read(int seg, typename vci_param::addr_t addr, typename vci_param::data_t &data);

  void crypto_process();
  void decyphering();
  void genMoore();
  void transition();
  void next_req();
  void ended(uint32_t error);
  void read_done(req_t *req );
  void write_done(req_t *req );
  void aes_process(bool enc, uint32_t size, uint32_t mode);

  uint8_t * _buffer;

  bool _handling;
  bool _must_finish;
  bool _crypto_start;

  ssize_t _burst;
  uint32_t _start;
  uint32_t _rirqen;
  uint32_t _bsize;
  uint32_t _rirq;
  uint32_t _crypto_count;
  uint32_t _offset;
  uint32_t _rstatus;
  uint32_t _rsrc;
  uint32_t _rdst;
  uint32_t _rlen;
  uint32_t _rcfg;
  uint32_t _rkey[SOCLIB_CRYPTO_KEY_COUNT];
  uint32_t _riv[SOCLIB_CRYPTO_IV_COUNT];

public:
  sc_in<bool> srstn;
  sc_in<bool> clk;
  sc_out<bool> irq;
  soclib::caba::VciTarget<vci_param> vci_target;
  soclib::caba::VciInitiator<vci_param> vci_initiator;

  Crypto(sc_module_name name,
      const soclib::common::MappingTable &mt,
      const soclib::common::IntTab &srcid,
      const soclib::caba::IntTab &tgtid,
      const size_t burst_size);

};

}
}
#endif
