/*
 * SecBus - This file is part of SecBus
 * Copyright (C) 2012 - Telecom ParisTech
 * 
 * This file must be used under the terms of the CeCILL.
 * This source file is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at    
 * http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.txt
 *
 */

#include "registers.h"
#include "global.h"

DataRegister::DataRegister(sc_module_name name):
  sc_module(name),
  p_clk("p_clk"),
  p_resetn("p_resetn")
{
  SC_METHOD(transition);
  sensitive << p_clk.pos();
  SC_METHOD(genMoore);
  sensitive << p_clk.neg();

  data_s = new sc_signal<int> [SIZE_256_IN_WORDS];
  
  DEBUG(NONE, STD, "[SECBUS] Building Register (%s)\n", basename());
}

DataRegister::~DataRegister()
{
  delete data_s;
}

void DataRegister::transition()
{
  if (!p_resetn.read()) 
  {
    address_s = 0xFFFFFFFF;
    be_s = 0;
    for(unsigned int i=0;i<SIZE_256_IN_WORDS;i++)
      data_s[i] = 0;
    return;
  }

  if (in.enable) 
  {	
    if (in.flush)
    {
      address_s	= 0xFFFFFFFF;
      be_s = 0;
      for(unsigned int i=0;i<SIZE_256_IN_WORDS;i++)
        data_s[i] = 0;
    }
    else
    {
      int data_v;
      //set data
      for (unsigned int j=0;j<SIZE_256_IN_WORDS;j++)
      {
        data_v = data_s[j];

        for (unsigned int u=0;u<4;u++)
        {
          if ((((in.be.read()>>(j*4)) & 0xF) & (0x1<<u))!= 0)
	  {
            data_v = (data_v & ~(0xFF<<(u*8))) | (in.data[j] & (0xFF<<(u*8)));
	  }
        }
        data_s[j] = data_v;	
      }

      //set be
      be_s = be_s | in.be;

      //set address
      address_s = aligned(in.address, SIZE_256_IN_BYTES);
    }
  }
}

void DataRegister::genMoore()
{
  out.be = be_s;
  out.address = address_s;
  for(unsigned int i=0;i<SIZE_256_IN_WORDS;i++)
    out.data[i] = data_s[i];
}
