Created
October 8, 2023 14:51
-
-
Save guttatus/563dd36d87f5a92354e60451df9b95f8 to your computer and use it in GitHub Desktop.
Creating SimObjects in the memory system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Import('*') | |
SimObject('SimpleMemobj.py', sim_objects=['SimpleMemobj']) | |
Source('simple_memobj.cc') | |
DebugFlag('SimpleMemobj') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "learning_gem5/simple_memobj/simple_memobj.hh" | |
#include "debug/SimpleMemobj.hh" | |
#include "base/trace.hh" | |
namespace gem5 | |
{ | |
SimpleMemobj::SimpleMemobj(const SimpleMemobjParams& params) : | |
SimObject(params), | |
instPort(params.name + "inst_port", this), | |
dataPort(params.name + "data_port", this), | |
memPort(params.name + "mem_port", this), | |
blocked(false) | |
{ } | |
Port& | |
SimpleMemobj::getPort(const std::string& if_name, PortID idx) | |
{ | |
panic_if(idx != InvalidPortID, "This object doesn't support vector ports"); | |
if(if_name == "mem_side") { | |
return memPort; | |
} else if (if_name == "inst_port") { | |
return instPort; | |
} else if (if_name == "data_port") { | |
return dataPort; | |
} else { | |
return SimpleMemobj::getPort(if_name, idx); | |
} | |
} | |
/********** get address range ***********/ | |
AddrRangeList | |
SimpleMemobj::CPUSidePort::getAddrRanges() const | |
{ | |
return owner->getAddrRanges(); | |
} | |
AddrRangeList | |
SimpleMemobj::getAddrRanges() const | |
{ | |
DPRINTF(SimpleMemobj,"Sending new ranges\n"); | |
return memPort.getAddrRanges(); | |
} | |
/*********** Functional handle *****************/ | |
void | |
SimpleMemobj::CPUSidePort::recvFunctional(PacketPtr pkt) | |
{ | |
return owner->handleFunctional(pkt); | |
} | |
void | |
SimpleMemobj::handleFunctional(PacketPtr pkt) | |
{ | |
memPort.sendFunctional(pkt); | |
} | |
/************ address range change *********/ | |
void | |
SimpleMemobj::MemSideport::recvRangeChange() | |
{ | |
owner->sendRangeChange(); | |
} | |
void | |
SimpleMemobj::sendRangeChange() | |
{ | |
instPort.sendRangeChange(); | |
dataPort.sendRangeChange(); | |
} | |
/********** request **********/ | |
bool | |
SimpleMemobj::CPUSidePort::recvTimingReq(PacketPtr pkt) | |
{ | |
if (!owner->handleRequest(pkt)) { | |
needRetry = true; | |
return false; | |
} else { | |
return true; | |
} | |
} | |
bool | |
SimpleMemobj::handleRequest(PacketPtr pkt) | |
{ | |
if(blocked) { | |
return false; | |
} | |
DPRINTF(SimpleMemobj,"Got requestr for addr %#x\n", pkt->getAddr()); | |
blocked = true; | |
memPort.sendPacket(pkt); | |
return true; | |
} | |
void | |
SimpleMemobj::MemSideport::sendPacket(PacketPtr pkt) | |
{ | |
panic_if(blockedPacket != nullptr, "should never try to send if blocked!"); | |
if(!sendTimingReq(pkt)) { | |
blockedPacket = pkt; | |
} | |
} | |
void | |
SimpleMemobj::MemSideport::recvReqRetry() | |
{ | |
assert(blockedPacket != nullptr); | |
PacketPtr pkt = blockedPacket; | |
blockedPacket = nullptr; | |
sendPacket(pkt); | |
} | |
/*************** response ******************/ | |
bool | |
SimpleMemobj::MemSideport::recvTimingResp(PacketPtr pkt) | |
{ | |
return owner->handleResponse(pkt); | |
} | |
bool | |
SimpleMemobj::handleResponse(PacketPtr pkt) | |
{ | |
assert(blocked); | |
DPRINTF(SimpleMemobj,"Got response for addr %#x\n", pkt->getAddr()); | |
blocked = false; | |
if (pkt->req->isInstFetch()) { | |
instPort.sendPacket(pkt); | |
} else { | |
dataPort.sendPacket(pkt); | |
} | |
instPort.trySendRetry(); | |
dataPort.trySendRetry(); | |
return true; | |
} | |
void | |
SimpleMemobj::CPUSidePort::sendPacket(PacketPtr pkt) | |
{ | |
panic_if(blockedPacket != nullptr, "Should never try to send if block!"); | |
if (!sendTimingResp(pkt)) { | |
blockedPacket = pkt; | |
} | |
} | |
void | |
SimpleMemobj::CPUSidePort::recvRespRetry() | |
{ | |
assert(blockedPacket != nullptr); | |
PacketPtr pkt = blockedPacket; | |
blockedPacket = nullptr; | |
sendPacket(pkt); | |
} | |
void | |
SimpleMemobj::CPUSidePort::trySendRetry() | |
{ | |
if(needRetry && blockedPacket == nullptr) { | |
needRetry = false; | |
DPRINTF(SimpleMemobj, "Sending retry req for %d\n", id); | |
sendRetryReq(); | |
} | |
} | |
SimpleMemobj* | |
SimpleMemobjParams::create() const | |
{ | |
return new SimpleMemobj(this); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __LEARNING_GEM5_SIMPLE_MEMOBJ_HH__ | |
#define __LEARNING_GEM5_SIMPLE_MEMOBJ_HH__ | |
#include "mem/port.hh" | |
#include "params/SimpleMemobj.hh" | |
#include "sim/sim_object.hh" | |
#include <string> | |
namespace gem5 | |
{ | |
class SimpleMemobj : public SimObject | |
{ | |
public: | |
class CPUSidePort : public ResponsePort | |
{ | |
private: | |
SimpleMemobj* owner; | |
bool needRetry; | |
PacketPtr blockedPacket; | |
public: | |
CPUSidePort(const std::string& name, SimpleMemobj* owner) : | |
ResponsePort(name,owner), | |
owner(owner), | |
needRetry(false), | |
blockedPacket(nullptr) | |
{ } | |
AddrRangeList getAddrRanges() const override; | |
void sendPacket(PacketPtr pkt); | |
void trySendRetry(); | |
protected: | |
Tick recvAtomic(PacketPtr pkt) override { panic("recvAtomic unimpl."); } | |
void recvFunctional(PacketPtr pkt) override; | |
bool recvTimingReq(PacketPtr pkt) override; | |
void recvRespRetry() override; | |
}; | |
class MemSideport : public RequestPort | |
{ | |
private: | |
SimpleMemobj* owner; | |
PacketPtr blockedPacket; | |
public: | |
MemSideport(const std::string& name, SimpleMemobj* owner) : | |
RequestPort(name, owner), | |
owner(owner), | |
blockedPacket(nullptr) | |
{ } | |
void sendPacket(PacketPtr pkt); | |
protected: | |
bool recvTimingResp(PacketPtr pkt) override; | |
void recvReqRetry() override; | |
void recvRangeChange() override; | |
}; | |
private: | |
bool handleRequest(PacketPtr pkt); | |
bool handleResponse(PacketPtr pkt); | |
void handleFunctional(PacketPtr pkt); | |
AddrRangeList getAddrRanges() const; | |
void sendRangeChange(); | |
CPUSidePort instPort; | |
CPUSidePort dataPort; | |
MemSideport memPort; | |
bool blocked; | |
public: | |
SimpleMemobj(const SimpleMemobjParams& params); | |
Port& getPort(const std::string& if_name, PortID idx=InvalidPortID) override; | |
}; | |
} | |
#endif // ! __LEARNING_GEM5_SIMPLE_MEMOBJ_HH__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from m5.params import * | |
from m5.proxy import * | |
from m5.SimObject import * | |
class SimpleMemobj(SimObject): | |
type = 'SimpleMemobj' | |
cxx_header = "learning_gem5/simple_memobj/simple_memobj.hh" | |
inst_port = SlavePort("CPU side port, receives requests") | |
data_port = SlavePort("CPU side port, receives requests") | |
mem_side = MasterPort("Memory side port, sends requests") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment