Skip to content

Instantly share code, notes, and snippets.

@guttatus
Created October 8, 2023 14:51
Show Gist options
  • Save guttatus/563dd36d87f5a92354e60451df9b95f8 to your computer and use it in GitHub Desktop.
Save guttatus/563dd36d87f5a92354e60451df9b95f8 to your computer and use it in GitHub Desktop.
Creating SimObjects in the memory system
Import('*')
SimObject('SimpleMemobj.py', sim_objects=['SimpleMemobj'])
Source('simple_memobj.cc')
DebugFlag('SimpleMemobj')
#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);
}
}
#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__
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