50#include "debug/DMA.hh"
51#include "debug/Drain.hh"
59 uint32_t sid, uint32_t ssid)
61 device(dev), sys(
s), requestorId(
s->getRequestorId(dev)),
63 defaultSid(sid), defaultSSid(ssid), cacheLineSize(
s->cacheLineSize())
87 DPRINTF(DMA,
"Received response %s for addr: %#x size: %d nb: %d," \
88 " tot: %d sched %d\n",
91 state->completionEvent ?
92 state->completionEvent->scheduled() : 0);
96 state->numBytes += size;
99 bool all_bytes = (
state->totBytes ==
state->numBytes);
100 if (
state->aborted) {
107 if (
state->abortEvent) {
112 }
else if (all_bytes) {
115 if (
state->completionEvent) {
116 delay +=
state->delay;
132 req->setStreamId(
sid);
133 req->setSubstreamId(
ssid);
149 assert(pkt->
req->isUncacheable() ||
165 "DMA port of %s not connected to anything!",
name());
175 DPRINTF(Drain,
"DmaPort not drained\n");
190 uint8_t *
data, uint32_t sid, uint32_t ssid,
Tick delay,
193 DPRINTF(DMA,
"Starting DMA for addr: %#x size: %d sched: %d\n",
addr, size,
227 if (
state->numBytes !=
state->gen.complete()) {
233 state->aborted =
true;
240 if (
state->abortEvent)
268 bool last =
state->gen.last();
289 DPRINTF(DMA,
"-- Failed, waiting for retry\n");
292 DPRINTF(DMA,
"TransmitList: %d, retryPending: %d\n",
300 DPRINTF(DMA,
"Sending DMA for addr: %#x size: %d\n",
306 bool done = !
state->gen.next();
322 DPRINTF(DMA,
"Sending DMA for addr: %#x size: %d\n",
331 auto callback = [
this](
const MemBackdoor &backdoor) {
334 if (it->second == &backdoor) {
339 panic(
"Got invalidation for unknown memory backdoor.");
341 bd->addInvalidationCallback(callback);
345 done = !
state->gen.next();
349 DPRINTF(DMA,
"Handling DMA for addr: %#x size %d through backdoor\n",
352 const auto *
bd = bd_it->second;
361 const Addr handled = std::min(remaining, available);
365 uint8_t *bd_data =
bd->ptr() +
offset;
366 uint8_t *state_data =
state->data +
state->gen.complete();
368 memcpy(state_data, bd_data, handled);
370 memcpy(bd_data, state_data, handled);
374 state->gen.setNext(
state->gen.addr() + handled);
377 done = !
state->gen.next();
395 DPRINTF(DMA,
"Can't send immediately, waiting to send\n");
413 panic(
"Unknown memory mode.");
420 if (if_name ==
"dma") {
427 unsigned max_req_size,
428 unsigned max_pending,
430 : maxReqSize(max_req_size), fifoSize(size),
431 reqFlags(
flags), port(_port), cacheLineSize(port.sys->cacheLineSize()),
540 const size_t xfer_size = std::min(fifo_space, block_remaining);
544 DPRINTF(DMA,
"Direct bypass startAddr=%#x xfer_size=%#x " \
545 "fifo_space=%#x block_remaining=%#x\n",
546 nextAddr, xfer_size, fifo_space, block_remaining);
559 size_t size_pending(0);
561 size_pending +=
e->requestSize();
572 event->reset(req_size);
576 size_pending += req_size;
602 if (!
event->canceled())
622 : parent(_parent), _data(max_size, 0)
630 setFlags(AutoDelete);
642 assert(
size <= _data.size());
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Cycles is a wrapper class for representing cycle counts, i.e.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
DmaDevice(const Params &p)
ClockedObject *const device
The device that owns this port.
EventFunctionWrapper sendEvent
Event used to schedule a future sending from the transmit list.
System *const sys
The system that device/port are in.
void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, uint8_t *data, Tick delay, Request::Flags flag=0)
bool sendAtomicBdReq(DmaReqState *state)
Send the next packet from a DMA request in atomic mode, and request and/or use memory backdoors if po...
void recvReqRetry() override
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
DmaPort(ClockedObject *dev, System *s, uint32_t sid=0, uint32_t ssid=0)
void trySendTimingReq()
Take the first request on the transmit list and attempt to send a timing packet from it.
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
PacketPtr inRetry
The packet (if any) waiting for a retry to send.
uint32_t pendingCount
Number of outstanding packets the dma port has.
std::deque< DmaReqState * > transmitList
Use a deque as we never do any insertion or removal in the middle.
AddrRangeMap< MemBackdoorPtr, 1 > memBackdoors
void sendDma()
For timing, attempt to send the first item on the transmit list, and if it is successful and there ar...
const uint32_t defaultSid
Default streamId.
void handleResp(DmaReqState *state, Addr addr, Addr size, Tick delay=0)
bool retryPending
Whether the other side expects us to wait for a retry.
const RequestorID requestorId
Id for all requests.
bool recvTimingResp(PacketPtr pkt) override
Receive a timing response from the peer.
bool sendAtomicReq(DmaReqState *state)
Send the next packet from a DMA request in atomic mode.
const uint32_t defaultSSid
Default substreamId.
void handleRespPacket(PacketPtr pkt, Tick delay=0)
Handle a response packet by updating the corresponding DMA request state to reflect the bytes receive...
DmaDoneEvent(DmaReadFifo *_parent, size_t max_size)
Buffered DMA engine helper class.
void serialize(CheckpointOut &cp) const override
Serialize an object.
size_t size() const
Get the amount of data stored in the FIFO.
virtual void onIdle()
Last response received callback.
bool tryGet(uint8_t *dst, size_t len)
Try to read data from the FIFO.
void startFill(Addr start, size_t size)
Start filling the FIFO.
DmaReadFifo(DmaPort &port, size_t size, unsigned max_req_size, unsigned max_pending, Request::Flags flags=0)
const Request::Flags reqFlags
Request flags.
virtual void onEndOfBlock()
End of block callback.
void resumeFill()
Try to issue new DMA requests or bypass DMA requests.
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
void unserialize(CheckpointIn &cp) override
Unserialize an object.
std::deque< DmaDoneEventUPtr > freeRequests
void dmaDone()
DMA request done, handle incoming data and issue new request.
bool isActive() const
Is the DMA engine active (i.e., are there still in-flight accesses)?
void stopFill()
Stop the DMA engine.
void resumeFillBypass()
Try to bypass DMA requests in non-caching mode.
bool atEndOfBlock() const
Has the DMA engine sent out the last request for the active block?
const Addr maxReqSize
Maximum request size in bytes.
const size_t fifoSize
Maximum FIFO size in bytes.
void handlePending()
Handle pending requests that have been flagged as done.
void resumeFillTiming()
Try to issue new DMA requests during normal execution.
std::unique_ptr< DmaDoneEvent > DmaDoneEventUPtr
std::deque< DmaDoneEventUPtr > pendingRequests
void write(InputIterator in, size_t len)
void read(OutputIterator out, size_t len)
const std::string & toString() const
Return the string to a cmd given by idx.
Command
List of all commands associated with a packet.
virtual std::string name() const
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
SenderState * senderState
This packet's sender state.
RequestPtr req
A pointer to the original request.
bool cacheResponding() const
This device is the base class which all devices senstive to an address range inherit from.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Ports are used to interface objects to each other.
bool isConnected() const
Is this port currently connected to a peer?
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time,...
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Tick sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor)
Send an atomic request packet like above, but also request a backdoor to the data being accessed.
bool isAtomicMode() const
Is the system in atomic mode?
bool isTimingMode() const
Is the system in timing mode?
bool bypassCaches() const
Should caches be bypassed?
ClockedObject declaration and implementation.
Addr addr() const
Return starting address of current chunk.
Addr complete() const
Number of bytes we have already chunked up.
bool done() const
Are we done? That is, did the last call to next() advance past the end of the region?
Addr size() const
Return size in bytes of current chunk.
void signalDrainDone() const
Signal that an object is drained.
DrainState drainState() const
Return the current drain state of an object.
DrainState
Object drain/handover states.
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
void deschedule(Event &event)
bool scheduled() const
Determine if the current event is scheduled.
void schedule(Event &event, Tick when)
#define panic(...)
This implements a cprintf based panic() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
#define UNSERIALIZE_CONTAINER(member)
#define SERIALIZE_CONTAINER(member)
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
void sendEvent(ThreadContext *tc)
Send an event (SEV) to a specific PE if there isn't already a pending event.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
std::shared_ptr< Request > RequestPtr
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
uint64_t Tick
Tick count type.
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
const Packet::Command cmd
Command for the request.
const uint32_t sid
Stream IDs.
ChunkGenerator gen
Object to track what chunks of bytes to send at a time.
uint8_t *const data
Pointer to a buffer for the data.
const Request::Flags flags
The flags to use for requests.
const std::string & name()