#ifdef SYSTEMC
/*
 * $Id: Multiplier_transition.cpp 116 2009-04-30 13:51:41Z moulu $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Generic/Multiplier/include/Multiplier.h"

namespace morpheo                    {
namespace behavioural {
namespace generic {
namespace multiplier {


#undef  FUNCTION
#define FUNCTION "Multiplier::transition"
  void Multiplier::transition (void)
  {
    log_begin(Multiplier,FUNCTION);
    
    // Test if stall
    if (PORT_READ(in_MULTIPLIER_NSTALL))
      {
        // Pop a slot of array
        for (uint32_t i=1;i<_pipeline->size();i++)
          _pipeline->at(i-1)=_pipeline->at(i);

        result_t data;
        
        switch (_param->_size_data)
          {
          case 8 :
            {
              if (_param->_sign) // 0 = signed, 1 = unsigned
                {
                  sc_uint<8> data_0 = static_cast<sc_uint<8> >(PORT_READ(in_MULTIPLIER_DATA_IN_0));
                  sc_uint<8> data_1 = static_cast<sc_uint<8> >(PORT_READ(in_MULTIPLIER_DATA_IN_1));
                  sc_uint<16> tmp    = (static_cast<sc_uint<16> >(data_0) * 
                                        static_cast<sc_uint<16> >(data_1));
                  
                  data.LSB = static_cast<Tdata_t>(_param->_mask &  tmp);
                  data.MSB = static_cast<Tdata_t>(_param->_mask & (tmp>>8));
                  
//                   std::cout << "uint8 : data_0 : " << std::hex << data_0 << std::dec << std::endl;
//                   std::cout << "uint8 : data_1 : " << std::hex << data_1 << std::dec << std::endl;
//                   std::cout << "uint8 : tmp    : " << std::hex << tmp << std::dec << std::endl;
//                   std::cout << "uint8 : lsb    : " << std::hex << data.LSB << std::dec << std::endl;
//                   std::cout << "uint8 : msb    : " << std::hex << data.MSB << std::dec << std::endl;
                  
//                   log_printf(TRACE,Multiplier,FUNCTION,"  * signed");
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data0 = %llx(%lld)",data_0, data_0);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data1 = %llx(%lld)",data_1, data_1);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * res   = %llx(%lld)",tmp, tmp);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * LSB   = %x (%d)",data.LSB, data.LSB);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * MSB   = %x (%d)",data.MSB, data.MSB);
                }
              else
                {
                  sc_int<8> data_0 = static_cast<sc_int<8> >(PORT_READ(in_MULTIPLIER_DATA_IN_0));
                  sc_int<8> data_1 = static_cast<sc_int<8> >(PORT_READ(in_MULTIPLIER_DATA_IN_1));
                  sc_int<16> tmp    = (static_cast<sc_int<16> >(data_0) * 
                                       static_cast<sc_int<16> >(data_1));
                  
                  data.LSB = static_cast<Tdata_t>(_param->_mask &  tmp);
                  data.MSB = static_cast<Tdata_t>(_param->_mask & (tmp>>8));
                  
//                   std::cout << "int8 : data_0 : " << std::hex << data_0 << std::dec << std::endl;
//                   std::cout << "int8 : data_1 : " << std::hex << data_1 << std::dec << std::endl;
//                   std::cout << "int8 : tmp    : " << std::hex << tmp << std::dec << std::endl;
//                   std::cout << "int8 : lsb    : " << std::hex << data.LSB << std::dec << std::endl;
//                   std::cout << "int8 : msb    : " << std::hex << data.MSB << std::dec << std::endl;
                  
//                   log_printf(TRACE,Multiplier,FUNCTION,"  * signed");
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data0 = %llx(%lld)",data_0, data_0);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data1 = %llx(%lld)",data_1, data_1);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * res   = %llx(%lld)",tmp, tmp);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * LSB   = %x (%d)",data.LSB, data.LSB);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * MSB   = %x (%d)",data.MSB, data.MSB);
                }
              break;
            }
          case 16 :
            {
              if (_param->_sign) // 0 = signed, 1 = unsigned
                {
                  sc_uint<16> data_0 = static_cast<sc_uint<16> >(PORT_READ(in_MULTIPLIER_DATA_IN_0));
                  sc_uint<16> data_1 = static_cast<sc_uint<16> >(PORT_READ(in_MULTIPLIER_DATA_IN_1));
                  sc_uint<32> tmp    = (static_cast<sc_uint<32> >(data_0) * 
                                        static_cast<sc_uint<32> >(data_1));
                  
                  data.LSB = static_cast<Tdata_t>(_param->_mask &  tmp);
                  data.MSB = static_cast<Tdata_t>(_param->_mask & (tmp>>16));
                  
//                   std::cout << "uint16 : data_0 : " << std::hex << data_0 << std::dec << std::endl;
//                   std::cout << "uint16 : data_1 : " << std::hex << data_1 << std::dec << std::endl;
//                   std::cout << "uint16 : tmp    : " << std::hex << tmp << std::dec << std::endl;
//                   std::cout << "uint16 : lsb    : " << std::hex << data.LSB << std::dec << std::endl;
//                   std::cout << "uint16 : msb    : " << std::hex << data.MSB << std::dec << std::endl;
                  
//                   log_printf(TRACE,Multiplier,FUNCTION,"  * signed");
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data0 = %llx(%lld)",data_0, data_0);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data1 = %llx(%lld)",data_1, data_1);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * res   = %llx(%lld)",tmp, tmp);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * LSB   = %x (%d)",data.LSB, data.LSB);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * MSB   = %x (%d)",data.MSB, data.MSB);
                }
              else
                {
                  sc_int<16> data_0 = static_cast<sc_int<16> >(PORT_READ(in_MULTIPLIER_DATA_IN_0));
                  sc_int<16> data_1 = static_cast<sc_int<16> >(PORT_READ(in_MULTIPLIER_DATA_IN_1));
                  sc_int<32> tmp    = (static_cast<sc_int<32> >(data_0) * 
                                       static_cast<sc_int<32> >(data_1));
                  
                  data.LSB = static_cast<Tdata_t>(_param->_mask &  tmp);
                  data.MSB = static_cast<Tdata_t>(_param->_mask & (tmp>>16));
                  
                  std::cout << "int16 : data_0 : " << std::hex << data_0   << std::dec << " - dec : " << data_0 << std::endl;
                  std::cout << "int16 : data_1 : " << std::hex << data_1   << std::dec << " - dec : " << data_1 << std::endl;
                  std::cout << "int16 : tmp    : " << std::hex << tmp      << std::dec << " - dec : " << tmp    << std::endl;
                  std::cout << "int16 : lsb    : " << std::hex << data.LSB << std::dec << std::endl;
                  std::cout << "int16 : msb    : " << std::hex << data.MSB << std::dec << std::endl;
                  
//                   log_printf(TRACE,Multiplier,FUNCTION,"  * signed");
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data0 = %llx(%lld)",data_0, data_0);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data1 = %llx(%lld)",data_1, data_1);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * res   = %llx(%lld)",tmp, tmp);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * LSB   = %x (%d)",data.LSB, data.LSB);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * MSB   = %x (%d)",data.MSB, data.MSB);
                }
              break;
            }
          case 32 :
            {
              if (_param->_sign) // 0 = signed, 1 = unsigned
                {
                  sc_uint<32> data_0 = static_cast<sc_uint<32> >(PORT_READ(in_MULTIPLIER_DATA_IN_0));
                  sc_uint<32> data_1 = static_cast<sc_uint<32> >(PORT_READ(in_MULTIPLIER_DATA_IN_1));
                  sc_uint<64> tmp    = (static_cast<sc_uint<64> >(data_0) * 
                                        static_cast<sc_uint<64> >(data_1));
                  
                  data.LSB = static_cast<Tdata_t>(_param->_mask &  tmp);
                  data.MSB = static_cast<Tdata_t>(_param->_mask & (tmp>>32));
                  
//                   std::cout << "uint32 : data_0 : " << std::hex << data_0 << std::dec << std::endl;
//                   std::cout << "uint32 : data_1 : " << std::hex << data_1 << std::dec << std::endl;
//                   std::cout << "uint32 : tmp    : " << std::hex << tmp << std::dec << std::endl;
//                   std::cout << "uint32 : lsb    : " << std::hex << data.LSB << std::dec << std::endl;
//                   std::cout << "uint32 : msb    : " << std::hex << data.MSB << std::dec << std::endl;
                  
//                   log_printf(TRACE,Multiplier,FUNCTION,"  * signed");
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data0 = %llx(%lld)",data_0, data_0);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data1 = %llx(%lld)",data_1, data_1);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * res   = %llx(%lld)",tmp, tmp);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * LSB   = %x (%d)",data.LSB, data.LSB);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * MSB   = %x (%d)",data.MSB, data.MSB);
                }
              else
                {
                  sc_int<32> data_0 = static_cast<sc_int<32> >(PORT_READ(in_MULTIPLIER_DATA_IN_0));
                  sc_int<32> data_1 = static_cast<sc_int<32> >(PORT_READ(in_MULTIPLIER_DATA_IN_1));
                  sc_int<64> tmp    = (static_cast<sc_int<64> >(data_0) * 
                                       static_cast<sc_int<64> >(data_1));
                  
                  data.LSB = static_cast<Tdata_t>(_param->_mask &  tmp);
                  data.MSB = static_cast<Tdata_t>(_param->_mask & (tmp>>32));
                  
//                   std::cout << "int32 : data_0 : " << std::hex << data_0 << std::dec << std::endl;
//                   std::cout << "int32 : data_1 : " << std::hex << data_1 << std::dec << std::endl;
//                   std::cout << "int32 : tmp    : " << std::hex << tmp << std::dec << std::endl;
//                   std::cout << "int32 : lsb    : " << std::hex << data.LSB << std::dec << std::endl;
//                   std::cout << "int32 : msb    : " << std::hex << data.MSB << std::dec << std::endl;
                  
//                   log_printf(TRACE,Multiplier,FUNCTION,"  * signed");
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data0 = %llx(%lld)",data_0, data_0);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * data1 = %llx(%lld)",data_1, data_1);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * res   = %llx(%lld)",tmp, tmp);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * LSB   = %x (%d)",data.LSB, data.LSB);
//                   log_printf(TRACE,Multiplier,FUNCTION,"    * MSB   = %x (%d)",data.MSB, data.MSB);
                }
              break;
            }
          default :
            {
              break;
            }
          }
        
        _pipeline->at(_param->_latency-1) = data;
        
      }
    
#if defined(STATISTICS) or defined(VHDL_TESTBENCH)
    end_cycle ();
#endif
    
    log_end(Multiplier,FUNCTION);
  };

}; // end namespace multiplier
}; // end namespace generic

}; // end namespace behavioural
}; // end namespace morpheo              
#endif
