/*****************************************************************************

  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
  more contributor license agreements.  See the NOTICE file distributed
  with this work for additional information regarding copyright ownership.
  Accellera licenses this file to you under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with the
  License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  implied.  See the License for the specific language governing
  permissions and limitations under the License.

 *****************************************************************************/

#ifndef __SIMPLESWITCHAT_H__
#define __SIMPLESWITCHAT_H__

#include "tlm.h"

#include "tlm_utils/multi_passthrough_initiator_socket.h"
#include "tlm_utils/multi_passthrough_target_socket.h"
#include "simpleAddressMap.h"
#include "extensionPool.h"
#include "tlm_utils/instance_specific_extensions.h"
#include "tlm_utils/peq_with_cb_and_phase.h"


/*
This class is a simple crossbar switch through which an arbitrary number of initiators
may communicate in parallel as long as they do not talk to the same target.

If two requestors address the same target at the same point of time,
the choice who will be allowed to communicate
is done non-deterministically (based on the SystemC process exectution order).

This could be avoided by changing the fwPEQ into a priority PEQ of some kind.

The switch ensures that the end_req and end_resp rules are not violated when
many initiator talk to the same target.
*/
class MultiSocketSimpleSwitchAT : public sc_core::sc_module, public tlm::tlm_mm_interface
{
public:
  typedef tlm::tlm_generic_payload                                 transaction_type;
  typedef tlm::tlm_phase                                           phase_type;
  typedef tlm::tlm_sync_enum                                       sync_enum_type;
  typedef tlm_utils::multi_passthrough_target_socket<MultiSocketSimpleSwitchAT>    target_socket_type;
  typedef tlm_utils::multi_passthrough_initiator_socket<MultiSocketSimpleSwitchAT> initiator_socket_type;

public:
  target_socket_type target_socket; //the target multi socket

private:
  initiator_socket_type initiator_socket; //the initiator multi socket (private to enforce use of bindTarget function)
  SimpleAddressMap m_addrMap; //a pretty simple address map
  std::vector<std::deque<transaction_type*> > m_pendingReqs; //list of pending reqs per target
  std::vector<std::deque<transaction_type*> > m_pendingResps; //list of pending resps per initiator
  std::vector<sc_dt::uint64> m_masks; //address masks for each target
  tlm_utils::instance_specific_extension_accessor accessMySpecificExtensions; //extension accessor to access private extensions
  tlm_utils::peq_with_cb_and_phase<MultiSocketSimpleSwitchAT> m_bwPEQ; //PEQ in the fw direction
  tlm_utils::peq_with_cb_and_phase<MultiSocketSimpleSwitchAT> m_fwPEQ; //PEQ in the bw direction


  //an instance specific extension that tells us whether we are in a wrapped b_transport or not
  class BTag : public tlm_utils::instance_specific_extension<BTag>{
  public:
    sc_core::sc_event event; //trigger this event when transaction is done
  };

  //an instance specific extension that holds information about source and sink of a txn
  // as well as information if the req still has to be cleared and if the txn is already
  //  complete on the target side
  class ConnectionInfo : public tlm_utils::instance_specific_extension<ConnectionInfo>{
    public:
    unsigned int  fwID; //socket number of sink
    unsigned int  bwID; //socket number of source
    bool clearReq;      //is the txn still in req phase?
    bool alreadyComplete; //has the txn already completed on the target side?
  };

  class internalPEQTypes{ //use the tpPEQ to delay connection infos
    public:
    typedef ConnectionInfo tlm_payload_type;
    typedef tlm::tlm_phase tlm_phase_type;
  };
  ExtensionPool<ConnectionInfo> m_connInfoPool; //our pool of extensions
  unsigned int m_target_count;  //number of connected targets (see bindTargetSocket for explanation)

public:
  SC_HAS_PROCESS(MultiSocketSimpleSwitchAT);
  MultiSocketSimpleSwitchAT(sc_core::sc_module_name name) :
    sc_core::sc_module(name),
    target_socket("target_socket"),
    initiator_socket("initiator_socket"),
    m_bwPEQ(this, &MultiSocketSimpleSwitchAT::bwPEQcb),
    m_fwPEQ(this, &MultiSocketSimpleSwitchAT::fwPEQcb),
    m_connInfoPool(10),
    m_target_count(0)
  {
    target_socket.register_nb_transport_fw(this, &MultiSocketSimpleSwitchAT::initiatorNBTransport);
    target_socket.register_b_transport(this, &MultiSocketSimpleSwitchAT::b_transport);
    initiator_socket.register_nb_transport_bw(this, &MultiSocketSimpleSwitchAT::targetNBTransport);
  }

