gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
hbm_ctrl.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 The Regents of the University of California
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "mem/hbm_ctrl.hh"
30
31#include "base/trace.hh"
32#include "debug/DRAM.hh"
33#include "debug/Drain.hh"
34#include "debug/MemCtrl.hh"
35#include "debug/QOS.hh"
36#include "mem/dram_interface.hh"
37#include "mem/mem_interface.hh"
38#include "sim/system.hh"
39
40namespace gem5
41{
42
43namespace memory
44{
45
46HBMCtrl::HBMCtrl(const HBMCtrlParams &p) :
47 MemCtrl(p),
48 retryRdReqPC1(false), retryWrReqPC1(false),
51 name()),
52 respondEventPC1([this] {processRespondEvent(pc1Int, respQueuePC1,
53 respondEventPC1, retryRdReqPC1); }, name()),
54 pc1Int(p.dram_2)
55{
56 DPRINTF(MemCtrl, "Setting up HBM controller\n");
57
58 pc0Int = dynamic_cast<DRAMInterface*>(dram);
59
60 assert(dynamic_cast<DRAMInterface*>(p.dram_2) != nullptr);
61
62 readBufferSize = pc0Int->readBufferSize + pc1Int->readBufferSize;
63 writeBufferSize = pc0Int->writeBufferSize + pc1Int->writeBufferSize;
64
65 fatal_if(!pc0Int, "Memory controller must have pc0 interface");
66 fatal_if(!pc1Int, "Memory controller must have pc1 interface");
67
68 pc0Int->setCtrl(this, commandWindow, 0);
69 pc1Int->setCtrl(this, commandWindow, 1);
70
71 writeHighThreshold = (writeBufferSize/2 * p.write_high_thresh_perc)/100.0;
72 writeLowThreshold = (writeBufferSize/2 * p.write_low_thresh_perc)/100.0;
73}
74
75void
80
81void
83{
85
87 if (isTimingMode) {
88 // shift the bus busy time sufficiently far ahead that we never
89 // have to worry about negative values when computing the time for
90 // the next request, this will add an insignificant bubble at the
91 // start of simulation
92 pc1Int->nextBurstAt = curTick() + pc1Int->commandOffset();
93 }
94}
95
96Tick
98{
99 Tick latency = 0;
100
101 if (pc0Int->getAddrRange().contains(pkt->getAddr())) {
102 latency = recvAtomicLogic(pkt, pc0Int);
103 } else if (pc1Int->getAddrRange().contains(pkt->getAddr())) {
104 latency = recvAtomicLogic(pkt, pc1Int);
105 } else {
106 panic("Can't handle address range for packet %s\n", pkt->print());
107 }
108
109 return latency;
110}
111
112void
114{
115 bool found = recvFunctionalLogic(pkt, pc0Int);
116
117 if (!found) {
118 found = recvFunctionalLogic(pkt, pc1Int);
119 }
120
121 if (!found) {
122 panic("Can't handle address range for packet %s\n", pkt->print());
123 }
124}
125
126Tick
128{
129 Tick latency = recvAtomic(pkt);
130
131 if (pc0Int && pc0Int->getAddrRange().contains(pkt->getAddr())) {
132 pc0Int->getBackdoor(backdoor);
133 } else if (pc1Int && pc1Int->getAddrRange().contains(pkt->getAddr())) {
134 pc1Int->getBackdoor(backdoor);
135 }
136 else {
137 panic("Can't handle address range for packet %s\n",
138 pkt->print());
139 }
140 return latency;
141}
142
143void
145 MemBackdoorPtr &backdoor)
146{
147 auto &range = req.range();
148 if (pc0Int && pc0Int->getAddrRange().isSubset(range)) {
149 pc0Int->getBackdoor(backdoor);
150 } else if (pc1Int && pc1Int->getAddrRange().isSubset(range)) {
151 pc1Int->getBackdoor(backdoor);
152 }
153 else {
154 panic("Can't handle address range for range %s\n", range.to_string());
155 }
156}
157
158bool
159HBMCtrl::writeQueueFullPC0(unsigned int neededEntries) const
160{
162 "Write queue limit %d, PC0 size %d, entries needed %d\n",
163 writeBufferSize/2, pc0Int->writeQueueSize, neededEntries);
164
165 unsigned int wrsize_new = (pc0Int->writeQueueSize + neededEntries);
166 return wrsize_new > (writeBufferSize/2);
167}
168
169bool
170HBMCtrl::writeQueueFullPC1(unsigned int neededEntries) const
171{
173 "Write queue limit %d, PC1 size %d, entries needed %d\n",
174 writeBufferSize/2, pc1Int->writeQueueSize, neededEntries);
175
176 unsigned int wrsize_new = (pc1Int->writeQueueSize + neededEntries);
177 return wrsize_new > (writeBufferSize/2);
178}
179
180bool
181HBMCtrl::readQueueFullPC0(unsigned int neededEntries) const
182{
184 "Read queue limit %d, PC0 size %d, entries needed %d\n",
185 readBufferSize/2, pc0Int->readQueueSize + respQueue.size(),
186 neededEntries);
187
188 unsigned int rdsize_new = pc0Int->readQueueSize + respQueue.size()
189 + neededEntries;
190 return rdsize_new > (readBufferSize/2);
191}
192
193bool
194HBMCtrl::readQueueFullPC1(unsigned int neededEntries) const
195{
197 "Read queue limit %d, PC1 size %d, entries needed %d\n",
198 readBufferSize/2, pc1Int->readQueueSize + respQueuePC1.size(),
199 neededEntries);
200
201 unsigned int rdsize_new = pc1Int->readQueueSize + respQueuePC1.size()
202 + neededEntries;
203 return rdsize_new > (readBufferSize/2);
204}
205
206bool
208{
209 // This is where we enter from the outside world
210 DPRINTF(MemCtrl, "recvTimingReq: request %s addr %#x size %d\n",
211 pkt->cmdString(), pkt->getAddr(), pkt->getSize());
212
213 panic_if(pkt->cacheResponding(), "Should not see packets where cache "
214 "is responding");
215
216 panic_if(!(pkt->isRead() || pkt->isWrite()),
217 "Should only see read and writes at memory controller\n");
218
219 // Calc avg gap between requests
220 if (prevArrival != 0) {
221 stats.totGap += curTick() - prevArrival;
222 }
224
225 // What type of media does this packet access?
226 bool is_pc0;
227
228 // TODO: make the interleaving bit across pseudo channels a parameter
229 if (bits(pkt->getAddr(), 6) == 0) {
230 is_pc0 = true;
231 } else {
232 is_pc0 = false;
233 }
234
235 // Find out how many memory packets a pkt translates to
236 // If the burst size is equal or larger than the pkt size, then a pkt
237 // translates to only one memory packet. Otherwise, a pkt translates to
238 // multiple memory packets
239 unsigned size = pkt->getSize();
240 uint32_t burst_size = pc0Int->bytesPerBurst();
241 unsigned offset = pkt->getAddr() & (burst_size - 1);
242 unsigned int pkt_count = divCeil(offset + size, burst_size);
243
244 // run the QoS scheduler and assign a QoS priority value to the packet
245 qosSchedule({&readQueue, &writeQueue}, burst_size, pkt);
246
247 // check local buffers and do not accept if full
248 if (pkt->isWrite()) {
249 if (is_pc0) {
250 if (writeQueueFullPC0(pkt_count)) {
251 DPRINTF(MemCtrl, "Write queue full, not accepting\n");
252 // remember that we have to retry this port
253 retryWrReq = true;
254 stats.numWrRetry++;
255 return false;
256 } else {
257 addToWriteQueue(pkt, pkt_count, pc0Int);
258 if (!nextReqEvent.scheduled()) {
259 DPRINTF(MemCtrl, "Request scheduled immediately\n");
261 }
262 stats.writeReqs++;
263 stats.bytesWrittenSys += size;
264 }
265 } else {
266 if (writeQueueFullPC1(pkt_count)) {
267 DPRINTF(MemCtrl, "Write queue full, not accepting\n");
268 // remember that we have to retry this port
269 retryWrReqPC1 = true;
270 stats.numWrRetry++;
271 return false;
272 } else {
273 addToWriteQueue(pkt, pkt_count, pc1Int);
274 if (!nextReqEventPC1.scheduled()) {
275 DPRINTF(MemCtrl, "Request scheduled immediately\n");
277 }
278 stats.writeReqs++;
279 stats.bytesWrittenSys += size;
280 }
281 }
282 } else {
283
284 assert(pkt->isRead());
285 assert(size != 0);
286
287 if (is_pc0) {
288 if (readQueueFullPC0(pkt_count)) {
289 DPRINTF(MemCtrl, "Read queue full, not accepting\n");
290 // remember that we have to retry this port
291 retryRdReq = true;
292 stats.numRdRetry++;
293 return false;
294 } else {
295 if (!addToReadQueue(pkt, pkt_count, pc0Int)) {
296 if (!nextReqEvent.scheduled()) {
297 DPRINTF(MemCtrl, "Request scheduled immediately\n");
299 }
300 }
301
302 stats.readReqs++;
303 stats.bytesReadSys += size;
304 }
305 } else {
306 if (readQueueFullPC1(pkt_count)) {
307 DPRINTF(MemCtrl, "Read queue full, not accepting\n");
308 // remember that we have to retry this port
309 retryRdReqPC1 = true;
310 stats.numRdRetry++;
311 return false;
312 } else {
313 if (!addToReadQueue(pkt, pkt_count, pc1Int)) {
314 if (!nextReqEventPC1.scheduled()) {
315 DPRINTF(MemCtrl, "Request scheduled immediately\n");
317 }
318 }
319 stats.readReqs++;
320 stats.bytesReadSys += size;
321 }
322 }
323 }
324
325 return true;
326}
327
328void
330{
331 auto it = rowBurstTicks.begin();
332 while (it != rowBurstTicks.end()) {
333 auto current_it = it++;
334 if (getBurstWindow(curTick()) > *current_it) {
335 DPRINTF(MemCtrl, "Removing burstTick for %d\n", *current_it);
336 rowBurstTicks.erase(current_it);
337 }
338 }
339}
340
341void
343{
344 auto it = colBurstTicks.begin();
345 while (it != colBurstTicks.end()) {
346 auto current_it = it++;
347 if (getBurstWindow(curTick()) > *current_it) {
348 DPRINTF(MemCtrl, "Removing burstTick for %d\n", *current_it);
349 colBurstTicks.erase(current_it);
350 }
351 }
352}
353
354void
360
361Tick
362HBMCtrl::verifySingleCmd(Tick cmd_tick, Tick max_cmds_per_burst, bool row_cmd)
363{
364 // start with assumption that there is no contention on command bus
365 Tick cmd_at = cmd_tick;
366
367 // get tick aligned to burst window
368 Tick burst_tick = getBurstWindow(cmd_tick);
369
370 // verify that we have command bandwidth to issue the command
371 // if not, iterate over next window(s) until slot found
372
373 if (row_cmd) {
374 while (rowBurstTicks.count(burst_tick) >= max_cmds_per_burst) {
375 DPRINTF(MemCtrl, "Contention found on row command bus at %d\n",
376 burst_tick);
377 burst_tick += commandWindow;
378 cmd_at = burst_tick;
379 }
380 DPRINTF(MemCtrl, "Now can send a row cmd_at %d\n",
381 cmd_at);
382 rowBurstTicks.insert(burst_tick);
383
384 } else {
385 while (colBurstTicks.count(burst_tick) >= max_cmds_per_burst) {
386 DPRINTF(MemCtrl, "Contention found on col command bus at %d\n",
387 burst_tick);
388 burst_tick += commandWindow;
389 cmd_at = burst_tick;
390 }
391 DPRINTF(MemCtrl, "Now can send a col cmd_at %d\n",
392 cmd_at);
393 colBurstTicks.insert(burst_tick);
394 }
395 return cmd_at;
396}
397
398Tick
399HBMCtrl::verifyMultiCmd(Tick cmd_tick, Tick max_cmds_per_burst,
400 Tick max_multi_cmd_split)
401{
402
403 // start with assumption that there is no contention on command bus
404 Tick cmd_at = cmd_tick;
405
406 // get tick aligned to burst window
407 Tick burst_tick = getBurstWindow(cmd_tick);
408
409 // Command timing requirements are from 2nd command
410 // Start with assumption that 2nd command will issue at cmd_at and
411 // find prior slot for 1st command to issue
412 // Given a maximum latency of max_multi_cmd_split between the commands,
413 // find the burst at the maximum latency prior to cmd_at
414 Tick burst_offset = 0;
415 Tick first_cmd_offset = cmd_tick % commandWindow;
416 while (max_multi_cmd_split > (first_cmd_offset + burst_offset)) {
417 burst_offset += commandWindow;
418 }
419 // get the earliest burst aligned address for first command
420 // ensure that the time does not go negative
421 Tick first_cmd_tick = burst_tick - std::min(burst_offset, burst_tick);
422
423 // Can required commands issue?
424 bool first_can_issue = false;
425 bool second_can_issue = false;
426 // verify that we have command bandwidth to issue the command(s)
427 while (!first_can_issue || !second_can_issue) {
428 bool same_burst = (burst_tick == first_cmd_tick);
429 auto first_cmd_count = rowBurstTicks.count(first_cmd_tick);
430 auto second_cmd_count = same_burst ?
431 first_cmd_count + 1 : rowBurstTicks.count(burst_tick);
432
433 first_can_issue = first_cmd_count < max_cmds_per_burst;
434 second_can_issue = second_cmd_count < max_cmds_per_burst;
435
436 if (!second_can_issue) {
437 DPRINTF(MemCtrl, "Contention (cmd2) found on command bus at %d\n",
438 burst_tick);
439 burst_tick += commandWindow;
440 cmd_at = burst_tick;
441 }
442
443 // Verify max_multi_cmd_split isn't violated when command 2 is shifted
444 // If commands initially were issued in same burst, they are
445 // now in consecutive bursts and can still issue B2B
446 bool gap_violated = !same_burst &&
447 ((burst_tick - first_cmd_tick) > max_multi_cmd_split);
448
449 if (!first_can_issue || (!second_can_issue && gap_violated)) {
450 DPRINTF(MemCtrl, "Contention (cmd1) found on command bus at %d\n",
451 first_cmd_tick);
452 first_cmd_tick += commandWindow;
453 }
454 }
455
456 // Add command to burstTicks
457 rowBurstTicks.insert(burst_tick);
458 rowBurstTicks.insert(first_cmd_tick);
459
460 return cmd_at;
461}
462
463void
465{
466
468
469 if (!isTimingMode && system()->isTimingMode()) {
470 // if we switched to timing mode, kick things into action,
471 // and behave as if we restored from a checkpoint
472 startup();
473 pc1Int->startup();
474 } else if (isTimingMode && !system()->isTimingMode()) {
475 // if we switch from timing mode, stop the refresh events to
476 // not cause issues with KVM
477 if (pc1Int) {
478 pc1Int->drainRanks();
479 }
480 }
481
482 // update the mode
484}
485
488{
489 AddrRangeList ranges;
490 ranges.push_back(pc0Int->getAddrRange());
491 ranges.push_back(pc1Int->getAddrRange());
492 return ranges;
493}
494
495} // namespace memory
496} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
const AddrRange & range() const
Definition backdoor.hh:140
bool isRead() const
Definition packet.hh:593
Addr getAddr() const
Definition packet.hh:807
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition packet.hh:588
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
Definition packet.cc:368
bool isWrite() const
Definition packet.hh:594
unsigned getSize() const
Definition packet.hh:817
bool cacheResponding() const
Definition packet.hh:659
bool isTimingMode() const
Is the system in timing mode?
Definition system.hh:275
bool readQueueFullPC1(unsigned int pkt_count) const
Definition hbm_ctrl.cc:194
DRAMInterface * pc1Int
Definition hbm_ctrl.hh:195
void recvMemBackdoorReq(const MemBackdoorReq &req, MemBackdoorPtr &_backdoor) override
Definition hbm_ctrl.cc:144
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition hbm_ctrl.cc:76
AddrRangeList getAddrRanges() override
Definition hbm_ctrl.cc:487
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor) override
Definition hbm_ctrl.cc:127
bool retryRdReqPC1
Remember if we have to retry a request for second pseudo channel.
Definition hbm_ctrl.hh:79
void recvFunctional(PacketPtr pkt) override
Definition hbm_ctrl.cc:113
virtual void drainResume() override
Resume execution after a successful drain.
Definition hbm_ctrl.cc:464
EventFunctionWrapper respondEventPC1
Definition hbm_ctrl.hh:135
bool recvTimingReq(PacketPtr pkt) override
Definition hbm_ctrl.cc:207
bool writeQueueFullPC1(unsigned int pkt_count) const
Definition hbm_ctrl.cc:170
void pruneBurstTick() override
Remove commands that have already issued from rowBurstTicks and colBurstTicks.
Definition hbm_ctrl.cc:355
virtual void startup() override
startup() is the final initialization call before simulation.
Definition hbm_ctrl.cc:82
std::unordered_multiset< Tick > colBurstTicks
This is used to ensure that the column command bandwidth does not exceed the allowable media constrai...
Definition hbm_ctrl.hh:187
bool readQueueFullPC0(unsigned int pkt_count) const
Check if the read queue partition of both pseudo channels has room for more entries.
Definition hbm_ctrl.cc:181
std::unordered_multiset< Tick > rowBurstTicks
Holds count of row commands issued in burst window starting at defined Tick.
Definition hbm_ctrl.hh:180
Tick recvAtomic(PacketPtr pkt) override
Definition hbm_ctrl.cc:97
EventFunctionWrapper nextReqEventPC1
NextReq and Respond events for second pseudo channel.
Definition hbm_ctrl.hh:134
HBMCtrl(const HBMCtrlParams &p)
Definition hbm_ctrl.cc:46
Tick verifyMultiCmd(Tick cmd_tick, Tick max_cmds_per_burst, Tick max_multi_cmd_split=0) override
Check for command bus contention for multi-cycle (2 currently) command.
Definition hbm_ctrl.cc:399
std::deque< MemPacket * > respQueuePC1
Response queue for pkts sent to second pseudo channel The first pseudo channel uses MemCtrl::respQueu...
Definition hbm_ctrl.hh:173
DRAMInterface * pc0Int
Pointers to interfaces of the two pseudo channels pc0Int is same as MemCtrl::dram (it will be pointin...
Definition hbm_ctrl.hh:194
Tick verifySingleCmd(Tick cmd_tick, Tick max_cmds_per_burst, bool row_cmd) override
Check for command bus contention for single cycle command.
Definition hbm_ctrl.cc:362
bool writeQueueFullPC0(unsigned int pkt_count) const
Check if the write queue partition of both pseudo channels has room for more entries.
Definition hbm_ctrl.cc:159
bool recvFunctionalLogic(PacketPtr pkt, MemInterface *mem_intr)
Definition mem_ctrl.cc:1395
bool retryRdReq
Remember if we have to retry a request when available.
Definition mem_ctrl.hh:293
virtual void startup() override
startup() is the final initialization call before simulation.
Definition mem_ctrl.cc:110
void addToWriteQueue(PacketPtr pkt, unsigned int pkt_count, MemInterface *mem_intr)
Decode the incoming pkt, create a mem_pkt and push to the back of the write queue.
Definition mem_ctrl.cc:304
Tick recvAtomicLogic(PacketPtr pkt, MemInterface *mem_intr)
Definition mem_ctrl.cc:136
std::deque< MemPacket * > respQueue
Response queue where read packets wait after we're done working with them, but it's not time to send ...
Definition mem_ctrl.hh:492
std::vector< MemPacketQueue > writeQueue
Definition mem_ctrl.hh:473
virtual void processNextReqEvent(MemInterface *mem_intr, MemPacketQueue &resp_queue, EventFunctionWrapper &resp_event, EventFunctionWrapper &next_req_event, bool &retry_wr_req)
Bunch of things requires to setup "events" in gem5 When event "respondEvent" occurs for example,...
Definition mem_ctrl.cc:881
bool addToReadQueue(PacketPtr pkt, unsigned int pkt_count, MemInterface *mem_intr)
When a new read comes in, first check if the write q has a pending request to the same address....
Definition mem_ctrl.cc:189
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition mem_ctrl.cc:100
uint32_t readBufferSize
The following are basic design parameters of the memory controller, and are initialized based on para...
Definition mem_ctrl.hh:514
EventFunctionWrapper nextReqEvent
Definition mem_ctrl.hh:307
std::vector< MemPacketQueue > readQueue
The controller's main read and write queues, with support for QoS reordering.
Definition mem_ctrl.hh:472
bool isTimingMode
Remember if the memory system is in timing mode.
Definition mem_ctrl.hh:288
MemCtrl(const MemCtrlParams &p)
Definition mem_ctrl.cc:60
Tick getBurstWindow(Tick cmd_tick)
Calculate burst window aligned tick.
Definition mem_ctrl.cc:675
virtual void drainResume() override
Resume execution after a successful drain.
Definition mem_ctrl.cc:1452
const Tick commandWindow
Length of a command window, used to check command bandwidth.
Definition mem_ctrl.hh:545
uint8_t qosSchedule(std::initializer_list< Queues * > queues_ptr, uint64_t queue_entry_size, const PacketPtr pkt)
Assign priority to a packet by executing the configured QoS policy.
Definition mem_ctrl.hh:495
System * system() const
read the system pointer
Definition mem_ctrl.hh:370
uint8_t schedule(RequestorID id, uint64_t data)
Definition mem_ctrl.cc:217
DRAMInterface declaration.
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
Definition addr_range.hh:64
static constexpr T divCeil(const T &a, const U &b)
Definition intmath.hh:110
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:268
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:246
HBMCtrl declaration.
MemInterface declaration.
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 0 > p
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
MemBackdoor * MemBackdoorPtr
Definition backdoor.hh:127
uint64_t Tick
Tick count type.
Definition types.hh:58
Packet * PacketPtr
const std::string & name()
Definition trace.cc:48

Generated on Mon May 26 2025 09:19:12 for gem5 by doxygen 1.13.2