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())
84 DPRINTF(
DMA,
"Received response %s for addr: %#x size: %d nb: %d," \
85 " tot: %d sched %d\n",
88 state->completionEvent ?
89 state->completionEvent->scheduled() : 0);
93 state->numBytes += size;
101 if (
state->completionEvent) {
102 delay +=
state->delay;
118 req->setStreamId(
sid);
119 req->setSubstreamId(
ssid);
135 assert(pkt->
req->isUncacheable() ||
151 "DMA port of %s not connected to anything!",
name());
161 DPRINTF(Drain,
"DmaPort not drained\n");
175 uint8_t *
data, uint32_t sid, uint32_t ssid,
Tick delay,
178 DPRINTF(
DMA,
"Starting DMA for addr: %#x size: %d sched: %d\n",
addr, size,
218 bool last =
state->gen.last();
236 DPRINTF(
DMA,
"-- Failed, waiting for retry\n");
239 DPRINTF(
DMA,
"TransmitList: %d, inRetry: %d\n",
247 DPRINTF(
DMA,
"Sending DMA for addr: %#x size: %d\n",
252 bool done = !
state->gen.next();
267 DPRINTF(
DMA,
"Sending DMA for addr: %#x size: %d\n",
276 auto callback = [
this](
const MemBackdoor &backdoor) {
279 if (it->second == &backdoor) {
284 panic(
"Got invalidation for unknown memory backdoor.");
286 bd->addInvalidationCallback(callback);
290 done = !
state->gen.next();
294 DPRINTF(
DMA,
"Handling DMA for addr: %#x size %d through backdoor\n",
297 const auto *
bd = bd_it->second;
306 const Addr handled = std::min(remaining, available);
310 uint8_t *bd_data =
bd->ptr() +
offset;
311 uint8_t *state_data =
state->data +
state->gen.complete();
313 memcpy(state_data, bd_data, handled);
315 memcpy(bd_data, state_data, handled);
319 state->gen.setNext(
state->gen.addr() + handled);
322 done = !
state->gen.next();
340 DPRINTF(
DMA,
"Can't send immediately, waiting to send\n");
353 bool done =
state->gen.done();
358 panic(
"Unknown memory mode.");
365 if (if_name ==
"dma") {
372 unsigned max_req_size,
373 unsigned max_pending,
375 : maxReqSize(max_req_size), fifoSize(size),
376 reqFlags(
flags), port(_port), cacheLineSize(port.sys->cacheLineSize()),
485 const size_t xfer_size = std::min(fifo_space, block_remaining);
489 DPRINTF(
DMA,
"Direct bypass startAddr=%#x xfer_size=%#x " \
490 "fifo_space=%#x block_remaining=%#x\n",
491 nextAddr, xfer_size, fifo_space, block_remaining);
504 size_t size_pending(0);
506 size_pending +=
e->requestSize();
517 event->reset(req_size);
521 size_pending += req_size;
547 if (!
event->canceled())
567 : parent(_parent), _data(max_size, 0)
575 setFlags(AutoDelete);
587 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)
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....
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
SenderState * senderState
This packet's sender state.
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
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.
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.
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)
void sendEvent(ThreadContext *tc)
Send an event (SEV) to a specific PE if there isn't already a pending event.
ProbePointArg< PacketInfo > Packet
Packet probe point.
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
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()