  void bindTargetSocket(initiator_socket_type::base_target_socket_type& target
                       ,sc_dt::uint64 low
                       ,sc_dt::uint64 high
                       ,sc_dt::uint64 mask = 0xffffffffffffffffULL){
    initiator_socket(target); //bind sockets
    //insert into address map and increase target count
    // (we have to count the targets manually, because target_socket.size() is only reliable during simulation
    //  as it gets evaluated during end_of_elaboration)
    m_addrMap.insert(low, high, m_target_count++);
    m_masks.push_back(mask); //add the mask for this target
  }

  unsigned int decode(const sc_dt::uint64& address)
  {
    return m_addrMap.decode(address);
  }

  void start_of_simulation(){
    //initialize the lists of pending reqs and resps
    m_pendingReqs.resize(initiator_socket.size());
    m_pendingResps.resize(target_socket.size());
  }


  void b_transport(int initiator_id, transaction_type& trans, sc_core::sc_time& t){
    //first make sure that there is no BTag (just for debugging)
    BTag* btag;
    accessMySpecificExtensions(trans).get_extension(btag);
    sc_assert(!btag);
    BTag tag; //now add our BTag
    bool added_mm=!trans.has_mm(); //in case there is no MM in we add it now
    if (added_mm){
      trans.set_mm(this);
      trans.acquire(); //acquire the txn
    }
    accessMySpecificExtensions(trans).set_extension(&tag);
    phase_type phase=tlm::BEGIN_REQ; //then simply use our nb implementation (respects all the rules)
    initiatorNBTransport(initiator_id, trans, phase, t);
    wait(tag.event); //and wait for the event to be triggered
    if (added_mm){  //if we added MM
      trans.release(); //we release our reference (this will not delete the txn but trigger the tag.event as soon as the ref count is zero)
      if (trans.get_ref_count())
        wait(tag.event); //wait for the ref count to get to zero
      trans.set_mm(NULL); //remove the MM
    }
    //don't forget to remove the extension (instance specific extensions are not cleared off by MM)
    accessMySpecificExtensions(trans).clear_extension(&tag);
  }

  void free(transaction_type* txn){
    BTag* btag;
    accessMySpecificExtensions(*txn).get_extension(btag);
    sc_assert(btag);
    txn->reset(); //clean off all extension that were added down stream
    btag->event.notify();
  }

  //do a fw transmission
  void initiatorNBTransport_core(transaction_type& trans,
                                 phase_type& phase,
                                 sc_core::sc_time& t,
                                 unsigned int tgtSocketNumber){
    switch (initiator_socket[tgtSocketNumber]->nb_transport_fw(trans, phase, t)) {
      case tlm::TLM_ACCEPTED:
      case tlm::TLM_UPDATED:
        // Transaction not yet finished
        if (phase != tlm::BEGIN_REQ)
        {
          sc_assert(phase!=tlm::END_RESP);
          m_bwPEQ.notify(trans,phase,t);
        }
        break;
      case tlm::TLM_COMPLETED:
        // Transaction finished
        ConnectionInfo* connInfo;
        accessMySpecificExtensions(trans).get_extension(connInfo);
        sc_assert(connInfo);
        connInfo->alreadyComplete=true;
        phase=tlm::BEGIN_RESP;
        m_bwPEQ.notify(trans, phase, t);
        break;
      default:
        sc_assert(0); exit(1);
    };
  }

  //nb_transport_fw
  sync_enum_type initiatorNBTransport(int initiator_id,
                                      transaction_type& trans,
                                      phase_type& phase,
                                      sc_core::sc_time& t)
  {
    ConnectionInfo* connInfo;
    accessMySpecificExtensions(trans).get_extension(connInfo);
    m_fwPEQ.notify(trans,phase,t);
    if (phase==tlm::BEGIN_REQ){
      //add our private information to the txn
      sc_assert(!connInfo);
      connInfo=m_connInfoPool.construct();
      connInfo->fwID=decode(trans.get_address());
      connInfo->bwID=initiator_id;
      connInfo->clearReq=true;
      connInfo->alreadyComplete=false;
      accessMySpecificExtensions(trans).set_extension(connInfo);
    }
    else
    if (phase==tlm::END_RESP){
      return tlm::TLM_COMPLETED;
    }
    else
      {sc_assert(0); exit(1);}
    return tlm::TLM_ACCEPTED;
  }

  sync_enum_type targetNBTransport(int portId,
                                   transaction_type& trans,
                                   phase_type& phase,
                                   sc_core::sc_time& t)
  {
    if (phase != tlm::END_REQ && phase != tlm::BEGIN_RESP) {
      std::cout << "ERROR: '" << name()
                << "': Illegal phase received from target." << std::endl;
      sc_assert(false); exit(1);
    }
    //simply stuff it into the bw PEQ
    m_bwPEQ.notify(trans,phase,t);
    return tlm::TLM_ACCEPTED;
  }

