dev — Device Models

Hardware Peripheral Simulation Framework

The dev module provides device models that connect to gem5's memory system through PIO and DMA ports. It implements PCI bus infrastructure, Ethernet NICs, storage controllers, VirtIO Device Framework | gem5 Wiki" href="virtio/index.html">VirtIO paravirtualized devices, AArch32, AArch64, TrustZone security extensions, SVE/SVE2 vector processing, PMU, and hardware transactional memory." href="../arch_doc/arm/index.html">ARM interrupt controllers, serial ports, and platform-specific peripherals needed for full-system simulation.

PCI Bus Ethernet NICs ARM GIC VirtIO Storage

16
Sub-Modules
418
Source Files
PIO+DMA
Port Model
C++
Language

📜 Table of Contents

Module Overview

📚 What is this & why does it exist?

The dev module is gem5's hardware peripheral layer. In a real computer, the CPU communicates with devices (network cards, disks, GPUs) through memory-mapped I/O (MMIO) and DMA. The dev module models these interactions so that a full operating system can boot, discover hardware, load drivers, and run I/O workloads inside the simulator.

💡 Real-world analogy

Think of the dev module as a collection of virtual appliances plugged into a simulated motherboard. Just as your physical PC has a network card in a PCIe slot, a SATA disk, and a USB controller — each with its own registers and DMA engine — gem5's device models present the same register interfaces and transfer mechanisms. The OS running inside gem5 sees "real" hardware and uses its normal drivers, even though everything is happening in software.

Device Architecture

All devices in gem5 inherit from a hierarchy rooted in ClockedObject. The base device classes provide the port infrastructure to communicate with the memory bus:

flowchart LR
  subgraph BaseClasses["Base Device Classes"]
    CO["ClockedObject"]
    PIO["PioDevice\n<i>PioPort for MMIO</i>"]
    BPIO["BasicPioDevice\n<i>fixed addr + size</i>"]
    DMA["DmaDevice\n<i>+ DmaPort for DMA</i>"]
  end

  subgraph PCIStack["PCI Stack"]
    PCID["PciDevice\n<i>config space, BARs</i>"]
    PCIE["PciEndpoint\n<i>Type 0 header</i>"]
    PCIB["PciType1Device\n<i>Bridge / Type 1</i>"]
    HOST["PciHost\n<i>root complex</i>"]
    BUS["PciBus\n<i>non-coherent xbar</i>"]
  end

  subgraph NetDevices["Network"]
    ELINK["EtherLink\n<i>point-to-point</i>"]
    EBUS["EtherBus\n<i>shared medium</i>"]
    ESWITCH["EtherSwitch"]
    NIC["NsGigE / IGbE / Sinic"]
  end

  subgraph StorageDevices["Storage"]
    IDEC["IdeController"]
    IDED["IdeDisk"]
    DIMG["DiskImage"]
  end

  subgraph VirtIODevices["VirtIO"]
    VDB["VirtIODeviceBase"]
    VQ["VirtQueue"]
    VBK["VirtIOBlock"]
    VCN["VirtIOConsole"]
  end

  subgraph Platform["Platform & Interrupts"]
    PLAT["Platform\n<i>interrupt routing</i>"]
  end

  CO --> PIO
  PIO --> BPIO
  PIO --> DMA
  DMA --> PCID
  PCID --> PCIE
  PCID --> PCIB
  HOST --> BUS
  PCIE --> NIC
  BPIO --> IDEC
  PLAT --> HOST
  DMA -.->|"DmaPort"| MEMBUS["Memory Bus"]
  PIO -.->|"PioPort"| MEMBUS
  NIC --> ELINK
  ELINK --> EBUS
  IDEC --> IDED
  IDED --> DIMG
  VDB --> VQ
  VDB --> VBK
  VDB --> VCN

Data Flow

Devices communicate with the CPU and memory through two fundamental mechanisms: Programmed I/O (PIO) and Direct Memory Access (DMA).

