1/* 2 * Copyright (c) 2017 Jason Lowe-Power 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Jason Lowe-Power 29 */ 30 31#ifndef __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__ 32#define __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__ 33 34#include "mem/port.hh" 35#include "params/SimpleMemobj.hh" 36#include "sim/sim_object.hh" 37 38/** 39 * A very simple memory object. Current implementation doesn't even cache 40 * anything it just forwards requests and responses. 41 * This memobj is fully blocking (not non-blocking). Only a single request can 42 * be outstanding at a time. 43 */ 44class SimpleMemobj : public SimObject 45{ 46 private: 47 48 /** 49 * Port on the CPU-side that receives requests. 50 * Mostly just forwards requests to the owner. 51 * Part of a vector of ports. One for each CPU port (e.g., data, inst) 52 */ 53 class CPUSidePort : public SlavePort 54 { 55 private: 56 /// The object that owns this object (SimpleMemobj) 57 SimpleMemobj *owner; 58 59 /// True if the port needs to send a retry req. 60 bool needRetry; 61 62 /// If we tried to send a packet and it was blocked, store it here 63 PacketPtr blockedPacket; 64 65 public: 66 /** 67 * Constructor. Just calls the superclass constructor. 68 */ 69 CPUSidePort(const std::string& name, SimpleMemobj *owner) : 70 SlavePort(name, owner), owner(owner), needRetry(false), 71 blockedPacket(nullptr) 72 { } 73 74 /** 75 * Send a packet across this port. This is called by the owner and 76 * all of the flow control is hanled in this function. 77 * 78 * @param packet to send. 79 */ 80 void sendPacket(PacketPtr pkt); 81 82 /** 83 * Get a list of the non-overlapping address ranges the owner is 84 * responsible for. All slave ports must override this function 85 * and return a populated list with at least one item. 86 * 87 * @return a list of ranges responded to 88 */ 89 AddrRangeList getAddrRanges() const override; 90 91 /** 92 * Send a retry to the peer port only if it is needed. This is called 93 * from the SimpleMemobj whenever it is unblocked. 94 */ 95 void trySendRetry(); 96 97 protected: 98 /** 99 * Receive an atomic request packet from the master port. 100 * No need to implement in this simple memobj. 101 */ 102 Tick recvAtomic(PacketPtr pkt) override 103 { panic("recvAtomic unimpl."); } 104 105 /** 106 * Receive a functional request packet from the master port. 107 * Performs a "debug" access updating/reading the data in place. 108 * 109 * @param packet the requestor sent. 110 */ 111 void recvFunctional(PacketPtr pkt) override; 112 113 /** 114 * Receive a timing request from the master port. 115 * 116 * @param the packet that the requestor sent 117 * @return whether this object can consume the packet. If false, we 118 * will call sendRetry() when we can try to receive this 119 * request again. 120 */ 121 bool recvTimingReq(PacketPtr pkt) override; 122 123 /** 124 * Called by the master port if sendTimingResp was called on this 125 * slave port (causing recvTimingResp to be called on the master 126 * port) and was unsuccesful. 127 */ 128 void recvRespRetry() override; 129 }; 130 131 /** 132 * Port on the memory-side that receives responses. 133 * Mostly just forwards requests to the owner 134 */ 135 class MemSidePort : public MasterPort 136 { 137 private: 138 /// The object that owns this object (SimpleMemobj) 139 SimpleMemobj *owner; 140 141 /// If we tried to send a packet and it was blocked, store it here 142 PacketPtr blockedPacket; 143 144 public: 145 /** 146 * Constructor. Just calls the superclass constructor. 147 */ 148 MemSidePort(const std::string& name, SimpleMemobj *owner) : 149 MasterPort(name, owner), owner(owner), blockedPacket(nullptr) 150 { } 151 152 /** 153 * Send a packet across this port. This is called by the owner and 154 * all of the flow control is hanled in this function. 155 * 156 * @param packet to send. 157 */ 158 void sendPacket(PacketPtr pkt); 159 160 protected: 161 /** 162 * Receive a timing response from the slave port. 163 */ 164 bool recvTimingResp(PacketPtr pkt) override; 165 166 /** 167 * Called by the slave port if sendTimingReq was called on this 168 * master port (causing recvTimingReq to be called on the slave 169 * port) and was unsuccesful. 170 */ 171 void recvReqRetry() override; 172 173 /** 174 * Called to receive an address range change from the peer slave 175 * port. The default implementation ignores the change and does 176 * nothing. Override this function in a derived class if the owner 177 * needs to be aware of the address ranges, e.g. in an 178 * interconnect component like a bus. 179 */ 180 void recvRangeChange() override; 181 }; 182 183 /** 184 * Handle the request from the CPU side 185 * 186 * @param requesting packet 187 * @return true if we can handle the request this cycle, false if the 188 * requestor needs to retry later 189 */ 190 bool handleRequest(PacketPtr pkt); 191 192 /** 193 * Handle the respone from the memory side 194 * 195 * @param responding packet 196 * @return true if we can handle the response this cycle, false if the 197 * responder needs to retry later 198 */ 199 bool handleResponse(PacketPtr pkt); 200 201 /** 202 * Handle a packet functionally. Update the data on a write and get the 203 * data on a read. 204 * 205 * @param packet to functionally handle 206 */ 207 void handleFunctional(PacketPtr pkt); 208 209 /** 210 * Return the address ranges this memobj is responsible for. Just use the 211 * same as the next upper level of the hierarchy. 212 * 213 * @return the address ranges this memobj is responsible for 214 */ 215 AddrRangeList getAddrRanges() const; 216 217 /** 218 * Tell the CPU side to ask for our memory ranges. 219 */ 220 void sendRangeChange(); 221 222 /// Instantiation of the CPU-side ports 223 CPUSidePort instPort; 224 CPUSidePort dataPort; 225 226 /// Instantiation of the memory-side port 227 MemSidePort memPort; 228 229 /// True if this is currently blocked waiting for a response. 230 bool blocked; 231 232 public: 233 234 /** constructor 235 */ 236 SimpleMemobj(SimpleMemobjParams *params); 237 238 /** 239 * Get a port with a given name and index. This is used at 240 * binding time and returns a reference to a protocol-agnostic 241 * port. 242 * 243 * @param if_name Port name 244 * @param idx Index in the case of a VectorPort 245 * 246 * @return A reference to the given port 247 */ 248 Port &getPort(const std::string &if_name, 249 PortID idx=InvalidPortID) override; 250}; 251 252 253#endif // __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__ 254