  void bwPEQcb(transaction_type& trans, const phase_type& phase){
    //first get our private info from the txn
    ConnectionInfo* connInfo;
    accessMySpecificExtensions(trans).get_extension(connInfo);
    sc_assert(connInfo);
    phase_type p=phase;
    sc_core::sc_time t=sc_core::SC_ZERO_TIME;
    BTag* btag;
    accessMySpecificExtensions(trans).get_extension(btag);
    bool doCall=btag==NULL; //we only will do a bw call if we are not in a wrapped b_transport
    if ((phase==tlm::END_REQ) | (connInfo->clearReq)){ //in case the target left out end_req clearReq reminds us to unlock the req port
      sc_assert(m_pendingReqs[connInfo->fwID].size());
      sc_assert(m_pendingReqs[connInfo->fwID].front()==&trans);
      m_pendingReqs[connInfo->fwID].pop_front(); //allow another req to start at this target
      if (m_pendingReqs[connInfo->fwID].size()){ //there was a pending req
        phase_type ph=tlm::BEGIN_REQ;
        initiatorNBTransport_core(*m_pendingReqs[connInfo->fwID].front(), ph, t,connInfo->fwID);
      }
      connInfo->clearReq=false;
    }
    //no else here, since we might clear the req AND begin a resp
    if (phase==tlm::BEGIN_RESP){
      m_pendingResps[connInfo->bwID].push_back(&trans);
      doCall=m_pendingResps[connInfo->bwID].size()==1; //do a call in case the response socket was free
    }

    if (doCall){ //we have to do a call on the bw of fw path
      if (btag){ //only possible if BEGIN_RESP and resp socket was free
          phase_type ph=tlm::END_RESP;
          m_fwPEQ.notify(trans, ph, t);
      }
      else
        switch (target_socket[connInfo->bwID]->nb_transport_bw(trans, p, t)){
          case tlm::TLM_ACCEPTED:
          case tlm::TLM_UPDATED:
            break;
          case tlm::TLM_COMPLETED:{
            //covers a piggy bagged END_RESP to START_RESP
            phase_type ph=tlm::END_RESP;
            m_fwPEQ.notify(trans, ph, t);
            }
            break;
          default:
            sc_assert(0); exit(1);

        };
    }
  }

  //the following two functions (fwPEQcb and clearPEQcb) could be one, if we were allowed
  // to stick END_RESP into a PEQ
  void fwPEQcb(transaction_type& trans, const phase_type& phase){
    ConnectionInfo* connInfo;
    accessMySpecificExtensions(trans).get_extension(connInfo);
    sc_assert(connInfo);
    phase_type ph=phase;
    sc_core::sc_time t=sc_core::SC_ZERO_TIME;
    if (phase==tlm::BEGIN_REQ){
      trans.set_address(trans.get_address()&m_masks[connInfo->fwID]); //mask address
      m_pendingReqs[connInfo->fwID].push_back(&trans);
      if (m_pendingReqs[connInfo->fwID].size()==1){ //the socket is free
        initiatorNBTransport_core(trans, ph, t, connInfo->fwID);
      }
    }
    else
    {
      //phase is always END_RESP
      BTag* btag;
      accessMySpecificExtensions(trans).get_extension(btag);
      accessMySpecificExtensions(trans).clear_extension(connInfo); //remove our specific extension as it is not needed any more
      if (!connInfo->alreadyComplete) {
        sync_enum_type tmp=initiator_socket[connInfo->fwID]->nb_transport_fw(trans, ph, t);
        sc_assert(tmp==tlm::TLM_COMPLETED);
      }
      sc_assert(m_pendingResps[connInfo->bwID].size());
      m_pendingResps[connInfo->bwID].pop_front(); //remove current response
      if (m_pendingResps[connInfo->bwID].size()){ //if there was one pending
        ph=tlm::BEGIN_RESP; //schedule its transmission
        m_bwPEQ.notify(*m_pendingResps[connInfo->bwID].front(),ph,t);
      }
      m_connInfoPool.free(connInfo); //release connInfo
      if (btag) btag->event.notify(t); //release b_transport
    }
  }

  void dump_status(){
    std::cout<<"At "<<sc_core::sc_time_stamp()<<" status of "<<name()<<" is "<<std::endl
             <<"  Number of connected initiators: "<<target_socket.size()<<std::endl
             <<"  Number of connected targets: "<<initiator_socket.size()<<std::endl
             <<"  Pending requests:"<<std::endl;
    for (unsigned int i=0; i<m_pendingReqs.size(); i++)
      std::cout<<"    "<<m_pendingReqs[i].size()<<" pending requests for target number "<<i<<std::endl;
    std::cout<<"  Pending responses:"<<std::endl;
    for (unsigned int i=0; i<m_pendingResps.size(); i++)
      std::cout<<"    "<<m_pendingResps[i].size()<<" pending responses for initiator number "<<i<<std::endl;
    std::cout<<"  The address map is:"<<std::endl;
    m_addrMap.dumpMap();

  }
};

#endif