sequenceDiagram
    participant CPU as CPU Core
    participant BUS as Memory Bus
    participant NIC as NIC Device
    participant DMAPORT as DMA Port
    participant RAM as System Memory

    Note over CPU,RAM: PIO Read — CPU reads a device register
    CPU->>BUS: ReadReq (device MMIO addr)
    BUS->>NIC: PioPort.recvAtomic(pkt)
    NIC->>NIC: read(pkt) — decode register
    NIC-->>BUS: Response with data
    BUS-->>CPU: Data returned

    Note over CPU,RAM: DMA Write — Device writes to host memory
    NIC->>DMAPORT: dmaWrite(addr, size, data)
    DMAPORT->>DMAPORT: ChunkGenerator splits request
    DMAPORT->>BUS: WriteReq (chunk 1)
    BUS->>RAM: Store data
    RAM-->>BUS: WriteResp
    BUS-->>DMAPORT: Response
    DMAPORT->>BUS: WriteReq (chunk 2)
    BUS->>RAM: Store data
    RAM-->>DMAPORT: Response
    DMAPORT->>NIC: completionEvent fired

    Note over CPU,RAM: Interrupt — Device signals CPU
    NIC->>NIC: intrPost()
    NIC-->>CPU: Interrupt delivered via Platform

Narrated Walkthrough: Network Packet Reception

Follow the journey of an Ethernet frame arriving at a simulated NIC, being DMA'd to memory, and triggering an interrupt for the guest OS to process:

Packet arrives at EtherLink. The EtherLink::Link models a fixed-bandwidth wire. The packet is queued with a propagation delay calculated from ticksPerByte * pkt.length + linkDelay.
Network Device Models | gem5 Wiki" class="xref">EtherInt delivers to NIC. The EtherInt interface calls recvPacket() on the NIC model (e.g., IGbE or NsGigE). The NIC stores the packet in an internal FIFO.
NIC checks receive descriptor ring. The NIC reads the guest OS's receive descriptor ring from memory via DMA to find the next available buffer address.
DMA read of descriptor. DmaPort::dmaAction(ReadReq, descAddr, ...) issues a memory read. The ChunkGenerator splits the request into Cache Hierarchy | gem5 Wiki" href="../mem_doc/cache/index.html">cache-line-sized chunks.
Descriptor parsed. The NIC decodes the descriptor to obtain the host memory buffer address and length where the packet data should be placed.
DMA write of packet data. dmaWrite(bufferAddr, pkt.length, data) initiates a DMA transfer. Each chunk travels through the memory bus to DRAM.
Completion event fires. When all DMA chunks are acknowledged, the completionEvent fires, telling the NIC the transfer is done.
NIC updates descriptor status. The NIC writes back the descriptor status (packet length, checksum flags) to the descriptor ring via another DMA write.
Interrupt posted. The NIC calls intrPost() which routes through the PCI host and Platform to deliver an interrupt to the CPU model.
Guest OS processes interrupt. The CPU's interrupt handler runs the NIC driver, which reads the completed descriptor, passes the packet up the network stack, and replenishes the receive ring.

Key Components

ClassHeaderRole
PioDevicedev/io_device.hhBase class for all programmed I/O devices; provides PioPort
BasicPioDevicedev/io_device.hhSimplified PioDevice with fixed address and size parameters
DmaDevicedev/dma_device.hhExtends PioDevice with DmaPort for DMA read/write capability
DmaPortdev/dma_device.hhRequest port that manages chunked DMA transfers with completion events
DmaReadFifodev/dma_device.hhBuffered DMA engine helper with FIFO for streaming reads
Platformdev/platform.hhSystem-level I/O controller; routes PCI and console interrupts
PciDevicedev/pci/device.hhBase PCI device with config space, BARs, MSI/MSI-X support
PciHostdev/pci/host.hhPCI host bridge; maps config/IO/memory spaces and routes interrupts
PciBusdev/pci/bus.hhNon-coherent crossbar implementing PCI bus topology
EtherLinkdev/net/etherlink.hhFixed-bandwidth full-duplex Ethernet link model
NsGigEdev/net/ns_gige.hhNational Semiconductor DP83820 Gigabit Ethernet NIC model
IGbEdev/net/i8254xGBe.hhIntel 8254x Gigabit Ethernet NIC model
IdeDiskdev/storage/ide_disk.hhIDE disk device with PIO/DMA transfer modes and state machine
IdeControllerdev/storage/ide_ctrl.hhIDE controller managing up to two disk channels
VirtIODeviceBasedev/virtio/base.hhBase class for VirtIO paravirtualized devices with VirtQueue support

