gem5 v24.1.0.1
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
amdgpu_device.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Advanced Micro Devices, Inc.
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 met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
33
34#include <fstream>
35
36#include "debug/AMDGPUDevice.hh"
44#include "gpu-compute/shader.hh"
45#include "mem/abstract_mem.hh"
46#include "mem/packet.hh"
47#include "mem/packet_access.hh"
48#include "params/AMDGPUDevice.hh"
49#include "sim/byteswap.hh"
50#include "sim/sim_exit.hh"
51
52namespace gem5
53{
54
55AMDGPUDevice::AMDGPUDevice(const AMDGPUDeviceParams &p)
56 : PciDevice(p), gpuMemMgr(p.memory_manager), deviceIH(p.device_ih),
57 cp(p.cp), checkpoint_before_mmios(p.checkpoint_before_mmios),
58 init_interrupt_count(0), _lastVMID(0),
59 deviceMem(name() + ".deviceMem", p.memories, false, "", false)
60{
61 // System pointer needs to be explicitly set for device memory since
62 // DRAMCtrl uses it to get (1) cache line size and (2) the mem mode.
63 // Note this means the cache line size is system wide.
64 for (auto& m : p.memories) {
65 m->system(p.system);
66
67 // Add to system's device memory map.
68 p.system->addDeviceMemory(gpuMemMgr->getRequestorID(), m);
69 }
70
71 if (config.expansionROM) {
72 romRange = RangeSize(config.expansionROM, ROM_SIZE);
73 } else {
75 }
76
77 if (p.device_name == "Vega10") {
78 gfx_version = GfxVersion::gfx900;
79 } else if (p.device_name == "MI100") {
80 gfx_version = GfxVersion::gfx908;
81 } else if (p.device_name == "MI200") {
82 gfx_version = GfxVersion::gfx90a;
83 } else if (p.device_name == "MI300X") {
84 gfx_version = GfxVersion::gfx942;
85 } else {
86 panic("Unknown GPU device %s\n", p.device_name);
87 }
88
89 int sdma_id = 0;
90 for (auto& s : p.sdmas) {
91 s->setGPUDevice(this);
92 s->setId(sdma_id);
93 sdmaIds.insert({sdma_id, s});
94 sdmaMmios.insert({sdma_id,
95 RangeSize(s->getMmioBase(), s->getMmioSize())});
96 DPRINTF(AMDGPUDevice, "SDMA%d has MMIO range %s\n", sdma_id,
97 sdmaMmios[sdma_id].to_string().c_str());
98 sdma_id++;
99 }
100
101 // Map SDMA MMIO addresses to functions
102 sdmaFunc.insert({0x81, &SDMAEngine::setGfxBaseLo});
103 sdmaFunc.insert({0x82, &SDMAEngine::setGfxBaseHi});
104 sdmaFunc.insert({0x88, &SDMAEngine::setGfxRptrHi});
105 sdmaFunc.insert({0x89, &SDMAEngine::setGfxRptrLo});
106 sdmaFunc.insert({0x92, &SDMAEngine::setGfxDoorbellLo});
108 sdmaFunc.insert({0x80, &SDMAEngine::setGfxSize});
109 sdmaFunc.insert({0xb2, &SDMAEngine::setGfxWptrLo});
110 sdmaFunc.insert({0xb3, &SDMAEngine::setGfxWptrHi});
111 if (p.device_name == "Vega10") {
112 sdmaFunc.insert({0xe1, &SDMAEngine::setPageBaseLo});
113 sdmaFunc.insert({0xe9, &SDMAEngine::setPageRptrLo});
114 sdmaFunc.insert({0xe8, &SDMAEngine::setPageRptrHi});
117 sdmaFunc.insert({0xe0, &SDMAEngine::setPageSize});
118 sdmaFunc.insert({0x113, &SDMAEngine::setPageWptrLo});
119 } else if (p.device_name == "MI100" || p.device_name == "MI200"
120 || p.device_name == "MI300X") {
121 sdmaFunc.insert({0xd9, &SDMAEngine::setPageBaseLo});
122 sdmaFunc.insert({0xe1, &SDMAEngine::setPageRptrLo});
123 sdmaFunc.insert({0xe0, &SDMAEngine::setPageRptrHi});
126 sdmaFunc.insert({0x10b, &SDMAEngine::setPageWptrLo});
127 } else {
128 panic("Unknown GPU device %s\n", p.device_name);
129 }
130
131 // Setup PM4 packet processors and sanity check IDs
132 std::set<int> pm4_ids;
133 for (auto& pm4 : p.pm4_pkt_procs) {
134 pm4->setGPUDevice(this);
135 fatal_if(pm4_ids.count(pm4->getIpId()),
136 "Two PM4s with same IP IDs is not allowed");
137 pm4_ids.insert(pm4->getIpId());
138 pm4PktProcs.insert({pm4->getIpId(), pm4});
139
140 pm4Ranges.insert({pm4->getMMIORange(), pm4});
141 }
142
143 // There should be at least one PM4 packet processor with ID 0
144 fatal_if(!pm4PktProcs.count(0), "No default PM4 processor found");
145
146 deviceIH->setGPUDevice(this);
148 cp->setGPUDevice(this);
149 nbio.setGPUDevice(this);
150
151 // Address aperture for device memory. We tell this to the driver and
152 // could possibly be anything, but these are the values used by hardware.
153 uint64_t mmhubBase = 0x8000ULL << 24;
154 uint64_t mmhubTop = 0x83ffULL << 24;
155 uint64_t mem_size = 0x3ff0; // 16 GB of memory
156
157 gpuvm.setMMHUBBase(mmhubBase);
158 gpuvm.setMMHUBTop(mmhubTop);
159
160 // Map other MMIO apertures based on gfx version. This must be done before
161 // any calls to get/setRegVal.
162 // NBIO 0x0 - 0x4280
163 // IH 0x4280 - 0x4980
164 // GRBM 0x8000 - 0xC000
165 // GFX 0x28000 - 0x3F000
166 // MMHUB 0x68000 - 0x6a120
170 gpuvm.setMMIOAperture(GFX_MMIO_RANGE, AddrRange(0x28000, 0x3F000));
172
173 // These are hardcoded register values to return what the driver expects
175
176 // There are different registers for different GPUs, so we set the value
177 // based on the GPU type specified by the user.
178 if (p.device_name == "Vega10") {
179 setRegVal(VEGA10_FB_LOCATION_BASE, mmhubBase >> 24);
180 setRegVal(VEGA10_FB_LOCATION_TOP, mmhubTop >> 24);
181 } else if (p.device_name == "MI100") {
182 setRegVal(MI100_FB_LOCATION_BASE, mmhubBase >> 24);
183 setRegVal(MI100_FB_LOCATION_TOP, mmhubTop >> 24);
184 setRegVal(MI100_MEM_SIZE_REG, mem_size);
185 } else if (p.device_name == "MI200") {
186 // This device can have either 64GB or 128GB of device memory.
187 // This limits to 16GB for simulation.
188 setRegVal(MI200_FB_LOCATION_BASE, mmhubBase >> 24);
189 setRegVal(MI200_FB_LOCATION_TOP, mmhubTop >> 24);
190 setRegVal(MI200_MEM_SIZE_REG, mem_size);
191 } else if (p.device_name == "MI300X") {
192 setRegVal(MI200_FB_LOCATION_BASE, mmhubBase >> 24);
193 setRegVal(MI200_FB_LOCATION_TOP, mmhubTop >> 24);
194 setRegVal(MI200_MEM_SIZE_REG, mem_size);
195 } else {
196 panic("Unknown GPU device %s\n", p.device_name);
197 }
198}
199
200void
202{
203 Addr rom_offset = pkt->getAddr() & (ROM_SIZE - 1);
204 uint64_t rom_data = 0;
205
206 memcpy(&rom_data, rom.data() + rom_offset, pkt->getSize());
207 pkt->setUintX(rom_data, ByteOrder::little);
208
209 DPRINTF(AMDGPUDevice, "Read from addr %#x on ROM offset %#x data: %#x\n",
210 pkt->getAddr(), rom_offset, rom_data);
211}
212
213void
215{
216 assert(isROM(pkt->getAddr()));
217
218 Addr rom_offset = pkt->getAddr() - romRange.start();
219 uint64_t rom_data = pkt->getUintX(ByteOrder::little);
220
221 memcpy(rom.data() + rom_offset, &rom_data, pkt->getSize());
222
223 DPRINTF(AMDGPUDevice, "Write to addr %#x on ROM offset %#x data: %#x\n",
224 pkt->getAddr(), rom_offset, rom_data);
225}
226
229{
231 AddrRangeList ret_ranges;
232 ret_ranges.push_back(romRange);
233
234 // If the range starts at zero assume OS hasn't assigned it yet. Do not
235 // return ranges starting with zero as they will surely overlap with
236 // another range causing the I/O crossbar to fatal.
237 for (auto & r : ranges) {
238 if (r.start() != 0) {
239 ret_ranges.push_back(r);
240 }
241 }
242
243 return ret_ranges;
244}
245
246Tick
248{
249 int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
250
253 } else {
254 if (offset >= PXCAP_BASE && offset < (PXCAP_BASE + sizeof(PXCAP))) {
255 int pxcap_offset = offset - PXCAP_BASE;
256
257 switch (pkt->getSize()) {
258 case sizeof(uint8_t):
259 pkt->setLE<uint8_t>(pxcap.data[pxcap_offset]);
261 "Read PXCAP: dev %#x func %#x reg %#x 1 bytes: data "
262 "= %#x\n", _busAddr.dev, _busAddr.func, pxcap_offset,
263 (uint32_t)pkt->getLE<uint8_t>());
264 break;
265 case sizeof(uint16_t):
266 pkt->setLE<uint16_t>(
267 *(uint16_t*)&pxcap.data[pxcap_offset]);
269 "Read PXCAP: dev %#x func %#x reg %#x 2 bytes: data "
270 "= %#x\n", _busAddr.dev, _busAddr.func, pxcap_offset,
271 (uint32_t)pkt->getLE<uint16_t>());
272 break;
273 case sizeof(uint32_t):
274 pkt->setLE<uint32_t>(
275 *(uint32_t*)&pxcap.data[pxcap_offset]);
277 "Read PXCAP: dev %#x func %#x reg %#x 4 bytes: data "
278 "= %#x\n",_busAddr.dev, _busAddr.func, pxcap_offset,
279 (uint32_t)pkt->getLE<uint32_t>());
280 break;
281 default:
282 panic("Invalid access size (%d) for amdgpu PXCAP %#x\n",
283 pkt->getSize(), pxcap_offset);
284 }
285 pkt->makeAtomicResponse();
286 } else {
287 warn("Device specific offset %d not implemented!\n", offset);
288 }
289 }
290
291 // Before sending MMIOs the driver sends three interrupts in a row.
292 // Use this to trigger creating a checkpoint to restore in timing mode.
293 // This is only necessary until we can create a "hole" in the KVM VM
294 // around the VGA ROM region such that KVM exits and sends requests to
295 // this device rather than the KVM VM.
297 if (offset == PCI0_INTERRUPT_PIN) {
298 if (++init_interrupt_count == 3) {
299 DPRINTF(AMDGPUDevice, "Checkpointing before first MMIO\n");
300 exitSimLoop("checkpoint", 0, curTick() + configDelay + 1);
301 }
302 } else {
304 }
305 }
306
307 return configDelay;
308}
309
310Tick
312{
313 [[maybe_unused]] int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
314 DPRINTF(AMDGPUDevice, "Write Config: from offset: %#x size: %#x "
315 "data: %#x\n", offset, pkt->getSize(),
316 pkt->getUintX(ByteOrder::little));
317
319 return PciDevice::writeConfig(pkt);
320
321
322 if (offset >= PXCAP_BASE && offset < (PXCAP_BASE + sizeof(PXCAP))) {
323 uint8_t *pxcap_data = &(pxcap.data[0]);
324 int pxcap_offset = offset - PXCAP_BASE;
325
326 DPRINTF(AMDGPUDevice, "Writing PXCAP offset %d size %d\n",
327 pxcap_offset, pkt->getSize());
328
329 memcpy(pxcap_data + pxcap_offset, pkt->getConstPtr<void>(),
330 pkt->getSize());
331 }
332
333 pkt->makeAtomicResponse();
334
335 return configDelay;
336}
337
338void
340{
341 DPRINTF(AMDGPUDevice, "%s from addr %#x size: %#x data: %#x\n",
342 read ? "Read" : "Write", pkt->getAddr(), pkt->getSize(),
343 pkt->getUintX(ByteOrder::little));
344
345 pkt->makeAtomicResponse();
346}
347
348void
350{
351 DPRINTF(AMDGPUDevice, "Read framebuffer address %#lx\n", offset);
352
353 /*
354 * Return data for frame reads in priority order: (1) Special addresses
355 * first, ignoring any writes from driver. (2) Any other address from
356 * device backing store / abstract memory class functionally.
357 */
358 if (nbio.readFrame(pkt, offset)) {
359 return;
360 }
361
362 /*
363 * Read the value from device memory. This must be done functionally
364 * because this method is called by the PCIDevice::read method which
365 * is a non-timing read.
366 */
367 RequestPtr req = std::make_shared<Request>(
368 offset, pkt->getSize(), 0, vramRequestorId());
369
370 PacketPtr readPkt = new Packet(req, MemCmd::ReadReq);
371 uint8_t *dataPtr = new uint8_t[pkt->getSize()];
372 readPkt->dataDynamic(dataPtr);
373 readPkt->req->setGPUFuncAccess(true);
374 readPkt->setSuppressFuncError();
375 cp->shader()->cuList[0]->memPort[0].sendFunctional(readPkt);
376 if (readPkt->cmd == MemCmd::FunctionalReadError) {
377 delete readPkt;
378 delete[] dataPtr;
379 RequestPtr req = std::make_shared<Request>(offset, pkt->getSize(), 0,
381 PacketPtr readPkt = Packet::createRead(req);
382 uint8_t *dataPtr = new uint8_t[pkt->getSize()];
383 readPkt->dataDynamic(dataPtr);
384
385 auto system = cp->shader()->gpuCmdProc.system();
386 system->getDeviceMemory(readPkt)->access(readPkt);
387 }
388
389 pkt->setUintX(readPkt->getUintX(ByteOrder::little), ByteOrder::little);
390 delete readPkt;
391}
392
393void
399
400void
402{
404 Addr aperture_offset = offset - aperture.start();
405
406 // By default read from MMIO trace. Overwrite the packet for a select
407 // few more dynamic MMIOs.
408 DPRINTF(AMDGPUDevice, "Read MMIO %#lx\n", offset);
410
411 if (aperture == gpuvm.getMMIORange(NBIO_MMIO_RANGE)) {
412 DPRINTF(AMDGPUDevice, "NBIO base\n");
413 nbio.readMMIO(pkt, aperture_offset);
414 } else if (aperture == gpuvm.getMMIORange(GRBM_MMIO_RANGE)) {
415 DPRINTF(AMDGPUDevice, "GRBM base\n");
416 gpuvm.readMMIO(pkt, aperture_offset >> GRBM_OFFSET_SHIFT);
417 } else if (aperture == gpuvm.getMMIORange(GFX_MMIO_RANGE)) {
418 DPRINTF(AMDGPUDevice, "GFX base\n");
419 gfx.readMMIO(pkt, aperture_offset);
420 } else if (aperture == gpuvm.getMMIORange(MMHUB_MMIO_RANGE)) {
421 DPRINTF(AMDGPUDevice, "MMHUB base\n");
422 gpuvm.readMMIO(pkt, aperture_offset >> MMHUB_OFFSET_SHIFT);
423 } else {
424 DPRINTF(AMDGPUDevice, "Unknown MMIO aperture for read %#x\n", offset);
425 }
426}
427
428void
430{
431 DPRINTF(AMDGPUDevice, "Wrote framebuffer address %#lx\n", offset);
432
433 for (auto& cu: CP()->shader()->cuList) {
434 Addr aligned_addr = offset & ~(gpuMemMgr->getCacheLineSize() - 1);
435 cu->sendInvL2(aligned_addr);
436 }
437
438 Addr aperture = gpuvm.getFrameAperture(offset);
439 Addr aperture_offset = offset - aperture;
440
441 // Record the value
442 if (aperture == gpuvm.gartBase()) {
443 gpuvm.gartTable[aperture_offset] = pkt->getUintX(ByteOrder::little);
444 DPRINTF(AMDGPUDevice, "GART translation %p -> %p\n", aperture_offset,
445 gpuvm.gartTable[aperture_offset]);
446 }
447
448 nbio.writeFrame(pkt, offset);
449
450 /*
451 * Write the value to device memory. This must be done functionally
452 * because this method is called by the PCIDevice::write method which
453 * is a non-timing write.
454 */
455 RequestPtr req = std::make_shared<Request>(offset, pkt->getSize(), 0,
457 PacketPtr writePkt = Packet::createWrite(req);
458 uint8_t *dataPtr = new uint8_t[pkt->getSize()];
459 std::memcpy(dataPtr, pkt->getPtr<uint8_t>(),
460 pkt->getSize() * sizeof(uint8_t));
461 writePkt->dataDynamic(dataPtr);
462
463 auto system = cp->shader()->gpuCmdProc.system();
464 system->getDeviceMemory(writePkt)->access(writePkt);
465
466 delete writePkt;
467}
468
469void
471{
472 DPRINTF(AMDGPUDevice, "Wrote doorbell %#lx\n", offset);
473
474 if (doorbells.find(offset) != doorbells.end()) {
475 QueueType q_type = doorbells[offset].qtype;
476 int ip_id = doorbells[offset].ip_id;
477 DPRINTF(AMDGPUDevice, "Doorbell offset %p queue: %d\n",
478 offset, q_type);
479 switch (q_type) {
480 case Compute:
481 assert(pm4PktProcs.count(ip_id));
482 pm4PktProcs[ip_id]->process(
483 pm4PktProcs[ip_id]->getQueue(offset),
484 pkt->getLE<uint64_t>());
485 break;
486 case Gfx:
487 assert(pm4PktProcs.count(ip_id));
488 pm4PktProcs[ip_id]->process(
489 pm4PktProcs[ip_id]->getQueue(offset, true),
490 pkt->getLE<uint64_t>());
491 break;
492 case SDMAGfx: {
493 SDMAEngine *sdmaEng = getSDMAEngine(offset);
494 sdmaEng->processGfx(pkt->getLE<uint64_t>());
495 } break;
496 case SDMAPage: {
497 SDMAEngine *sdmaEng = getSDMAEngine(offset);
498 sdmaEng->processPage(pkt->getLE<uint64_t>());
499 } break;
500 case ComputeAQL: {
501 assert(pm4PktProcs.count(ip_id));
503 pkt->getLE<uint64_t>() + 1);
504 pm4PktProcs[ip_id]->updateReadIndex(offset,
505 pkt->getLE<uint64_t>() + 1);
506 } break;
507 case InterruptHandler:
508 deviceIH->updateRptr(pkt->getLE<uint32_t>());
509 break;
510 case RLC: {
511 SDMAEngine *sdmaEng = getSDMAEngine(offset);
512 sdmaEng->processRLC(offset, pkt->getLE<uint64_t>());
513 } break;
514 default:
515 panic("Write to unkown queue type!");
516 }
517 } else {
518 warn("Unknown doorbell offset: %lx. Saving to pending doorbells.\n",
519 offset);
520
521 // We have to ACK the PCI packet immediately, so create a copy of the
522 // packet here to send again. The packet data contains the value of
523 // the doorbell to write so we need to copy that as the original
524 // packet gets deleted after the PCI write() method returns.
525 RequestPtr pending_req(pkt->req);
526 PacketPtr pending_pkt = Packet::createWrite(pending_req);
527 uint8_t *pending_data = new uint8_t[pkt->getSize()];
528 memcpy(pending_data, pkt->getPtr<uint8_t>(), pkt->getSize());
529 pending_pkt->dataDynamic(pending_data);
530
531 pendingDoorbellPkts.emplace(offset, pending_pkt);
532 }
533}
534
535void
537{
539 Addr aperture_offset = offset - aperture.start();
540
541 DPRINTF(AMDGPUDevice, "Wrote MMIO %#lx\n", offset);
542
543 // Check SDMA functions first, then fallback to MMIO ranges.
544 for (int idx = 0; idx < sdmaIds.size(); ++idx) {
545 if (sdmaMmios[idx].contains(offset)) {
546 Addr sdma_offset = (offset - sdmaMmios[idx].start()) >> 2;
547 if (sdmaFunc.count(sdma_offset)) {
548 DPRINTF(AMDGPUDevice, "Calling SDMA%d MMIO function %lx\n",
549 idx, sdma_offset);
550 sdmaFuncPtr mptr = sdmaFunc[sdma_offset];
551 (getSDMAById(idx)->*mptr)(pkt->getLE<uint32_t>());
552 } else {
553 DPRINTF(AMDGPUDevice, "Unknown SDMA%d MMIO: %#lx\n", idx,
554 sdma_offset);
555 }
556
557 return;
558 }
559 }
560
561 // Check PM4s next, returning to avoid duplicate writes.
562 for (auto& [range, pm4_proc] : pm4Ranges) {
563 if (range.contains(offset)) {
564 // PM4 MMIOs are offset based on the MMIO range start
565 Addr ip_offset = offset - range.start();
566 pm4_proc->writeMMIO(pkt, ip_offset >> GRBM_OFFSET_SHIFT);
567
568 return;
569 }
570 }
571
572 if (aperture == gpuvm.getMMIORange(GRBM_MMIO_RANGE)) {
573 DPRINTF(AMDGPUDevice, "GRBM base\n");
574 gpuvm.writeMMIO(pkt, aperture_offset >> GRBM_OFFSET_SHIFT);
575 } else if (aperture == gpuvm.getMMIORange(IH_MMIO_RANGE)) {
576 DPRINTF(AMDGPUDevice, "IH base\n");
577 deviceIH->writeMMIO(pkt, aperture_offset >> IH_OFFSET_SHIFT);
578 } else if (aperture == gpuvm.getMMIORange(NBIO_MMIO_RANGE)) {
579 DPRINTF(AMDGPUDevice, "NBIO base\n");
580 nbio.writeMMIO(pkt, aperture_offset);
581 } else if (aperture == gpuvm.getMMIORange(GFX_MMIO_RANGE)) {
582 DPRINTF(AMDGPUDevice, "GFX base\n");
583 gfx.writeMMIO(pkt, aperture_offset);
584 } else {
585 DPRINTF(AMDGPUDevice, "Unknown MMIO aperture for write %#x\n", offset);
586 }
587}
588
589Tick
591{
592 if (isROM(pkt->getAddr())) {
593 readROM(pkt);
594 } else {
595 int barnum = -1;
596 Addr offset = 0;
597 getBAR(pkt->getAddr(), barnum, offset);
598
599 switch (barnum) {
600 case FRAMEBUFFER_BAR:
601 readFrame(pkt, offset);
602 break;
603 case DOORBELL_BAR:
604 readDoorbell(pkt, offset);
605 break;
606 case MMIO_BAR:
607 readMMIO(pkt, offset);
608 break;
609 default:
610 panic("Request with address out of mapped range!");
611 }
612 }
613
614 dispatchAccess(pkt, true);
615 return pioDelay;
616}
617
618Tick
620{
621 if (isROM(pkt->getAddr())) {
622 writeROM(pkt);
623
624 dispatchAccess(pkt, false);
625
626 return pioDelay;
627 }
628
629 int barnum = -1;
630 Addr offset = 0;
631 getBAR(pkt->getAddr(), barnum, offset);
632
633 switch (barnum) {
634 case FRAMEBUFFER_BAR:
635 writeFrame(pkt, offset);
636 break;
637 case DOORBELL_BAR:
638 writeDoorbell(pkt, offset);
639 break;
640 case MMIO_BAR:
641 writeMMIO(pkt, offset);
642 break;
643 default:
644 panic("Request with address out of mapped range!");
645 }
646
647 // Record only if there is non-zero value, or a value to be overwritten.
648 // Reads return 0 by default.
649 uint64_t data = pkt->getUintX(ByteOrder::little);
650
651 DPRINTF(AMDGPUDevice, "PCI Write to %#lx data %#lx\n",
652 pkt->getAddr(), data);
653
654 dispatchAccess(pkt, false);
655
656 return pioDelay;
657}
658
659void
661{
662 if (pendingDoorbellPkts.count(offset)) {
663 DPRINTF(AMDGPUDevice, "Sending pending doorbell %x\n", offset);
667 }
668}
669
670uint32_t
672{
673 // This is somewhat of a guess based on amdgpu_device_mm_access
674 // in amdgpu_device.c in the ROCk driver. If bit 32 is 1 then
675 // assume VRAM and use full address, otherwise assume register
676 // address and only user lower 31 bits.
677 Addr fixup_addr = bits(addr, 31, 31) ? addr : addr & 0x7fffffff;
678
679 uint32_t pkt_data = 0;
680 RequestPtr request = std::make_shared<Request>(fixup_addr,
681 sizeof(uint32_t), 0 /* flags */, vramRequestorId());
682 PacketPtr pkt = Packet::createRead(request);
683 pkt->dataStatic((uint8_t *)&pkt_data);
684 readMMIO(pkt, addr);
685 DPRINTF(AMDGPUDevice, "Getting register 0x%lx = %x\n",
686 fixup_addr, pkt->getLE<uint32_t>());
687
688 pkt_data = pkt->getLE<uint32_t>();
689 delete pkt;
690
691 return pkt_data;
692}
693
694void
695AMDGPUDevice::setRegVal(uint64_t addr, uint32_t value)
696{
697 DPRINTF(AMDGPUDevice, "Setting register 0x%lx to %x\n",
698 addr, value);
699
700 uint32_t pkt_data = value;
701 RequestPtr request = std::make_shared<Request>(addr,
702 sizeof(uint32_t), 0 /* flags */, vramRequestorId());
703 PacketPtr pkt = Packet::createWrite(request);
704 pkt->dataStatic((uint8_t *)&pkt_data);
705 writeMMIO(pkt, addr);
706 delete pkt;
707}
708
709void
711{
712 DPRINTF(AMDGPUDevice, "Setting doorbell type for %x\n", offset);
713 doorbells[offset].qtype = qt;
714 doorbells[offset].ip_id = ip_id;
715}
716
717void
719{
720 doorbells.erase(offset);
721}
722
723void
728
731{
736 assert(sdmaIds.count(id));
737
738 return sdmaIds[id];
739}
740
746
747void
752
753void
755{
756 // Serialize the PciDevice base class
758
759 uint64_t doorbells_size = doorbells.size();
760 uint64_t sdma_engs_size = sdmaEngs.size();
761 uint64_t used_vmid_map_size = usedVMIDs.size();
762
763 SERIALIZE_SCALAR(doorbells_size);
764 SERIALIZE_SCALAR(sdma_engs_size);
765 // Save the number of vmids used
766 SERIALIZE_SCALAR(used_vmid_map_size);
767
768 // Make a c-style array of the regs to serialize
769 uint32_t doorbells_offset[doorbells_size];
770 QueueType doorbells_queues[doorbells_size];
771 int doorbells_ip_ids[doorbells_size];
772 uint32_t sdma_engs_offset[sdma_engs_size];
773 int sdma_engs[sdma_engs_size];
774 int used_vmids[used_vmid_map_size];
775 int used_queue_id_sizes[used_vmid_map_size];
776 std::vector<int> used_vmid_sets;
777
778 int idx = 0;
779 for (auto & it : doorbells) {
780 doorbells_offset[idx] = it.first;
781 doorbells_queues[idx] = it.second.qtype;
782 doorbells_ip_ids[idx] = it.second.ip_id;
783 ++idx;
784 }
785
786 idx = 0;
787 for (auto & it : sdmaEngs) {
788 sdma_engs_offset[idx] = it.first;
789 sdma_engs[idx] = it.second->getId();
790 ++idx;
791 }
792
793 idx = 0;
794 for (auto & it : usedVMIDs) {
795 used_vmids[idx] = it.first;
796 used_queue_id_sizes[idx] = it.second.size();
797 std::vector<int> set_vector(it.second.begin(), it.second.end());
798 used_vmid_sets.insert(used_vmid_sets.end(),
799 set_vector.begin(), set_vector.end());
800 ++idx;
801 }
802
803 int num_queue_id = used_vmid_sets.size();
804 int* vmid_array = new int[num_queue_id];
805 std::copy(used_vmid_sets.begin(), used_vmid_sets.end(), vmid_array);
806
807 SERIALIZE_ARRAY(doorbells_offset, sizeof(doorbells_offset)/
808 sizeof(doorbells_offset[0]));
809 SERIALIZE_ARRAY(doorbells_queues, sizeof(doorbells_queues)/
810 sizeof(doorbells_queues[0]));
811 SERIALIZE_ARRAY(doorbells_ip_ids, sizeof(doorbells_ip_ids)/
812 sizeof(doorbells_ip_ids[0]));
813 SERIALIZE_ARRAY(sdma_engs_offset, sizeof(sdma_engs_offset)/
814 sizeof(sdma_engs_offset[0]));
815 SERIALIZE_ARRAY(sdma_engs, sizeof(sdma_engs)/sizeof(sdma_engs[0]));
816 // Save the vmids used in an array
817 SERIALIZE_ARRAY(used_vmids, sizeof(used_vmids)/sizeof(used_vmids[0]));
818 // Save the size of the set of queue ids mapped to each vmid
819 SERIALIZE_ARRAY(used_queue_id_sizes,
820 sizeof(used_queue_id_sizes)/sizeof(used_queue_id_sizes[0]));
821 // Save all the queue ids used for all the vmids
822 SERIALIZE_ARRAY(vmid_array, num_queue_id);
823 // Save the total number of queue idsused
824 SERIALIZE_SCALAR(num_queue_id);
825
826 // Serialize the device memory
827 deviceMem.serializeSection(cp, "deviceMem");
828 gpuvm.serializeSection(cp, "GPUVM");
829
830 delete[] vmid_array;
831}
832
833void
835{
836 // Unserialize the PciDevice base class
838
839 uint64_t doorbells_size = 0;
840 uint64_t sdma_engs_size = 0;
841 uint64_t used_vmid_map_size = 0;
842
843 UNSERIALIZE_SCALAR(doorbells_size);
844 UNSERIALIZE_SCALAR(sdma_engs_size);
845 UNSERIALIZE_SCALAR(used_vmid_map_size);
846
847
848 if (doorbells_size > 0) {
849 uint32_t doorbells_offset[doorbells_size];
850 QueueType doorbells_queues[doorbells_size];
851 int doorbells_ip_ids[doorbells_size];
852
853 UNSERIALIZE_ARRAY(doorbells_offset, sizeof(doorbells_offset)/
854 sizeof(doorbells_offset[0]));
855 UNSERIALIZE_ARRAY(doorbells_queues, sizeof(doorbells_queues)/
856 sizeof(doorbells_queues[0]));
857 UNSERIALIZE_ARRAY(doorbells_ip_ids, sizeof(doorbells_ip_ids)/
858 sizeof(doorbells_ip_ids[0]));
859
860 for (int idx = 0; idx < doorbells_size; ++idx) {
861 doorbells[doorbells_offset[idx]].qtype = doorbells_queues[idx];
862 doorbells[doorbells_offset[idx]].ip_id = doorbells_ip_ids[idx];
863 }
864 }
865
866 if (sdma_engs_size > 0) {
867 uint32_t sdma_engs_offset[sdma_engs_size];
868 int sdma_engs[sdma_engs_size];
869
870 UNSERIALIZE_ARRAY(sdma_engs_offset, sizeof(sdma_engs_offset)/
871 sizeof(sdma_engs_offset[0]));
872 UNSERIALIZE_ARRAY(sdma_engs, sizeof(sdma_engs)/sizeof(sdma_engs[0]));
873
874 for (int idx = 0; idx < sdma_engs_size; ++idx) {
875 int sdma_id = sdma_engs[idx];
876 assert(sdmaIds.count(sdma_id));
877 SDMAEngine *sdma = sdmaIds[sdma_id];
878 sdmaEngs.insert(std::make_pair(sdma_engs_offset[idx], sdma));
879 }
880 }
881
882 if (used_vmid_map_size > 0) {
883 int used_vmids[used_vmid_map_size];
884 int used_queue_id_sizes[used_vmid_map_size];
885 int num_queue_id = 0;
886 std::vector<int> used_vmid_sets;
887 // Extract the total number of queue ids used
888 UNSERIALIZE_SCALAR(num_queue_id);
889 int* vmid_array = new int[num_queue_id];
890 // Extract the number of vmids used
891 UNSERIALIZE_ARRAY(used_vmids, used_vmid_map_size);
892 // Extract the size of the queue id set for each vmid
893 UNSERIALIZE_ARRAY(used_queue_id_sizes, used_vmid_map_size);
894 // Extract all the queue ids used
895 UNSERIALIZE_ARRAY(vmid_array, num_queue_id);
896 // Populate the usedVMIDs map with the queue ids per vm
897 int idx = 0;
898 for (int it = 0; it < used_vmid_map_size; it++) {
899 int vmid = used_vmids[it];
900 int vmid_set_size = used_queue_id_sizes[it];
901 for (int j = 0; j < vmid_set_size; j++) {
902 usedVMIDs[vmid].insert(vmid_array[idx + j]);
903 }
904 idx += vmid_set_size;
905 }
906 delete[] vmid_array;
907 }
908
909 // Unserialize the device memory
910 deviceMem.unserializeSection(cp, "deviceMem");
911 gpuvm.unserializeSection(cp, "GPUVM");
912}
913
914uint16_t
916{
917 for (uint16_t vmid = 1; vmid < AMDGPU_VM_COUNT; vmid++) {
918 auto result = usedVMIDs.find(vmid);
919 if (result == usedVMIDs.end()) {
920 idMap.insert(std::make_pair(pasid, vmid));
921 usedVMIDs[vmid] = {};
922 _lastVMID = vmid;
923 return vmid;
924 }
925 }
926 panic("All VMIDs have been assigned");
927}
928
929void
931{
932 usedVMIDs.erase(vmid);
933}
934
935void
937{
938 auto result = idMap.find(pasid);
939 assert(result != idMap.end());
940 if (result == idMap.end()) return;
941 uint16_t vmid = result->second;
942
943 idMap.erase(result);
944 usedVMIDs.erase(vmid);
945}
946
947void
949{
950 idMap.erase(idMap.begin(), idMap.end());
951 usedVMIDs.erase(usedVMIDs.begin(), usedVMIDs.end());
952
953 for (auto& it : sdmaEngs) {
954 it.second->deallocateRLCQueues(unmap_static);
955 }
956
957 // "All" queues implicitly refers to all user queues. User queues begin at
958 // doorbell address 0x4000, so unmap any queue at or above that address.
959 for (auto [offset, vmid] : doorbellVMIDMap) {
960 if (offset >= 0x4000) {
961 doorbells.erase(offset);
962 }
963 }
964}
965
966void
967AMDGPUDevice::mapDoorbellToVMID(Addr doorbell, uint16_t vmid)
968{
969 doorbellVMIDMap[doorbell] = vmid;
970}
971
972std::unordered_map<uint16_t, std::set<int>>&
974{
975 return usedVMIDs;
976}
977
978void
979AMDGPUDevice::insertQId(uint16_t vmid, int id)
980{
981 usedVMIDs[vmid].insert(id);
982}
983
984} // namespace gem5
AbstractMemory declaration.
#define AMDGPU_MP0_SMN_C2PMSG_33
#define VEGA10_FB_LOCATION_BASE
Definition amdgpu_vm.hh:77
#define VEGA10_FB_LOCATION_TOP
Definition amdgpu_vm.hh:78
#define MI200_MEM_SIZE_REG
Definition amdgpu_vm.hh:84
#define MI200_FB_LOCATION_TOP
Definition amdgpu_vm.hh:86
#define MI100_FB_LOCATION_BASE
Definition amdgpu_vm.hh:81
#define MI200_FB_LOCATION_BASE
Definition amdgpu_vm.hh:85
#define MI100_FB_LOCATION_TOP
Definition amdgpu_vm.hh:82
#define MI100_MEM_SIZE_REG
Definition amdgpu_vm.hh:80
#define DPRINTF(x,...)
Definition trace.hh:209
const char data[]
Device model for an AMD GPU.
void insertQId(uint16_t vmid, int id)
std::unordered_map< AddrRange, PM4PacketProcessor *, AddrRangeHasher > pm4Ranges
void deallocateAllQueues(bool unmap_static)
std::unordered_map< Addr, uint16_t > doorbellVMIDMap
std::unordered_map< uint16_t, uint16_t > idMap
void readMMIO(PacketPtr pkt, Addr offset)
void serialize(CheckpointOut &cp) const override
Checkpoint support.
void processPendingDoorbells(uint32_t offset)
AddrRangeList getAddrRanges() const override
Every PIO device is obliged to provide an implementation that returns the address ranges the device r...
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void writeMMIO(PacketPtr pkt, Addr offset)
GPUCommandProcessor * cp
void setDoorbellType(uint32_t offset, QueueType qt, int ip_id=0)
Set handles to GPU blocks.
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
void readROM(PacketPtr pkt)
AddrRange romRange
VGA ROM methods.
std::unordered_map< uint32_t, DoorbellInfo > doorbells
Structures to hold registers, doorbells, and some frame memory.
std::unordered_map< uint16_t, std::set< int > > & getUsedVMIDs()
std::array< uint8_t, ROM_SIZE > rom
bool isROM(Addr addr) const
void unsetDoorbell(uint32_t offset)
std::unordered_map< uint32_t, PacketPtr > pendingDoorbellPkts
void setRegVal(uint64_t addr, uint32_t value)
std::unordered_map< uint32_t, AddrRange > sdmaMmios
void(SDMAEngine::* sdmaFuncPtr)(uint32_t)
SDMAEngine * getSDMAEngine(Addr offset)
AMDGPUMemoryManager * gpuMemMgr
AMDGPUDevice(const AMDGPUDeviceParams &p)
void readDoorbell(PacketPtr pkt, Addr offset)
AMDGPUNbio nbio
Blocks of the GPU.
Tick readConfig(PacketPtr pkt) override
Read from the PCI config space data that is stored locally.
std::unordered_map< uint32_t, sdmaFuncPtr > sdmaFunc
std::unordered_map< uint16_t, std::set< int > > usedVMIDs
AMDGPUInterruptHandler * deviceIH
Tick writeConfig(PacketPtr pkt) override
Write to the PCI config space data that is stored locally.
AMDMMIOReader mmioReader
MMIO reader to populate device registers map.
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
bool checkpoint_before_mmios
Initial checkpoint support variables.
void dispatchAccess(PacketPtr pkt, bool read)
Convert a PCI packet into a response.
uint32_t getRegVal(uint64_t addr)
Register value getter/setter.
void deallocateVmid(uint16_t vmid)
void mapDoorbellToVMID(Addr doorbell, uint16_t vmid)
void intrPost()
Methods inherited from PciDevice.
void readFrame(PacketPtr pkt, Addr offset)
Helper methods to handle specific BAR read/writes.
void writeROM(PacketPtr pkt)
void writeDoorbell(PacketPtr pkt, Addr offset)
RequestorID vramRequestorId()
Methods related to translations and system/device memory.
std::unordered_map< uint32_t, SDMAEngine * > sdmaIds
uint16_t allocateVMID(uint16_t pasid)
std::unordered_map< int, PM4PacketProcessor * > pm4PktProcs
void deallocatePasid(uint16_t pasid)
SDMAEngine * getSDMAById(int id)
void writeFrame(PacketPtr pkt, Addr offset)
void setSDMAEngine(Addr offset, SDMAEngine *eng)
memory::PhysicalMemory deviceMem
std::unordered_map< uint32_t, SDMAEngine * > sdmaEngs
GPUCommandProcessor * CP()
void readMMIO(PacketPtr pkt, Addr offset)
Definition amdgpu_gfx.cc:48
void writeMMIO(PacketPtr pkt, Addr offset)
Definition amdgpu_gfx.cc:66
void setGPUDevice(AMDGPUDevice *gpu_device)
void updateRptr(const uint32_t &data)
void writeMMIO(PacketPtr pkt, Addr mmio_offset)
Methods for setting the values of interrupt handler MMIO registers.
RequestorID getRequestorID() const
Get the requestorID for the memory manager.
void readMMIO(PacketPtr pkt, Addr offset)
void writeMMIO(PacketPtr pkt, Addr offset)
bool readFrame(PacketPtr pkt, Addr offset)
void writeFrame(PacketPtr pkt, Addr offset)
void setGPUDevice(AMDGPUDevice *gpu_device)
void setMMIOAperture(mmio_range_t mmio_aperture, AddrRange range)
Definition amdgpu_vm.cc:62
void setMMHUBBase(Addr base)
Definition amdgpu_vm.hh:230
AddrRange getMMIORange(mmio_range_t mmio_aperture)
Definition amdgpu_vm.cc:68
std::unordered_map< uint64_t, uint64_t > gartTable
Copy of GART table.
Definition amdgpu_vm.hh:203
void readMMIO(PacketPtr pkt, Addr offset)
Definition amdgpu_vm.cc:99
const AddrRange & getMMIOAperture(Addr addr)
Definition amdgpu_vm.cc:74
void writeMMIO(PacketPtr pkt, Addr offset)
Definition amdgpu_vm.cc:135
Addr getFrameAperture(Addr addr)
Definition amdgpu_vm.hh:259
Addr gartBase()
Return base address of GART table in framebuffer.
Definition amdgpu_vm.cc:87
void setMMHUBTop(Addr top)
Definition amdgpu_vm.hh:231
void readFromTrace(PacketPtr pkt, int barnum, Addr offset)
Get the next MMIO read from the trace file to an offset in a BAR and write the value to the packet pr...
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition addr_range.hh:82
void setGPUDevice(AMDGPUDevice *gpu_device)
HSAPacketProcessor & hsaPacketProc()
void setGPUDevice(AMDGPUDevice *gpu_device)
void write(Addr db_addr, uint64_t doorbell_reg)
@ FunctionalReadError
Definition packet.hh:139
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
void setUintX(uint64_t w, ByteOrder endian)
Set the value in the word w after truncating it to the length of the packet and then byteswapping it ...
Definition packet.cc:361
void setLE(T v)
Set the value in the data pointer to v as little endian.
static PacketPtr createWrite(const RequestPtr &req)
Definition packet.hh:1044
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Definition packet.hh:1175
T * getPtr()
get a pointer to the data ptr.
Definition packet.hh:1225
static PacketPtr createRead(const RequestPtr &req)
Constructor-like methods that return Packets based on Request objects.
Definition packet.hh:1038
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
unsigned getSize() const
Definition packet.hh:817
uint64_t getUintX(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness and zero-extended to 64 bits.
Definition packet.cc:352
const T * getConstPtr() const
Definition packet.hh:1234
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition packet.hh:1213
void makeAtomicResponse()
Definition packet.hh:1074
MemCmd cmd
The command field of the packet.
Definition packet.hh:372
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
void setSuppressFuncError()
Definition packet.hh:757
PCI device, base implementation is only config space.
Definition device.hh:270
PCIConfig config
The current config space.
Definition device.hh:275
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Definition device.cc:464
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Definition device.cc:401
bool getBAR(Addr addr, int &num, Addr &offs)
Which base address register (if any) maps the given address?
Definition device.hh:320
AddrRangeList getAddrRanges() const override
Determine the address ranges that this device responds to.
Definition device.cc:269
const PciBusAddr _busAddr
Definition device.hh:272
virtual Tick readConfig(PacketPtr pkt)
Read from the PCI config space data that is stored locally.
Definition device.cc:212
virtual Tick writeConfig(PacketPtr pkt)
Write to the PCI config space data that is stored locally.
Definition device.cc:283
void intrPost()
Definition device.hh:364
const int PXCAP_BASE
Definition device.hh:300
System DMA Engine class for AMD dGPU.
void setPageRptrLo(uint32_t data)
void setGfxRptrLo(uint32_t data)
void setGfxWptrLo(uint32_t data)
void setGfxRptrHi(uint32_t data)
void processRLC(Addr doorbellOffset, Addr wptrOffset)
void setGfxSize(uint32_t data)
void setGfxBaseLo(uint32_t data)
void processGfx(Addr wptrOffset)
Given a new write ptr offset, communicated to the GPU through a doorbell write, the SDMA engine proce...
void setGfxWptrHi(uint32_t data)
void setGfxDoorbellOffsetLo(uint32_t data)
void processPage(Addr wptrOffset)
void setPageDoorbellOffsetLo(uint32_t data)
void setPageWptrLo(uint32_t data)
void setGfxDoorbellLo(uint32_t data)
void setPageDoorbellLo(uint32_t data)
void setPageSize(uint32_t data)
void setPageBaseLo(uint32_t data)
void setGfxBaseHi(uint32_t data)
void setPageRptrHi(uint32_t data)
std::vector< ComputeUnit * > cuList
Definition shader.hh:268
GPUCommandProcessor & gpuCmdProc
Definition shader.hh:270
memory::AbstractMemory * getDeviceMemory(const PacketPtr &pkt) const
Return a pointer to the device memory.
Definition system.cc:311
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
STL vector class.
Definition stl.hh:37
The GPUCommandProcessor (CP) is responsible for accepting commands, in the form of HSA AQL packets,...
AddrRange RangeSize(Addr start, Addr size)
Addr start() const
Get the start address of the range.
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:188
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
Definition serialize.cc:74
#define UNSERIALIZE_ARRAY(member, size)
Definition serialize.hh:618
#define SERIALIZE_ARRAY(member, size)
Definition serialize.hh:610
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
Definition serialize.cc:81
#define warn(...)
Definition logging.hh:256
Bitfield< 4 > s
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 33 > id
Bitfield< 0 > m
Bitfield< 0 > p
Bitfield< 15 > system
Definition misc.hh:1032
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
std::shared_ptr< Request > RequestPtr
Definition request.hh:94
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
constexpr int MMIO_BAR
std::ostream CheckpointOut
Definition serialize.hh:66
@ InterruptHandler
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
Bitfield< 10 > pasid
Definition x86_cpu.cc:129
uint64_t Tick
Tick count type.
Definition types.hh:58
constexpr uint32_t ROM_SIZE
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
Definition sim_events.cc:88
static constexpr uint32_t IH_OFFSET_SHIFT
static constexpr uint32_t MMHUB_OFFSET_SHIFT
static constexpr int AMDGPU_VM_COUNT
constexpr int FRAMEBUFFER_BAR
@ GRBM_MMIO_RANGE
Definition amdgpu_vm.hh:107
@ GFX_MMIO_RANGE
Definition amdgpu_vm.hh:106
@ IH_MMIO_RANGE
Definition amdgpu_vm.hh:108
@ MMHUB_MMIO_RANGE
Definition amdgpu_vm.hh:105
@ NBIO_MMIO_RANGE
Definition amdgpu_vm.hh:104
constexpr int DOORBELL_BAR
constexpr uint32_t VGA_ROM_DEFAULT
static constexpr uint32_t GRBM_OFFSET_SHIFT
Declaration of the Packet class.
#define PCI0_INTERRUPT_PIN
Definition pcireg.h:135
#define PCI_DEVICE_SPECIFIC
Definition pcireg.h:164
#define PCI_CONFIG_SIZE
Definition pcireg.h:165
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568
uint8_t func
Definition types.hh:58
uint8_t dev
Definition types.hh:57
const std::string & name()
Definition trace.cc:48
Defines the PCI Express capability register and its associated bitfields for a PCIe device.
Definition pcireg.h:330
uint8_t data[48]
Definition pcireg.h:331

Generated on Mon Jan 13 2025 04:28:33 for gem5 by doxygen 1.9.8