Go to the documentation of this file.
45 #include "debug/Config.hh"
46 #include "debug/Drain.hh"
47 #include "debug/Ruby.hh"
48 #include "mem/ruby/protocol/AccessPermission.hh"
56 m_controller(NULL), m_mandatory_q_ptr(NULL),
58 pioRequestPort(
csprintf(
"%s.pio-request-port",
name()), this),
59 pioResponsePort(
csprintf(
"%s.pio-response-port",
name()), this),
60 memRequestPort(
csprintf(
"%s.mem-request-port",
name()), this),
61 memResponsePort(
csprintf(
"%s-mem-response-port",
name()), this,
62 p->ruby_system->getAccessBackingStore(), -1,
63 p->no_retry_on_stall),
64 gotAddrRanges(
p->port_interrupt_out_port_connection_count),
65 m_isCPUSequencer(
p->is_cpu_sequencer)
70 for (
size_t i = 0;
i <
p->port_in_ports_connection_count; ++
i) {
72 (
"%s.response_ports%d",
name(),
i),
this,
73 p->ruby_system->getAccessBackingStore(),
74 i,
p->no_retry_on_stall));
78 for (
size_t i = 0;
i <
p->port_interrupt_out_port_connection_count; ++
i) {
80 "%s.request_ports%d",
name(),
i),
this));
94 if (if_name ==
"mem_request_port") {
96 }
else if (if_name ==
"pio_request_port") {
98 }
else if (if_name ==
"mem_response_port") {
100 }
else if (if_name ==
"pio_response_port") {
102 }
else if (if_name ==
"interrupt_out_port") {
106 panic(
"%s: unknown %s index (%d)\n", __func__, if_name, idx);
110 }
else if (if_name ==
"in_ports") {
114 panic(
"%s: unknown %s index (%d)\n", __func__, if_name, idx);
127 reqQueue(*_port, *this), snoopRespQueue(*_port, *this)
136 DPRINTF(
RubyPort,
"Created response pioport on sequencer %s\n", _name);
142 reqQueue(*_port, *this), snoopRespQueue(*_port, *this)
144 DPRINTF(
RubyPort,
"Created request memport on ruby sequencer %s\n", _name);
149 bool _access_backing_store,
PortID id,
150 bool _no_retry_on_stall)
152 access_backing_store(_access_backing_store),
153 no_retry_on_stall(_no_retry_on_stall)
181 assert(port != NULL);
203 for (
auto it =
l.begin(); it !=
l.end(); ++it) {
204 if (it->contains(pkt->
getAddr())) {
207 bool M5_VAR_USED success =
214 panic(
"Should never reach here!\n");
223 panic(
"Ruby supports atomic accesses only in noncaching mode\n");
228 for (
auto it =
l.begin(); it !=
l.end(); ++it) {
229 if (it->contains(pkt->
getAddr())) {
234 panic(
"Could not find address in Ruby PIO address ranges!\n");
245 panic(
"RubyPort should never see request with the "
246 "cacheResponding flag set\n");
250 if (pkt->
req->isCacheMaintenance()) {
251 warn_once(
"Cache maintenance operations are not supported in Ruby.\n");
253 schedTimingResp(pkt,
curTick());
259 if (!isPhysMemAddress(pkt)) {
260 assert(!pkt->
req->isHTMCmd());
263 "pio address\n", pkt->
getAddr());
282 RequestStatus requestStatus = ruby_port->
makeRequest(pkt);
287 if (requestStatus == RequestStatus_Issued) {
299 "Request %s for address %#x did not issue because %s\n",
301 RequestStatus_to_string(requestStatus));
315 panic(
"Ruby supports atomic accesses only in noncaching mode\n");
321 if (!isPhysMemAddress(pkt)) {
324 "pio address\n", pkt->
getAddr());
344 pkt->
getAddr(), MachineType_Directory);
347 rs->m_abstract_controls[
id.getType()][
id.getNum()];
349 if (access_backing_store)
350 rs->getPhysMem()->access(pkt);
364 if (!no_retry_on_stall && !ruby_port->
onRetryList(
this)) {
379 if (!isPhysMemAddress(pkt)) {
381 assert(rp->pioRequestPort.isConnected());
382 rp->pioRequestPort.sendFunctional(pkt);
389 if (access_backing_store) {
394 rs->getPhysMem()->functionalAccess(pkt);
396 bool accessSucceeded =
false;
401 accessSucceeded =
rs->functionalRead(pkt);
403 accessSucceeded =
rs->functionalWrite(pkt);
411 fatal(
"Ruby functional %s failed for address %#x\n",
427 accessSucceeded ?
"successful":
"failed");
446 assert(port != NULL);
471 for (
auto i = curRetryList.begin();
i != curRetryList.end(); ++
i) {
473 "Sequencer may now be free. SendRetry to port %s\n",
475 (*i)->sendRetryReq();
486 DPRINTF(Drain,
"Drain count: %u\n", drainCount);
487 if (drainCount == 0) {
488 DPRINTF(Drain,
"RubyPort done draining, signaling drain done\n");
507 DPRINTF(Drain,
"RubyPort not drained\n");
521 bool accessPhysMem = access_backing_store;
525 if (pkt->
req->getExtraData() != 0) {
535 accessPhysMem =
false;
548 accessPhysMem =
false;
551 if (pkt->
req->isKernel()) {
552 accessPhysMem =
false;
553 needsResponse =
true;
567 rs->getPhysMem()->access(pkt);
569 panic(
"Packet is in neither device nor system memory!");
571 }
else if (needsResponse) {
581 schedTimingResp(pkt,
curTick());
597 ranges.splice(ranges.begin(),
600 for (
const auto M5_VAR_USED &
r : ranges)
620 auto request = std::make_shared<Request>(
630 if ((*p)->isSnooping()) {
632 (*p)->sendTimingSnoopReq(&pkt);
643 r.pioResponsePort.sendRangeChange();
652 if (port->trySatisfyFunctional(func_pkt)) {
#define fatal(...)
This implements a cprintf based fatal() function.
Tick recvAtomic(PacketPtr pkt)
Receive an atomic request packet from the peer.
virtual bool isDeadlockEventScheduled() const =0
void ruby_hit_callback(PacketPtr pkt)
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
bool cacheResponding() const
static uint32_t getBlockSizeBytes()
Tick recvAtomic(PacketPtr pkt)
Addr makeLineAddress(Addr addr)
void convertLlToRead()
When ruby is in use, Ruby will monitor the cache line and the phys memory should treat LL ops as norm...
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
virtual MessageBuffer * getMandatoryQueue() const =0
Tick recvAtomic(PacketPtr pkt)
Receive an atomic request packet from the peer.
bool recvTimingReq(PacketPtr pkt)
Receive a timing request from the peer.
RubyPort(const Params *p)
uint64_t Tick
Tick count type.
MachineID mapAddressToMachine(Addr addr, MachineType mtype) const
Map an address to the correct MachineID.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
RequestPtr req
A pointer to the original request.
RequestorID requestorId() const
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
void recvFunctional(PacketPtr pkt)
Receive a functional request packet from the peer.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
bool onRetryList(MemResponsePort *port)
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
void convertScToWrite()
It has been determined that the SC packet should successfully update memory.
MemRequestPort(const std::string &_name, RubyPort *_port)
virtual RequestStatus makeRequest(PacketPtr pkt)=0
void schedTimingReq(PacketPtr pkt, Tick when)
Schedule the sending of a timing request.
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
MessageBuffer * m_mandatory_q_ptr
@ Drained
Buffers drained, ready for serialization/handover.
AbstractController * m_controller
DrainState
Object drain/handover states.
std::vector< MemResponsePort * > response_ports
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
The QueuedRequestPort combines two queues, a request queue and a snoop response queue,...
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
RubyTester::SenderState SenderState
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Ports are used to interface objects to each other.
bool needsResponse() const
MemResponsePort(const std::string &_name, RubyPort *_port, bool _access_backing_store, PortID id, bool _no_retry_on_stall)
bool suppressFuncError() const
bool bypassCaches() const
Should caches be bypassed?
void signalDrainDone() const
Signal that an object is drained.
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
MemRequestPort memRequestPort
MemResponsePort memResponsePort
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
const std::string name() const
Return port name (for DPRINTF).
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
const std::string & name()
bool htmTransactionFailedInCache() const
Returns whether or not this packet/request has returned from the cache hierarchy in a failed transact...
virtual int functionalWrite(Packet *func_pkt)
PioResponsePort(const std::string &_name, RubyPort *_port)
DrainState drainState() const
Return the current drain state of an object.
@ funcRequestorId
This requestor id is used for functional requests that don't come from a particular device.
PioRequestPort pioRequestPort
virtual const std::string name() const
void addToRetryList(MemResponsePort *port)
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
MemCmd cmd
The command field of the packet.
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...
bool isDeviceMemAddr(PacketPtr pkt) const
Similar to isMemAddr but for devices.
void recvRangeChange()
Called to receive an address range change from the peer response port.
Cycles ticksToCycles(Tick t) const
std::vector< MemResponsePort * > retryList
std::vector< PioRequestPort * > request_ports
virtual void descheduleDeadlockEvent()=0
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Addr getOffset(Addr addr)
void hitCallback(PacketPtr pkt)
bool isConnected() const
Is this port currently connected to a peer?
PioRequestPort(const std::string &_name, RubyPort *_port)
PioResponsePort pioResponsePort
virtual int outstandingCount() const =0
AbstractMemory * getDeviceMemory(RequestorID _id) const
Return a pointer to the device memory.
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time,...
bool isPhysMemAddress(PacketPtr pkt) const
RubySystem * m_ruby_system
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.
void setFunctionalResponseStatus(bool success)
std::string csprintf(const char *format, const Args &...args)
std::vector< MemResponsePort * >::iterator CpuPortIter
Vector of M5 Ports attached to this Ruby port.
void ruby_eviction_callback(Addr address)
@ Draining
Draining buffers pending serialization/handover.
bool recvTimingReq(PacketPtr pkt)
Receive a timing request from the peer.
#define panic(...)
This implements a cprintf based panic() function.
Tick curTick()
The current simulated tick.
Generated on Wed Sep 30 2020 14:02:14 for gem5 by doxygen 1.8.17