Adding more code from Learning gem5 Part II See http://learning.gem5.org/book/part2/memoryobject.html Change-Id: Iaa9480c5cdbe4090364f02e81dc1d0a0ddac392a Signed-off-by: Jason Lowe-Power <jason@lowepower.com> Reviewed-on: https://gem5-review.googlesource.com/5022 Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
266 lines
8.7 KiB
C++
266 lines
8.7 KiB
C++
/*
|
|
* Copyright (c) 2017 Jason Lowe-Power
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met: redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer;
|
|
* 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;
|
|
* neither the name of the copyright holders 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
|
|
* OWNER 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: Jason Lowe-Power
|
|
*/
|
|
|
|
#ifndef __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
|
|
#define __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
|
|
|
|
#include "mem/mem_object.hh"
|
|
#include "params/SimpleMemobj.hh"
|
|
|
|
/**
|
|
* A very simple memory object. Current implementation doesn't even cache
|
|
* anything it just forwards requests and responses.
|
|
* This memobj is fully blocking (not non-blocking). Only a single request can
|
|
* be outstanding at a time.
|
|
*/
|
|
class SimpleMemobj : public MemObject
|
|
{
|
|
private:
|
|
|
|
/**
|
|
* Port on the CPU-side that receives requests.
|
|
* Mostly just forwards requests to the owner.
|
|
* Part of a vector of ports. One for each CPU port (e.g., data, inst)
|
|
*/
|
|
class CPUSidePort : public SlavePort
|
|
{
|
|
private:
|
|
/// The object that owns this object (SimpleMemobj)
|
|
SimpleMemobj *owner;
|
|
|
|
/// True if the port needs to send a retry req.
|
|
bool needRetry;
|
|
|
|
/// If we tried to send a packet and it was blocked, store it here
|
|
PacketPtr blockedPacket;
|
|
|
|
public:
|
|
/**
|
|
* Constructor. Just calls the superclass constructor.
|
|
*/
|
|
CPUSidePort(const std::string& name, SimpleMemobj *owner) :
|
|
SlavePort(name, owner), owner(owner), needRetry(false),
|
|
blockedPacket(nullptr)
|
|
{ }
|
|
|
|
/**
|
|
* Send a packet across this port. This is called by the owner and
|
|
* all of the flow control is hanled in this function.
|
|
*
|
|
* @param packet to send.
|
|
*/
|
|
void sendPacket(PacketPtr pkt);
|
|
|
|
/**
|
|
* Get a list of the non-overlapping address ranges the owner is
|
|
* responsible for. All slave ports must override this function
|
|
* and return a populated list with at least one item.
|
|
*
|
|
* @return a list of ranges responded to
|
|
*/
|
|
AddrRangeList getAddrRanges() const override;
|
|
|
|
/**
|
|
* Send a retry to the peer port only if it is needed. This is called
|
|
* from the SimpleMemobj whenever it is unblocked.
|
|
*/
|
|
void trySendRetry();
|
|
|
|
protected:
|
|
/**
|
|
* Receive an atomic request packet from the master port.
|
|
* No need to implement in this simple memobj.
|
|
*/
|
|
Tick recvAtomic(PacketPtr pkt) override
|
|
{ panic("recvAtomic unimpl."); }
|
|
|
|
/**
|
|
* Receive a functional request packet from the master port.
|
|
* Performs a "debug" access updating/reading the data in place.
|
|
*
|
|
* @param packet the requestor sent.
|
|
*/
|
|
void recvFunctional(PacketPtr pkt) override;
|
|
|
|
/**
|
|
* Receive a timing request from the master port.
|
|
*
|
|
* @param the packet that the requestor sent
|
|
* @return whether this object can consume the packet. If false, we
|
|
* will call sendRetry() when we can try to receive this
|
|
* request again.
|
|
*/
|
|
bool recvTimingReq(PacketPtr pkt) override;
|
|
|
|
/**
|
|
* Called by the master port if sendTimingResp was called on this
|
|
* slave port (causing recvTimingResp to be called on the master
|
|
* port) and was unsuccesful.
|
|
*/
|
|
void recvRespRetry() override;
|
|
};
|
|
|
|
/**
|
|
* Port on the memory-side that receives responses.
|
|
* Mostly just forwards requests to the owner
|
|
*/
|
|
class MemSidePort : public MasterPort
|
|
{
|
|
private:
|
|
/// The object that owns this object (SimpleMemobj)
|
|
SimpleMemobj *owner;
|
|
|
|
/// If we tried to send a packet and it was blocked, store it here
|
|
PacketPtr blockedPacket;
|
|
|
|
public:
|
|
/**
|
|
* Constructor. Just calls the superclass constructor.
|
|
*/
|
|
MemSidePort(const std::string& name, SimpleMemobj *owner) :
|
|
MasterPort(name, owner), owner(owner), blockedPacket(nullptr)
|
|
{ }
|
|
|
|
/**
|
|
* Send a packet across this port. This is called by the owner and
|
|
* all of the flow control is hanled in this function.
|
|
*
|
|
* @param packet to send.
|
|
*/
|
|
void sendPacket(PacketPtr pkt);
|
|
|
|
protected:
|
|
/**
|
|
* Receive a timing response from the slave port.
|
|
*/
|
|
bool recvTimingResp(PacketPtr pkt) override;
|
|
|
|
/**
|
|
* Called by the slave port if sendTimingReq was called on this
|
|
* master port (causing recvTimingReq to be called on the slave
|
|
* port) and was unsuccesful.
|
|
*/
|
|
void recvReqRetry() override;
|
|
|
|
/**
|
|
* Called to receive an address range change from the peer slave
|
|
* port. The default implementation ignores the change and does
|
|
* nothing. Override this function in a derived class if the owner
|
|
* needs to be aware of the address ranges, e.g. in an
|
|
* interconnect component like a bus.
|
|
*/
|
|
void recvRangeChange() override;
|
|
};
|
|
|
|
/**
|
|
* Handle the request from the CPU side
|
|
*
|
|
* @param requesting packet
|
|
* @return true if we can handle the request this cycle, false if the
|
|
* requestor needs to retry later
|
|
*/
|
|
bool handleRequest(PacketPtr pkt);
|
|
|
|
/**
|
|
* Handle the respone from the memory side
|
|
*
|
|
* @param responding packet
|
|
* @return true if we can handle the response this cycle, false if the
|
|
* responder needs to retry later
|
|
*/
|
|
bool handleResponse(PacketPtr pkt);
|
|
|
|
/**
|
|
* Handle a packet functionally. Update the data on a write and get the
|
|
* data on a read.
|
|
*
|
|
* @param packet to functionally handle
|
|
*/
|
|
void handleFunctional(PacketPtr pkt);
|
|
|
|
/**
|
|
* Return the address ranges this memobj is responsible for. Just use the
|
|
* same as the next upper level of the hierarchy.
|
|
*
|
|
* @return the address ranges this memobj is responsible for
|
|
*/
|
|
AddrRangeList getAddrRanges() const;
|
|
|
|
/**
|
|
* Tell the CPU side to ask for our memory ranges.
|
|
*/
|
|
void sendRangeChange();
|
|
|
|
/// Instantiation of the CPU-side ports
|
|
CPUSidePort instPort;
|
|
CPUSidePort dataPort;
|
|
|
|
/// Instantiation of the memory-side port
|
|
MemSidePort memPort;
|
|
|
|
/// True if this is currently blocked waiting for a response.
|
|
bool blocked;
|
|
|
|
public:
|
|
|
|
/** constructor
|
|
*/
|
|
SimpleMemobj(SimpleMemobjParams *params);
|
|
|
|
/**
|
|
* Get a master port with a given name and index. This is used at
|
|
* binding time and returns a reference to a protocol-agnostic
|
|
* base master port.
|
|
*
|
|
* @param if_name Port name
|
|
* @param idx Index in the case of a VectorPort
|
|
*
|
|
* @return A reference to the given port
|
|
*/
|
|
BaseMasterPort& getMasterPort(const std::string& if_name,
|
|
PortID idx = InvalidPortID) override;
|
|
|
|
/**
|
|
* Get a slave port with a given name and index. This is used at
|
|
* binding time and returns a reference to a protocol-agnostic
|
|
* base master port.
|
|
*
|
|
* @param if_name Port name
|
|
* @param idx Index in the case of a VectorPort
|
|
*
|
|
* @return A reference to the given port
|
|
*/
|
|
BaseSlavePort& getSlavePort(const std::string& if_name,
|
|
PortID idx = InvalidPortID) override;
|
|
};
|
|
|
|
|
|
#endif // __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
|