Sub-Module Deep Dives

Core Device Infrastructure

pci

PCI Bus and Device Framework

Complete PCI subsystem: host bridge with CAM/ECAM config space, PCI bus crossbar, BAR management (IO/Memory/64-bit), MSI/MSI-X interrupts, and the PciEndpoint/PciType1Device hierarchy for endpoint and bridge devices.

17 filesPciDevicePciHostPciBus

net

Network Device Models

Ethernet simulation layer: NIC models (NsGigE, IGbE, Sinic), link/bus/switch topologies, packet FIFOs, distributed simulation interfaces, and EtherDump packet capture. Supports both local and multi-process simulation.

31 files3 NIC modelsEtherLinkEtherSwitch

storage

Storage Device Models

IDE disk controller and disk models with full ATA command set, PIO/DMA transfer modes, and disk image backends (raw and copy-on-write). Provides block-level storage for full-system simulation.

14 filesIdeDiskIdeControllerDiskImage

virtio

VirtIO Device Framework

Paravirtualized device framework using VirtQueues for efficient guest-host communication. Includes block device, serial console, RNG, and 9P filesystem sharing — all usable with standard VirtIO guest drivers.

17 filesVirtIODeviceBaseVirtQueue5 device types

Architecture-Specific Devices

arm

ARM-specific devices: GIC (Generic Interrupt Controller) v2/v3/v4, GPU (NoMali), timers, SMMU v3, AMBA bus, HDLcd display, RealView/VExpress platforms, flash memory, energy controllers.

80+ filesGICv2/v3/v4SMMUv3

x86

x86 platform devices: i8254 PIT, i8259 PIC, i82094 IOAPIC, ACPI PM timer, SMBios, Intel 8237 DMA, i8042 keyboard controller, speaker, CMOS, South/North bridge stubs.

30+ filesAPICIOAPIC

riscv

RISC-V devices: PLIC (Platform Level Interrupt Controller), CLINT (Core Local Interruptor), HiFive platform, RTC.

12 filesPLICCLINT

serial

UART and terminal models: UART8250 (16550A-compatible), Atomic and Timing Simple CPUs — gem5 Wiki" href="../cpu_doc/simple/index.html">simple UART, terminal emulation for console I/O.

10 filesUart8250Terminal

Other Sub-Modules

amdgpu

AMD GPU device models for HSA and ROCm support.

hsa

HSA (Heterogeneous System Architecture) packet processor and signal handling.

i2c

I2C bus and device models for low-speed peripheral communication.

lupio

LupIO educational devices for RISC-V: timer, PIC, block, console, RNG, IPI, TTY, system.

mips

MIPS-specific platform devices: Malta board, interrupt controller.

sparc

SPARC T1000 platform: IOB, DTOD, memory-mapped disk.

ps2

PS/2 keyboard and mouse interface models.

qemu

QEMU firmware configuration (fw_cfg) device for passing boot parameters.

Directory Map

