| /* | 
 |  * Copyright (c) 2016, Dresden University of Technology (TU Dresden) | 
 |  * All rights reserved. | 
 |  * | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions are | 
 |  * met: | 
 |  * | 
 |  * 1. Redistributions of source code must retain the above copyright notice, | 
 |  *    this list of conditions and the following disclaimer. | 
 |  * | 
 |  * 2. Redistributions in binary form must reproduce the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer in the | 
 |  *    documentation and/or other materials provided with the distribution. | 
 |  * | 
 |  * 3. Neither the name of the copyright holder nor the names of its | 
 |  *    contributors may be used to endorse or promote products derived from | 
 |  *    this software without specific prior written permission. | 
 |  * | 
 |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
 |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 
 |  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
 |  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER | 
 |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 
 |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
 |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 
 |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 
 |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
 |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
 |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
 |  * | 
 |  * Authors: Christian Menard | 
 |  */ | 
 |  | 
 | #ifndef __SC_MASTER_PORT_HH__ | 
 | #define __SC_MASTER_PORT_HH__ | 
 |  | 
 | #include <tlm_utils/peq_with_cb_and_phase.h> | 
 |  | 
 | #include <systemc> | 
 | #include <tlm> | 
 |  | 
 | #include "mem/external_master.hh" | 
 | #include "sc_peq.hh" | 
 | #include "sim_control.hh" | 
 |  | 
 | namespace Gem5SystemC | 
 | { | 
 |  | 
 | // forward declaration | 
 | class Gem5MasterTransactor; | 
 |  | 
 | /** | 
 |  * This is a gem5 master port that translates TLM transactions to gem5 packets. | 
 |  * | 
 |  * Upon receiving a TLM transaction (b_transport, nb_transport_fw, | 
 |  * dbg_transport) the port generates a gem5 packet and initializes the packet | 
 |  * with information from the transaction payload. The original TLM payload is | 
 |  * added as a sender state to the gem5 packet. This way the payload can be | 
 |  * restored when the response packet arrives at the port. | 
 |  * | 
 |  * Special care is required, when the TLM transaction originates from a | 
 |  * SCSlavePort (i.e. it is a gem5 packet that enters back into the gem5 world). | 
 |  * This is a common scenario, when multiple gem5 CPUs communicate via a SystemC | 
 |  * interconnect. In this case, the master port restores the original packet | 
 |  * from the payload extension (added by the SCSlavePort) and forwards it to the | 
 |  * gem5 world. Throughout the code, this mechanism is called 'pipe through'. | 
 |  * | 
 |  * If gem5 operates in atomic mode, the master port registers the TLM blocking | 
 |  * interface and automatically translates non-blocking requests to blocking. | 
 |  * If gem5 operates in timing mode, the transactor registers the non-blocking | 
 |  * interface. Then, the transactor automatically translated blocking requests. | 
 |  * It is assumed that the mode (atomic/timing) does not change during | 
 |  * execution. | 
 |  */ | 
 | class SCMasterPort : public ExternalMaster::Port | 
 | { | 
 |   private: | 
 |     struct TlmSenderState : public Packet::SenderState | 
 |     { | 
 |         tlm::tlm_generic_payload& trans; | 
 |         TlmSenderState(tlm::tlm_generic_payload& trans) | 
 |           : trans(trans) | 
 |         { | 
 |         } | 
 |     }; | 
 |  | 
 |     tlm_utils::peq_with_cb_and_phase<SCMasterPort> peq; | 
 |  | 
 |     bool waitForRetry; | 
 |     tlm::tlm_generic_payload* pendingRequest; | 
 |     PacketPtr pendingPacket; | 
 |  | 
 |     bool needToSendRetry; | 
 |  | 
 |     bool responseInProgress; | 
 |  | 
 |     Gem5MasterTransactor* transactor; | 
 |  | 
 |     System* system; | 
 |  | 
 |     Gem5SimControl& simControl; | 
 |  | 
 |   protected: | 
 |     // payload event call back | 
 |     void peq_cb(tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase); | 
 |  | 
 |     // The TLM target interface | 
 |     tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& trans, | 
 |                                        tlm::tlm_phase& phase, | 
 |                                        sc_core::sc_time& t); | 
 |     void b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& t); | 
 |     unsigned int transport_dbg(tlm::tlm_generic_payload& trans); | 
 |     bool get_direct_mem_ptr(tlm::tlm_generic_payload& trans, | 
 |                             tlm::tlm_dmi& dmi_data); | 
 |  | 
 |     // Gem5 SCMasterPort interface | 
 |     bool recvTimingResp(PacketPtr pkt); | 
 |     void recvReqRetry(); | 
 |     void recvRangeChange(); | 
 |  | 
 |   public: | 
 |     SCMasterPort(const std::string& name_, | 
 |                  const std::string& systemc_name, | 
 |                  ExternalMaster& owner_, | 
 |                  Gem5SimControl& simControl); | 
 |  | 
 |     void bindToTransactor(Gem5MasterTransactor* transactor); | 
 |  | 
 |     friend PayloadEvent<SCMasterPort>; | 
 |  | 
 |   private: | 
 |     void sendEndReq(tlm::tlm_generic_payload& trans); | 
 |     void sendBeginResp(tlm::tlm_generic_payload& trans, | 
 |                        sc_core::sc_time& delay); | 
 |  | 
 |     void handleBeginReq(tlm::tlm_generic_payload& trans); | 
 |     void handleEndResp(tlm::tlm_generic_payload& trans); | 
 |  | 
 |     PacketPtr generatePacket(tlm::tlm_generic_payload& trans); | 
 |     void destroyPacket(PacketPtr pkt); | 
 |  | 
 |     void checkTransaction(tlm::tlm_generic_payload& trans); | 
 | }; | 
 |  | 
 | class SCMasterPortHandler : public ExternalMaster::Handler | 
 | { | 
 |   private: | 
 |     Gem5SimControl& control; | 
 |  | 
 |   public: | 
 |     SCMasterPortHandler(Gem5SimControl& control) : control(control) {} | 
 |  | 
 |     ExternalMaster::Port *getExternalPort(const std::string &name, | 
 |                                           ExternalMaster &owner, | 
 |                                           const std::string &port_data); | 
 | }; | 
 |  | 
 | } | 
 |  | 
 | #endif |