gem5 v24.0.0.0
Loading...
Searching...
No Matches
DMASequencer.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2008 Mark D. Hill and David A. Wood
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
42
43#include <memory>
44
45#include "debug/RubyDma.hh"
46#include "debug/RubyStats.hh"
47#include "mem/ruby/protocol/SequencerMsg.hh"
48#include "mem/ruby/protocol/SequencerRequestType.hh"
50
51namespace gem5
52{
53
54namespace ruby
55{
56
57DMARequest::DMARequest(uint64_t start_paddr, int len, bool write,
58 int bytes_completed, int bytes_issued, uint8_t *data,
59 PacketPtr pkt)
60 : start_paddr(start_paddr), len(len), write(write),
61 bytes_completed(bytes_completed), bytes_issued(bytes_issued), data(data),
62 pkt(pkt)
63{
64}
65
67 : RubyPort(p), m_outstanding_count(0),
68 m_max_outstanding_requests(p.max_outstanding_requests)
69{
70}
71
72void
78
79RequestStatus
81{
83 return RequestStatus_BufferFull;
84 }
85
86 Addr paddr = pkt->getAddr();
87 uint8_t* data = pkt->getPtr<uint8_t>();
88 int len = pkt->getSize();
89 bool write = pkt->isWrite();
90
91 // Should DMA be allowed to generate this ?
92 assert(!pkt->isMaskedWrite());
93
95 Addr line_addr = makeLineAddress(paddr);
96 auto emplace_pair =
97 m_RequestTable.emplace(std::piecewise_construct,
98 std::forward_as_tuple(line_addr),
99 std::forward_as_tuple(paddr, len, write, 0,
100 0, data, pkt));
101 DMARequest& active_request = emplace_pair.first->second;
102
103 // This is pretty conservative. A regular Sequencer with a more beefy
104 // request table that can track multiple requests for a cache line should
105 // be used if a more aggressive policy is needed.
106 if (!emplace_pair.second) {
107 DPRINTF(RubyDma, "DMA aliased: addr %p, len %d\n", line_addr, len);
108 return RequestStatus_Aliased;
109 }
110
111 DPRINTF(RubyDma, "DMA req created: addr %p, len %d\n", line_addr, len);
112
113 std::shared_ptr<SequencerMsg> msg =
114 std::make_shared<SequencerMsg>(clockEdge());
115 msg->getPhysicalAddress() = paddr;
116 msg->getLineAddress() = line_addr;
117
118 if (pkt->req->isAtomic()) {
119 msg->setType(SequencerRequestType_ATOMIC);
120
121 // While regular LD/ST can support DMAs spanning multiple cache lines,
122 // atomic requests are only supported within a single cache line. The
123 // atomic request will end upon atomicCallback and not call issueNext.
124 int block_size = m_ruby_system->getBlockSizeBytes();
125 int atomic_offset = pkt->getAddr() - line_addr;
126 std::vector<bool> access_mask(block_size, false);
127 assert(atomic_offset + pkt->getSize() <= block_size);
128
129 for (int idx = 0; idx < pkt->getSize(); ++idx) {
130 access_mask[atomic_offset + idx] = true;
131 }
132
135 atomic_op(atomic_offset, pkt->getAtomicOp());
136
137 atomic_ops.emplace_back(atomic_op);
138 msg->getwriteMask().setAtomicOps(atomic_ops);
139 } else if (write) {
140 msg->setType(SequencerRequestType_ST);
141 } else {
142 assert(pkt->isRead());
143 msg->setType(SequencerRequestType_LD);
144 }
145
146 int offset = paddr & m_data_block_mask;
147
148 msg->getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ?
150
151 if (write && (data != NULL)) {
152 if (active_request.data != NULL) {
153 msg->getDataBlk().setData(data, offset, msg->getLen());
154 }
155 }
156
158
159 assert(m_mandatory_q_ptr != NULL);
161 active_request.bytes_issued += msg->getLen();
162
163 return RequestStatus_Issued;
164}
165
166void
168{
169 RequestTable::iterator i = m_RequestTable.find(address);
170 assert(i != m_RequestTable.end());
171
172 DMARequest &active_request = i->second;
173
175 active_request.bytes_completed = active_request.bytes_issued;
176 if (active_request.len == active_request.bytes_completed) {
177 DPRINTF(RubyDma, "DMA request completed: addr %p, size %d\n",
178 address, active_request.len);
180 PacketPtr pkt = active_request.pkt;
181 m_RequestTable.erase(i);
183 return;
184 }
185
186 std::shared_ptr<SequencerMsg> msg =
187 std::make_shared<SequencerMsg>(clockEdge());
188 msg->getPhysicalAddress() = active_request.start_paddr +
189 active_request.bytes_completed;
190
191 assert((msg->getPhysicalAddress() & m_data_block_mask) == 0);
192 msg->getLineAddress() = makeLineAddress(msg->getPhysicalAddress());
193
194 msg->getType() = (active_request.write ? SequencerRequestType_ST :
195 SequencerRequestType_LD);
196
197 msg->getLen() =
198 (active_request.len -
200 active_request.len - active_request.bytes_completed :
202
203 if (active_request.write) {
204 msg->getDataBlk().
205 setData(&active_request.data[active_request.bytes_completed],
206 0, msg->getLen());
207 }
208
209 assert(m_mandatory_q_ptr != NULL);
211 active_request.bytes_issued += msg->getLen();
212 DPRINTF(RubyDma,
213 "DMA request bytes issued %d, bytes completed %d, total len %d\n",
214 active_request.bytes_issued, active_request.bytes_completed,
215 active_request.len);
216}
217
218void
219DMASequencer::dataCallback(const DataBlock & dblk, const Addr& address)
220{
221
222 RequestTable::iterator i = m_RequestTable.find(address);
223 assert(i != m_RequestTable.end());
224
225 DMARequest &active_request = i->second;
226 int len = active_request.bytes_issued - active_request.bytes_completed;
227 int offset = 0;
228 if (active_request.bytes_completed == 0)
229 offset = active_request.start_paddr & m_data_block_mask;
230 assert(!active_request.write);
231 if (active_request.data != NULL) {
232 memcpy(&active_request.data[active_request.bytes_completed],
233 dblk.getData(offset, len), len);
234 }
235 issueNext(address);
236}
237
238void
240{
241 assert(m_RequestTable.find(address) != m_RequestTable.end());
242 issueNext(address);
243}
244
245void
246DMASequencer::atomicCallback(const DataBlock& dblk, const Addr& address)
247{
248 RequestTable::iterator i = m_RequestTable.find(address);
249 assert(i != m_RequestTable.end());
250
251 DMARequest &active_request = i->second;
252 PacketPtr pkt = active_request.pkt;
253
254 int offset = active_request.start_paddr & m_data_block_mask;
255 memcpy(pkt->getPtr<uint8_t>(), dblk.getData(offset, pkt->getSize()),
256 pkt->getSize());
257
259
261 m_RequestTable.erase(i);
262}
263
264void
265DMASequencer::recordRequestType(DMASequencerRequestType requestType)
266{
267 DPRINTF(RubyStats, "Recorded statistic: %s\n",
268 DMASequencerRequestType_to_string(requestType));
269}
270
271} // namespace ruby
272} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
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...
Tick cyclesToTicks(Cycles c) const
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
bool isRead() const
Definition packet.hh:593
Addr getAddr() const
Definition packet.hh:807
T * getPtr()
get a pointer to the data ptr.
Definition packet.hh:1225
bool isWrite() const
Definition packet.hh:594
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
unsigned getSize() const
Definition packet.hh:817
AtomicOpFunctor * getAtomicOp() const
Accessor function to atomic op.
Definition packet.hh:845
bool isMaskedWrite() const
Definition packet.hh:1450
void dataCallback(const DataBlock &dblk, const Addr &addr)
DMASequencerParams Params
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
void issueNext(const Addr &addr)
DMASequencer(const Params &)
RequestStatus makeRequest(PacketPtr pkt) override
void ackCallback(const Addr &addr)
void atomicCallback(const DataBlock &dblk, const Addr &addr)
void recordRequestType(DMASequencerRequestType requestType)
const uint8_t * getData(int offset, int len) const
Definition DataBlock.cc:157
void enqueue(MsgPtr message, Tick curTime, Tick delta, bool bypassStrictFIFO=false)
void ruby_hit_callback(PacketPtr pkt)
Definition RubyPort.cc:452
RubySystem * m_ruby_system
Definition RubyPort.hh:202
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition RubyPort.cc:92
MessageBuffer * m_mandatory_q_ptr
Definition RubyPort.hh:205
static uint32_t getBlockSizeBytes()
Definition RubySystem.hh:72
static uint32_t getBlockSizeBits()
Definition RubySystem.hh:73
STL pair class.
Definition stl.hh:58
STL vector class.
Definition stl.hh:37
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
Bitfield< 18, 16 > len
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 0 > p
Addr makeLineAddress(Addr addr)
Definition Address.cc:60
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
DMARequest(uint64_t start_paddr, int len, bool write, int bytes_completed, int bytes_issued, uint8_t *data, PacketPtr pkt)

Generated on Tue Jun 18 2024 16:24:05 for gem5 by doxygen 1.11.0