Source tree
src/dev/
├── io_device.hh/cc         ← PioDevice, BasicPioDevice, PioPort
├── dma_device.hh/cc        ← DmaDevice, DmaPort, DmaReadFifo, DmaCallback
├── platform.hh/cc          ← Platform base — interrupt routing
├── baddev.hh/cc            ← BadDevice — catches invalid accesses
├── isa_fake.hh/cc          ← IsaFake — stub device for unmapped ranges
├── intel_8254_timer.hh/cc  ← Intel 8254 PIT timer model
├── mc146818.hh/cc          ← MC146818 RTC (real-time clock) model
├── pixelpump.hh/cc         ← Pixel pump for display timing
├── reg_bank.hh             ← Register bank template for device registers
├── intpin.hh               ← Interrupt pin interface
├── pci/                    ← PCI host, bus, device, BARs, copy engine
├── net/                    ← Ethernet NICs, links, switches, dist. sim
├── storage/                ← IDE controller, disk, disk images
├── virtio/                 ← VirtIO base, block, console, RNG, 9P
├── arm/                    ← ARM GIC, SMMU, timers, AMBA, platforms
├── x86/                    ← x86 PIC, PIT, IOAPIC, ACPI devices
├── riscv/                  ← RISC-V PLIC, CLINT, HiFive board
├── serial/                 ← UART, terminal models
├── amdgpu/                 ← AMD GPU device models
├── hsa/                    ← HSA packet processor
├── i2c/                    ← I2C bus and device
├── lupio/                  ← LupIO educational RISC-V devices
├── mips/                   ← MIPS Malta platform
├── sparc/                  ← SPARC T1000 platform
├── ps2/                    ← PS/2 keyboard and mouse
└── qemu/                   ← QEMU fw_cfg device

Configuration Reference

ParameterPython ClassDefaultDescription
pio_addrBasicPioDevice0x0Base address for the device's PIO range in physical memory
pio_latencyBasicPioDevice'100ns'Latency for PIO accesses to the device
systemPioDevice—Reference to the System object (required for all devices)
pci_busPciDevice0PCI bus number
pci_devPciDevice0PCI device number
pci_funcPciDevice0PCI function number
InterruptLinePciDevice0x1fPCI interrupt line (legacy INTx)
speedEtherLink'1Gbps'Link bandwidth
delayEtherLink'0us'Propagation delay
imageIdeDisk—DiskImage object backing the IDE disk

Cross-Module Connections

flowchart TD
  subgraph dev["dev Module"]
    PIO["PioDevice"]
    DMA["DmaDevice"]
    PLAT["Platform"]
  end
  subgraph mem["mem Module"]
    MBUS["MemBus / CoherentXBar"]
    PORT["Port (Request/Response)"]
    DRAM["DRAM Controller"]
  end
  subgraph cpu["cpu Module"]
    CPUCORE["CPU Core"]
    INT["Interrupt Handler"]
  end
  subgraph sim["sim Module"]
    SYS["System"]
    EVTQ["EventQueue"]
  end

  PIO -->|"PioPort"| PORT
  DMA -->|"DmaPort"| PORT
  PORT --> MBUS
  MBUS --> DRAM
  PLAT -->|"postInt / clearInt"| INT
  INT --> CPUCORE
  SYS -->|"owns"| PIO
  SYS -->|"owns"| DMA
  EVTQ -->|"schedules"| DMA
Key insight: The dev module depends on mem for its port infrastructure (SimpleTimingPort, RequestPort), on sim for ClockedObject and event scheduling, and on cpu/arch for interrupt delivery. Device models never directly access CPU state — all communication is through the memory bus and interrupt lines.

Glossary

TermDefinition
PIOProgrammed I/O — CPU directly reads/writes device registers via memory-mapped addresses
DMADirect Memory Access — device reads/writes system memory without CPU intervention
BARBase Address Register — PCI config space register that maps a device's memory/IO region
MSI/MSI-XMessage Signaled Interrupts — PCI interrupt mechanism using memory writes instead of dedicated lines
VirtQueueShared memory ring buffer used by VirtIO for guest-host data exchange
MMIOMemory-Mapped I/O — device registers accessible at physical memory addresses
ECAMEnhanced Configuration Access Mechanism — PCIe standard for config space addressing