45 #include "debug/Config.hh" 46 #include "debug/Drain.hh" 47 #include "debug/Ruby.hh" 48 #include "mem/ruby/protocol/AccessPermission.hh" 55 :
ClockedObject(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") {
95 }
else if (if_name ==
"pio_master_port") {
97 }
else if (if_name ==
"mem_slave_port") {
99 }
else if (if_name ==
"pio_slave_port") {
101 }
else if (if_name ==
"master") {
105 panic(
"RubyPort::getPort master: unknown index %d\n", idx);
109 }
else if (if_name ==
"slave") {
112 if (idx >= static_cast<PortID>(
slave_ports.size())) {
113 panic(
"RubyPort::getPort slave: unknown index %d\n", idx);
126 reqQueue(*_port, *this), snoopRespQueue(*_port, *this)
141 reqQueue(*_port, *this), snoopRespQueue(*_port, *this)
143 DPRINTF(
RubyPort,
"Created master memport on ruby sequencer %s\n", _name);
147 bool _access_backing_store,
PortID id,
148 bool _no_retry_on_stall)
150 access_backing_store(_access_backing_store),
151 no_retry_on_stall(_no_retry_on_stall)
153 DPRINTF(
RubyPort,
"Created slave memport on ruby sequencer %s\n", _name);
177 assert(port != NULL);
187 port->schedTimingResp(pkt,
curTick() + rp->m_ruby_system->clockPeriod());
199 for (
auto it = l.begin(); it != l.end(); ++it) {
200 if (it->contains(pkt->
getAddr())) {
210 panic(
"Should never reach here!\n");
219 panic(
"Ruby supports atomic accesses only in noncaching mode\n");
224 for (
auto it = l.begin(); it != l.end(); ++it) {
225 if (it->contains(pkt->
getAddr())) {
230 panic(
"Could not find address in Ruby PIO address ranges!\n");
241 panic(
"RubyPort should never see request with the " 242 "cacheResponding flag set\n");
246 if (pkt->
req->isCacheMaintenance()) {
247 warn_once(
"Cache maintenance operations are not supported in Ruby.\n");
256 assert(ruby_port->memMasterPort.isConnected());
258 "pio address\n", pkt->
getAddr());
266 ruby_port->memMasterPort.schedTimingReq(pkt,
276 RequestStatus requestStatus = ruby_port->makeRequest(pkt);
281 if (requestStatus == RequestStatus_Issued) {
293 "Request %s for address %#x did not issue because %s\n",
295 RequestStatus_to_string(requestStatus));
309 panic(
"Ruby supports atomic accesses only in noncaching mode\n");
318 "pio address\n", pkt->
getAddr());
338 pkt->
getAddr(), MachineType_Directory);
372 assert(rp->pioMasterPort.isConnected());
373 rp->pioMasterPort.sendFunctional(pkt);
387 bool accessSucceeded =
false;
402 fatal(
"Ruby functional %s failed for address %#x\n",
412 accessSucceeded ?
"successful":
"failed");
431 assert(port != NULL);
434 port->hitCallback(pkt);
456 for (
auto i = curRetryList.begin();
i != curRetryList.end(); ++
i) {
458 "Sequencer may now be free. SendRetry to port %s\n",
460 (*i)->sendRetryReq();
471 DPRINTF(Drain,
"Drain count: %u\n", drainCount);
472 if (drainCount == 0) {
473 DPRINTF(Drain,
"RubyPort done draining, signaling drain done\n");
492 DPRINTF(Drain,
"RubyPort not drained\n");
510 if (pkt->
req->getExtraData() != 0) {
520 accessPhysMem =
false;
533 accessPhysMem =
false;
536 if (pkt->
req->isKernel()) {
537 accessPhysMem =
false;
538 needsResponse =
true;
547 }
else if (needsResponse) {
573 ranges.splice(ranges.begin(),
595 auto request = std::make_shared<Request>(
604 if ((*p)->isSnooping()) {
606 (*p)->sendTimingSnoopReq(&pkt);
std::vector< MemSlavePort * > slave_ports
#define panic(...)
This implements a cprintf based panic() function.
RubyTester::SenderState SenderState
void functionalAccess(PacketPtr pkt)
Perform an untimed memory read or write without changing anything but the memory itself.
Ports are used to interface objects to each other.
Tick recvAtomic(PacketPtr pkt)
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
bool suppressFuncError() const
bool recvTimingReq(PacketPtr pkt)
Receive a timing request from the peer.
void sendRangeChange() const
Called by the owner to send a range change.
#define fatal(...)
This implements a cprintf based fatal() function.
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.
MachineID mapAddressToMachine(Addr addr, MachineType mtype) const
Map an address to the correct MachineID.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
AbstractController * m_controller
std::vector< MemSlavePort * > retryList
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
The QueuedMasterPort combines two queues, a request queue and a snoop response queue, that both share the same port.
bool cacheResponding() const
DrainState drainState() const
Return the current drain state of an object.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
bool functionalRead(Packet *ptr)
void signalDrainDone() const
Signal that an object is drained.
AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
virtual int outstandingCount() const =0
bool isConnected() const
Is this port currently connected to a peer?
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
bool functionalWrite(Packet *ptr)
bool recvTimingReq(PacketPtr pkt)
Receive a timing request from the peer.
RubySystem * m_ruby_system
SimpleMemory declaration.
RequestPtr req
A pointer to the original request.
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)
bool needsResponse() const
void hitCallback(PacketPtr pkt)
void ruby_eviction_callback(Addr address)
void addToRetryList(MemSlavePort *port)
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
PioSlavePort pioSlavePort
virtual MessageBuffer * getMandatoryQueue() const =0
MemMasterPort(const std::string &_name, RubyPort *_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...
bool access_backing_store
uint64_t Tick
Tick count type.
Tick recvAtomic(PacketPtr pkt)
Receive an atomic request packet from the peer.
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
unsigned int gotAddrRanges
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
std::vector< std::map< uint32_t, AbstractController * > > m_abstract_controls
virtual bool isDeadlockEventScheduled() const =0
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.
Tick recvAtomic(PacketPtr pkt)
Receive an atomic request packet from the peer.
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.
virtual const std::string name() const
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 peer.
This master id is used for functional requests that don't come from a particular device.
PioMasterPort pioMasterPort
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...
Cycles ticksToCycles(Tick t) const
RubyPort(const Params *p)
const PortID id
A numeric identifier to distinguish ports in a vector, and set to InvalidPortID in case this port is ...
MemCmd cmd
The command field of the packet.
bool bypassCaches() const
Should caches be bypassed?
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.
static const int NumArgumentRegs M5_VAR_USED
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
MemSlavePort memSlavePort
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time...
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
std::vector< MemSlavePort * >::iterator CpuPortIter
Vector of M5 Ports attached to this Ruby port.
static uint32_t getBlockSizeBytes()
DrainState drain() override
Notify an object that it needs to drain its state.
bool isPhysMemAddress(Addr addr) const
MemSlavePort(const std::string &_name, RubyPort *_port, bool _access_backing_store, PortID id, bool _no_retry_on_stall)