51#include "debug/DMA.hh"
52#include "debug/Drain.hh"
60 std::optional<uint32_t> sid, std::optional<uint32_t> ssid)
64 defaultSid(sid), defaultSSid(ssid), cacheLineSize(
s->cacheLineSize())
71 assert(pkt->isResponse());
72 warn_if(pkt->isError(),
"Response pkt error.");
75 auto *state = dynamic_cast<DmaReqState*>(pkt->senderState);
78 handleResp(state, pkt->getAddr(), pkt->req->getSize(), delay);
86 assert(pendingCount != 0);
88 DPRINTF(DMA,
"Received response %s for addr: %#x size: %d nb: %d," \
89 " tot: %d sched %d\n",
90 MemCmd(state->cmd).toString(), addr, size,
91 state->numBytes, state->totBytes,
92 state->completionEvent ?
93 state->completionEvent->scheduled() : 0);
97 state->numBytes += size;
98 assert(state->totBytes >= state->numBytes);
100 bool all_bytes = (state->totBytes == state->numBytes);
101 if (state->aborted) {
106 if (all_bytes || pendingCount == 0) {
108 if (state->abortEvent) {
109 device->schedule(state->abortEvent, curTick());
113 }
else if (all_bytes) {
117 delay += state->
delay;
124 if (pendingCount == 0)
133 if (
sid.has_value()) {
134 req->setStreamId(
sid.value());
136 if (
ssid.has_value()) {
137 req->setSubstreamId(
ssid.value());
154 assert(pkt->
req->isUncacheable() ||
170 "DMA port of %s not connected to anything!",
name());
180 DPRINTF(Drain,
"DmaPort not drained\n");
195 uint8_t *
data, std::optional<uint32_t> sid,
196 std::optional<uint32_t> ssid,
Tick delay,
199 DPRINTF(DMA,
"Starting DMA for addr: %#x size: %d sched: %d\n",
addr, size,
295 DPRINTF(DMA,
"-- Failed, waiting for retry\n");
298 DPRINTF(DMA,
"TransmitList: %d, retryPending: %d\n",
306 DPRINTF(DMA,
"Sending DMA for addr: %#x size: %d\n",
312 bool done = !state->
gen.
next();
328 DPRINTF(DMA,
"Sending DMA for addr: %#x size: %d\n",
337 auto callback = [
this](
const MemBackdoor &backdoor) {
340 if (it->second == &backdoor) {
345 panic(
"Got invalidation for unknown memory backdoor.");
347 bd->addInvalidationCallback(callback);
355 DPRINTF(DMA,
"Handling DMA for addr: %#x size %d through backdoor\n",
358 const auto *
bd = bd_it->second;
367 const Addr handled = std::min(remaining, available);
371 uint8_t *bd_data =
bd->ptr() +
offset;
374 memcpy(state_data, bd_data, handled);
376 memcpy(bd_data, state_data, handled);
397 if (
sys->isTimingMode()) {
401 DPRINTF(DMA,
"Can't send immediately, waiting to send\n");
406 }
else if (
sys->isAtomicMode()) {
407 const bool bypass =
sys->bypassCaches();
419 panic(
"Unknown memory mode.");
426 if (if_name ==
"dma") {
433 unsigned max_req_size,
434 unsigned max_pending,
531 if (
port.sys->bypassCaches())
543 const size_t fifo_space =
buffer.capacity() -
buffer.size();
546 const size_t xfer_size = std::min(fifo_space, block_remaining);
550 DPRINTF(DMA,
"Direct bypass startAddr=%#x xfer_size=%#x " \
551 "fifo_space=%#x block_remaining=%#x\n",
552 nextAddr, xfer_size, fifo_space, block_remaining);
557 buffer.write(tmp_buffer.begin(), xfer_size);
565 size_t size_pending(0);
567 size_pending +=
e->requestSize();
578 event->reset(req_size);
582 size_pending += req_size;
608 if (!
event->canceled())
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
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)
const std::optional< uint32_t > defaultSSid
Default substreamId.
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...
const std::optional< uint32_t > defaultSid
Default streamId.
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, std::optional< uint32_t > sid=0, std::optional< 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...
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.
void handleRespPacket(PacketPtr pkt, Tick delay=0)
Handle a response packet by updating the corresponding DMA request state to reflect the bytes receive...
std::vector< uint8_t > _data
DmaDoneEvent(DmaReadFifo *_parent, size_t max_size)
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
static const FlagsType AutoDelete
void setFlags(Flags _flags)
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
PioDevice(const Params &p)
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.
const std::string name() const
Return port name (for DPRINTF).
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.
RequestPort(const std::string &name, SimObject *_owner, PortID id=InvalidPortID)
Request port.
Tick sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor)
Send an atomic request packet like above, but also request a backdoor to the data being accessed.
gem5::Flags< FlagsType > Flags
ClockedObject declaration and implementation.
bool last() const
Is this the last chunk?
Addr addr() const
Return starting address of current chunk.
Addr complete() const
Number of bytes we have already chunked up.
void setNext(Addr next)
Grow this chunk to cover additional bytes which are already handled.
bool done() const
Are we done?
Addr size() const
Return size in bytes of current chunk.
bool next()
Advance generator to next 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.
#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)
Copyright (c) 2024 Arm Limited 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.
MemBackdoor * MemBackdoorPtr
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 std::optional< uint32_t > ssid
const Addr totBytes
Total number of bytes that this transaction involves.
Event * completionEvent
Event to call on the device when this transaction (all packets) complete.
Addr numBytes
Number of bytes that have been acked for this transaction.
const Tick delay
Amount to delay completion of dma by.
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.
Event * abortEvent
Event to call on the device when this transaction is aborted.
const std::optional< uint32_t > sid
Stream IDs.
const Request::Flags flags
The flags to use for requests.
bool aborted
Whether this request was aborted.