45 #include "debug/Config.hh"
46 #include "debug/Drain.hh"
47 #include "debug/Ruby.hh"
48 #include "mem/protocol/AccessPermission.hh"
55 :
MemObject(p), m_ruby_system(p->ruby_system), m_version(p->version),
56 m_controller(NULL), m_mandatory_q_ptr(NULL),
57 m_usingRubyTester(p->using_ruby_tester),
system(p->
system),
58 pioMasterPort(
csprintf(
"%s.pio-master-port",
name()), this),
59 pioSlavePort(
csprintf(
"%s.pio-slave-port",
name()), this),
60 memMasterPort(
csprintf(
"%s.mem-master-port",
name()), this),
61 memSlavePort(
csprintf(
"%s-mem-slave-port",
name()), this,
62 p->ruby_system->getAccessBackingStore(), -1,
63 p->no_retry_on_stall),
64 gotAddrRanges(p->port_master_connection_count),
65 m_isCPUSequencer(p->is_cpu_sequencer)
70 for (
size_t i = 0;
i < p->port_slave_connection_count; ++
i) {
72 i),
this, p->ruby_system->getAccessBackingStore(),
73 i, p->no_retry_on_stall));
77 for (
size_t i = 0;
i < p->port_master_connection_count; ++
i) {
93 if (if_name ==
"mem_master_port") {
97 if (if_name ==
"pio_master_port") {
103 if (if_name !=
"master") {
108 panic(
"RubyPort::getMasterPort: unknown index %d\n", idx);
118 if (if_name ==
"mem_slave_port") {
122 if (if_name ==
"pio_slave_port")
127 if (if_name !=
"slave") {
131 if (idx >= static_cast<PortID>(
slave_ports.size())) {
132 panic(
"RubyPort::getSlavePort: unknown index %d\n", idx);
142 reqQueue(*_port, *this), snoopRespQueue(*_port, *this)
157 reqQueue(*_port, *this), snoopRespQueue(*_port, *this)
159 DPRINTF(
RubyPort,
"Created master memport on ruby sequencer %s\n", _name);
163 bool _access_backing_store,
PortID id,
164 bool _no_retry_on_stall)
166 access_backing_store(_access_backing_store),
167 no_retry_on_stall(_no_retry_on_stall)
169 DPRINTF(
RubyPort,
"Created slave memport on ruby sequencer %s\n", _name);
193 assert(port != NULL);
203 port->schedTimingResp(pkt,
curTick() + rp->m_ruby_system->clockPeriod());
215 for (
auto it = l.begin(); it != l.end(); ++it) {
216 if (it->contains(pkt->
getAddr())) {
226 panic(
"Should never reach here!\n");
237 panic(
"RubyPort should never see request with the "
238 "cacheResponding flag set\n");
243 if (!isPhysMemAddress(pkt->
getAddr())) {
244 assert(ruby_port->memMasterPort.isConnected());
246 "pio address\n", pkt->
getAddr());
254 ruby_port->memMasterPort.schedTimingReq(pkt,
264 RequestStatus requestStatus = ruby_port->makeRequest(pkt);
269 if (requestStatus == RequestStatus_Issued) {
281 "Request for address %#x did not issued because %s\n",
282 pkt->
getAddr(), RequestStatus_to_string(requestStatus));
300 if (!no_retry_on_stall && !ruby_port->
onRetryList(
this)) {
315 if (!isPhysMemAddress(pkt->
getAddr())) {
317 assert(rp->pioMasterPort.isConnected());
318 rp->pioMasterPort.sendFunctional(pkt);
325 if (access_backing_store) {
332 bool accessSucceeded =
false;
347 fatal(
"Ruby functional %s failed for address %#x\n",
357 accessSucceeded ?
"successful":
"failed");
376 assert(port != NULL);
379 port->hitCallback(pkt);
401 for (
auto i = curRetryList.begin();
i != curRetryList.end(); ++
i) {
403 "Sequencer may now be free. SendRetry to port %s\n",
405 (*i)->sendRetryReq();
416 DPRINTF(Drain,
"Drain count: %u\n", drainCount);
417 if (drainCount == 0) {
418 DPRINTF(Drain,
"RubyPort done draining, signaling drain done\n");
437 DPRINTF(Drain,
"RubyPort not drained\n");
451 bool accessPhysMem = access_backing_store;
465 accessPhysMem =
false;
478 accessPhysMem =
false;
482 accessPhysMem =
false;
483 needsResponse =
true;
492 }
else if (needsResponse) {
502 schedTimingResp(pkt,
curTick());
518 ranges.splice(ranges.begin(),
547 if ((*p)->isSnooping()) {
549 (*p)->sendTimingSnoopReq(&pkt);
std::vector< MemSlavePort * > slave_ports
RubyTester::SenderState SenderState
This master id is used for functional requests that don't come from a particular device.
void functionalAccess(PacketPtr pkt)
Perform an untimed memory read or write without changing anything but the memory itself.
bool recvTimingReq(PacketPtr pkt)
Receive a timing request from the master port.
bool isMemAddr(Addr addr) const
Check if a physical address is within a range of a memory that is part of the global address map...
const std::string & name()
PioSlavePort(const std::string &_name, RubyPort *_port)
DrainState
Object drain/handover states.
SimpleMemory * getPhysMem()
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
AbstractController * m_controller
std::vector< MemSlavePort * > retryList
bool isPhysMemAddress(Addr addr) const
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the slave port.
uint64_t getExtraData() const
Accessor function for store conditional return value.
The QueuedMasterPort combines two queues, a request queue and a snoop response queue, that both share the same port.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
bool functionalRead(Packet *ptr)
virtual int outstandingCount() const =0
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
bool suppressFuncError() const
virtual BaseSlavePort & getSlavePort(const std::string &if_name, PortID idx=InvalidPortID)
Get a slave port with a given name and index.
bool functionalWrite(Packet *ptr)
bool recvTimingReq(PacketPtr pkt)
Receive a timing request from the master port.
A BaseSlavePort is a protocol-agnostic slave port, responsible only for the structural connection to ...
RubySystem * m_ruby_system
SimpleMemory declaration.
void setFunctionalResponseStatus(bool success)
bool onRetryList(MemSlavePort *port)
Tick curTick()
The current simulated tick.
void convertScToWrite()
It has been determined that the SC packet should successfully update memory.
std::string csprintf(const char *format, const Args &...args)
void hitCallback(PacketPtr pkt)
void ruby_eviction_callback(Addr address)
void addToRetryList(MemSlavePort *port)
PioSlavePort pioSlavePort
virtual MessageBuffer * getMandatoryQueue() const =0
MemMasterPort(const std::string &_name, RubyPort *_port)
unsigned int gotAddrRanges
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
const RequestPtr req
A pointer to the original request.
virtual bool isDeadlockEventScheduled() const =0
bool needsResponse() const
Addr getOffset(Addr addr)
virtual void descheduleDeadlockEvent()=0
void recvRangeChange()
Called to receive an address range change from the peer slave port.
void ruby_hit_callback(PacketPtr pkt)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
bool cacheResponding() const
void convertLlToRead()
When ruby is in use, Ruby will monitor the cache line and the phys memory should treat LL ops as norm...
Draining buffers pending serialization/handover.
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
PioMasterPort(const std::string &_name, RubyPort *_port)
Addr makeLineAddress(Addr addr)
void recvFunctional(PacketPtr pkt)
Receive a functional request packet from the master port.
void sendRangeChange() const
Called by the owner to send a range change.
PioMasterPort pioMasterPort
static const int NumArgumentRegs M5_VAR_USED
MessageBuffer * m_mandatory_q_ptr
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
virtual const std::string name() const
RubyPort(const Params *p)
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
MemCmd cmd
The command field of the packet.
The MemObject class extends the ClockedObject with accessor functions to get its master and slave por...
A BaseMasterPort is a protocol-agnostic master port, responsible only for the structural connection t...
void signalDrainDone() const
Signal that an object is drained.
void schedTimingResp(PacketPtr pkt, Tick when, bool force_order=false)
Schedule the sending of a timing response.
DrainState drainState() const
Return the current drain state of an object.
void pushSenderState(SenderState *sender_state)
Push a new sender state to the packet and make the current sender state the predecessor of the new on...
MemMasterPort memMasterPort
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
std::vector< PioMasterPort * > master_ports
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
BaseSlavePort & getSlavePort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a slave port with a given name and index.
MemSlavePort memSlavePort
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the slave port.
AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
std::vector< MemSlavePort * >::iterator CpuPortIter
Vector of M5 Ports attached to this Ruby port.
static uint32_t getBlockSizeBytes()
virtual BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a master port with a given name and index.
BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a master port with a given name and index.
DrainState drain() override
Notify an object that it needs to drain its state.
MemSlavePort(const std::string &_name, RubyPort *_port, bool _access_backing_store, PortID id, bool _no_retry_on_stall)