1/*
2 * Copyright (c) 2015, University of Kaiserslautern
3 * Copyright (c) 2016, Dresden University of Technology (TU Dresden)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 *    this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 *    contributors may be used to endorse or promote products derived from
19 *    this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
25 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Authors: Matthias Jung
34 *          Christian Menard
35 */
36
37#ifndef __SC_SLAVE_PORT_HH__
38#define __SC_SLAVE_PORT_HH__
39
40#include <systemc>
41#include <tlm>
42
43#include "mem/external_slave.hh"
44#include "sc_mm.hh"
45#include "sc_peq.hh"
46#include "sim_control.hh"
47
48namespace Gem5SystemC
49{
50
51// forward declaration
52class Gem5SlaveTransactor;
53
54/**
55 * Test that gem5 is at the same time as SystemC
56 */
57#define CAUGHT_UP do { \
58    assert(curTick() == sc_core::sc_time_stamp().value()); \
59} while (0)
60
61/**
62 * This is a gem5 slave port that translates gem5 packets to TLM transactions.
63 *
64 * Upon receiving a packet (recvAtomic, recvTiningReq, recvFunctional) the port
65 * creates a new TLM payload and initializes it with information from the gem5
66 * packet. The original packet is added as an extension to the TLM payload.
67 * Then the port issues a TLM transaction in the SystemC world. By storing the
68 * original packet as a payload extension, the packet can be restored and send
69 * back to the gem5 world upon receiving a response from the SystemC world.
70 */
71class SCSlavePort : public ExternalSlave::Port
72{
73  public:
74    /** One instance of pe and the related callback needed */
75    //payloadEvent<SCSlavePort> pe;
76    void pec(PayloadEvent<SCSlavePort> * pe,
77        tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase);
78
79    /**
80     * A transaction after BEGIN_REQ has been sent but before END_REQ, which
81     * is blocking the request channel (Exlusion Rule, see IEEE1666)
82     */
83    tlm::tlm_generic_payload *blockingRequest;
84
85    /**
86     * Did another gem5 request arrive while currently blocked?
87     * This variable is needed when a retry should happen
88     */
89    bool needToSendRequestRetry;
90
91    /**
92     * A response which has been asked to retry by gem5 and so is blocking
93     * the response channel
94     */
95    tlm::tlm_generic_payload *blockingResponse;
96
97  protected:
98    /** The gem5 Port slave interface */
99    Tick recvAtomic(PacketPtr packet);
100    void recvFunctional(PacketPtr packet);
101    bool recvTimingReq(PacketPtr packet);
102    bool recvTimingSnoopResp(PacketPtr packet);
103    void recvRespRetry();
104    void recvFunctionalSnoop(PacketPtr packet);
105
106    Gem5SlaveTransactor* transactor;
107
108  public:
109    /** The TLM initiator interface */
110    tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload& trans,
111                                       tlm::tlm_phase& phase,
112                                       sc_core::sc_time& t);
113
114    SCSlavePort(const std::string &name_,
115                const std::string &systemc_name,
116                ExternalSlave &owner_);
117
118    void bindToTransactor(Gem5SlaveTransactor* transactor);
119
120    friend PayloadEvent<SCSlavePort>;
121};
122
123class SCSlavePortHandler : public ExternalSlave::Handler
124{
125  private:
126    Gem5SimControl& control;
127
128  public:
129    SCSlavePortHandler(Gem5SimControl& control) : control(control) {}
130
131    ExternalSlave::Port *getExternalPort(const std::string &name,
132                                         ExternalSlave &owner,
133                                         const std::string &port_data);
134};
135
136}
137
138#endif // __SC_SLAVE_PORT_H__
139