37a38,46
> DMARequest::DMARequest(uint64_t start_paddr, int len, bool write,
> int bytes_completed, int bytes_issued, uint8_t *data,
> PacketPtr pkt)
> : start_paddr(start_paddr), len(len), write(write),
> bytes_completed(bytes_completed), bytes_issued(bytes_issued), data(data),
> pkt(pkt)
> {
> }
>
39c48,49
< : RubyPort(p)
---
> : RubyPort(p), m_outstanding_count(0),
> m_max_outstanding_requests(p->max_outstanding_requests)
47d56
< m_is_busy = false;
57c66
< if (m_is_busy) {
---
> if (m_outstanding_count == m_max_outstanding_requests) {
66,67c75,82
< assert(!m_is_busy); // only support one outstanding DMA request
< m_is_busy = true;
---
> assert(m_outstanding_count < m_max_outstanding_requests);
> Addr line_addr = makeLineAddress(paddr);
> auto emplace_pair =
> m_RequestTable.emplace(std::piecewise_construct,
> std::forward_as_tuple(line_addr),
> std::forward_as_tuple(paddr, len, write, 0,
> 0, data, pkt));
> DMARequest& active_request = emplace_pair.first->second;
69,75c84,90
< active_request.start_paddr = paddr;
< active_request.write = write;
< active_request.data = data;
< active_request.len = len;
< active_request.bytes_completed = 0;
< active_request.bytes_issued = 0;
< active_request.pkt = pkt;
---
> // This is pretty conservative. A regular Sequencer with a more beefy
> // request table that can track multiple requests for a cache line should
> // be used if a more aggressive policy is needed.
> if (!emplace_pair.second) {
> DPRINTF(RubyDma, "DMA aliased: addr %p, len %d\n", line_addr, len);
> return RequestStatus_Aliased;
> }
76a92,93
> DPRINTF(RubyDma, "DMA req created: addr %p, len %d\n", line_addr, len);
>
80c97
< msg->getLineAddress() = makeLineAddress(msg->getPhysicalAddress());
---
> msg->getLineAddress() = line_addr;
92a110,111
> m_outstanding_count++;
>
101c120
< DMASequencer::issueNext()
---
> DMASequencer::issueNext(const Addr& address)
103c122,127
< assert(m_is_busy);
---
> RequestTable::iterator i = m_RequestTable.find(address);
> assert(i != m_RequestTable.end());
>
> DMARequest &active_request = i->second;
>
> assert(m_outstanding_count <= m_max_outstanding_requests);
106,112c130,135
< //
< // Must unset the busy flag before calling back the dma port because
< // the callback may cause a previously nacked request to be reissued
< //
< DPRINTF(RubyDma, "DMA request completed\n");
< m_is_busy = false;
< ruby_hit_callback(active_request.pkt);
---
> DPRINTF(RubyDma, "DMA request completed: addr %p, size %d\n",
> address, active_request.len);
> m_outstanding_count--;
> PacketPtr pkt = active_request.pkt;
> m_RequestTable.erase(i);
> ruby_hit_callback(pkt);
149c172
< DMASequencer::dataCallback(const DataBlock & dblk)
---
> DMASequencer::dataCallback(const DataBlock & dblk, const Addr& address)
151c174,178
< assert(m_is_busy);
---
>
> RequestTable::iterator i = m_RequestTable.find(address);
> assert(i != m_RequestTable.end());
>
> DMARequest &active_request = i->second;
161c188
< issueNext();
---
> issueNext(address);
165c192
< DMASequencer::ackCallback()
---
> DMASequencer::ackCallback(const Addr& address)
167c194,197
< issueNext();
---
> RequestTable::iterator i = m_RequestTable.find(address);
> assert(i != m_RequestTable.end());
>
> issueNext(address);